diff --git a/src/filo/Config b/src/filo/Config deleted file mode 100644 index 9f39b3d9..00000000 --- a/src/filo/Config +++ /dev/null @@ -1,68 +0,0 @@ -# !!! NOTE !!! -# Do NOT add spaces or comments at the end of option lines. -# It confuses some versions of make. - -# Image filename for automatic boot and optional command line parameter -#AUTOBOOT_FILE = "hda3:/boot/vmlinuz root=/dev/hda3 console=tty0 console=ttyS0,115200" -AUTOBOOT_FILE = "hda2:/boot/vmlinuz initrd=/boot/initrd pci=noacpi ro root=/dev/hda2 console=tty0 console=ttyS0,115200" -#AUTOBOOT_FILE = "mem@0xfff80000" -#AUTOBOOT_FILE = "hde1@0" -#AUTOBOOT_FILE = "uda1:/ram0_2.5_2.6.5_k8.2_mydisk7.elf" -#AUTOBOOT_FILE = "hda5:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hda7 console=tty0 console=ttyS0,115200" - -# Time in second before booting AUTOBOOT_FILE -AUTOBOOT_DELAY = 2 - -# Driver for hard disk, CompactFlash, and CD-ROM on IDE bus -IDE_DISK = 1 - -# Driver for USB disk -USB_DISK = 1 - -# Filesystems -# To make filo.zelf < 32 k, You may not enable JFS, MINIX, XFS -# Is anyone still using these file system? BY LYH -FSYS_EXT2FS = 1 -FSYS_FAT = 1 -#FSYS_JFS = 1 -#FSYS_MINIX = 1 -FSYS_REISERFS = 1 -#FSYS_XFS = 1 -FSYS_ISO9660 = 1 - -# Support for boot disk image in bootable CD-ROM (El Torito) -ELTORITO = 1 - -# PCI support -SUPPORT_PCI = 1 - - -# Debugging -#DEBUG_ALL = 1 -#DEBUG_ELFBOOT = 1 -#DEBUG_ELFNOTE = 1 -#DEBUG_LINUXBIOS = 1 -#DEBUG_MALLOC = 1 -#DEBUG_MULTIBOOT = 1 -#DEBUG_SEGMENT = 1 -#DEBUG_SYS_INFO = 1 -#DEBUG_TIMER = 1 -#DEBUG_BLOCKDEV = 1 -#DEBUG_PCI = 1 -#DEBUG_LINUXLOAD = 1 -#DEBUG_IDE = 1 -#DEBUG_USB = 1 -#DEBUG_ELTORITO = 1 - -# i386 options - -# Loader for standard Linux kernel image, a.k.a. /vmlinuz -LINUX_LOADER = 1 - -# Boot FILO from Multiboot loader (eg. GRUB) -# You need to modify i386/multiboot.c to use it. change mmrange to e820entries. -# By LYH -#MULTIBOOT_IMAGE = 1 - -# Use PCI Configuration Mechanism #1 (most boards) -PCI_CONFIG_1 = 1 diff --git a/src/filo/README.filo b/src/filo/README.filo deleted file mode 100644 index 1e801d31..00000000 --- a/src/filo/README.filo +++ /dev/null @@ -1,125 +0,0 @@ -This is FILO, a bootloader which loads boot images from local filesystem, -without help from legacy BIOS services. - -Expected usage is to flash it into the BIOS ROM together with LinuxBIOS. - -FEATURES - - - Supported boot devices: IDE hard disk and CD-ROM, and system memory (ROM) - - Supported filesystems: ext2, fat, jfs, minix, reiserfs, xfs, and iso9660 - - Supported image formats: ELF and [b]zImage (a.k.a. /vmlinuz) - - Supports boot disk image of El Torito bootable CD-ROM - - Supports loading image from raw device with user-specified offset - - Console on VGA + keyboard, serial port, or both - - Line editing with ^H, ^W and ^U keys to type arbitrary filename to boot - - Full support for the ELF Boot Proposal (where is it btw, Eric?) - - Auxiliary tool to compute checksum of ELF boot images - - Full 32-bit code, no BIOS calls - -REQUIREMENT - - Only i386 PC architecture is currently supported. - - x86-64 (AMD 64) machines in 32-bit mode should also work. - (It looks like LinuxBIOS uses 32-bit mode and Linux kernel does - the transition to 64-bit mode) - - I'm using a VIA EPIA 5000 mini-ITX board, with a 2.5" IDE hard disk - and a 32x CD-RW, for testing, and Bochs and VMware for development. - - Recent version of GNU toolchain is required to build. - I have tested with Debian/woody (gcc 2.95.4, binutils 2.12.90.0.1, - make 3.79.1) and Debian/sid (gcc 3.3.2, binutils 2.14.90.0.6, - make 3.80). - -INSTALL - - First invocation of make creates the default Config file. - $ make - Edit this file as you like. It's fairly straightforward (I hope). - $ vi Config - Then running make again will build filo.elf, the ELF boot image of FILO. - $ make - - Use filo.elf as your payload of LinuxBIOS, or a boot image for - Etherboot. - - If you enable MULTIBOOT_IMAGE option in Config, you can - also boot filo.elf from GNU GRUB or other Multiboot bootloader. - This feature is intended for testing or development purpose. - -USING - - When FILO starts, it displays "boot:" prompt. - At "boot:" prompt, type the name of your boot image, and optionally - the kernel parameter, in the form: - DEVICE:FILENAME[ PARAM] - for example: - boot: hda1:/vmlinuz root=/dev/hda1 - - Notation of DEVICE for IDE disk and CD-ROM is same as in Linux - (eg. hda1 means the first partition of master device on primary - IDE channel). - - FILENAME can be standard bzImage/zImage (vmlinuz) Linux kernels, - Linux-compatible images such as memtest.bin of Memtest86, - and any bootable ELF images, which include Linux kernel converted - by mkelfImage, Etherboot .elf and .zelf, Memtest86, FILO itself, etc. - - If AUTOBOOT_FILE is set in Config, FILO tries to boot this file - first, and falls back to boot: prompt if it fails. - - If AUTOBOOT_DELAY is also set, FILO waits for specified time in - seconds before booting AUTOBOOT_FILE. If key is pressed - during this time period, automatic boot is canceled. - Pressing key also cancels the delay, but in this case - AUTOBOOT_FILE is booted immediately. - - Even if AUTOBOOT_DELAY is not set, automatic boot can be disabled - by pressing key beforehand. - - FILO can also load separate initrd images along with vmlinuz - kernels. (For ELF kernel, initrd images are embedded into the - ELF file and cannot be altered). - To do so, add "initrd=NAME" parameter to the kernel command line. - NAME uses the same notation as kernel image name. - (eg. boot: hda1:/vmlinuz initrd=hda1:/root.gz root=/dev/ram) - - To boot an image in the BIOS flash (or whatever is mapped in the system - memory space), use the notation "mem@OFFSET[,LENGTH]", like: - boot: mem@0xfffe0000 - In this example, it loads the boot image from the last 128KB of BIOS - flash. - - The same notation can be used with IDE devices, eg: - boot: hda@512,697344 initrd=hda@1M,4M - In this case the 697344 bytes starting from second sector of IDE drive - is loaded as kernel, and 4M bytes of offset 1M bytes of the same disk - is loaded as initrd. - Note that when you load vmlinuz kernel or initrd this way, - you must specify the LENGTH parameter. You can omit it for ELF - images since they have segment length internally. - OFFSET and LENGTH parameters must be multiple of 512. - -BUG REPORTING - - If you have problem with FILO, set DEBUG_ALL in Config and send its - console output to me at . - -ACKNOWLEDGEMENTS - - Filesystem code is taken from GNU GRUB and patches for it. - IDE driver is originally taken from Etherboot. - Steve Gehlbach wrote the original bzImage loader for FILO. - - Besides, I have taken pieces of code and/or learned concepts - from various standalone programs, including GNU GRUB, Etherboot, - polled IDE patch by Adam Agnew, Memtest86, LinuxBIOS, and Linux. - I must say thanks to all the developers of these wonderful software, - especially to Eric Biederman for his great development work in this area. - -LICENSE - - Copyright (C) 2003 by SONE Takeshi and others. - This program is licensed under the terms of GNU General Public License. - See the COPYING file for details. diff --git a/src/filo/README.filo_in_etherboot b/src/filo/README.filo_in_etherboot deleted file mode 100644 index dc203f63..00000000 --- a/src/filo/README.filo_in_etherboot +++ /dev/null @@ -1,48 +0,0 @@ -Moved from FILO into Etherboot, yhlu add boot from SATA disk and move usb boot framework -from Steven James baremetal in LinuxBIOS, also add the OHCI support. - - -1. refer to README.filo - but don't need to use make config. -2. CFLAG added - CONSOLE_BTEXT --- for btext console support - CONSOLE_PC_KBD --- for direct pc keyboard support - CONFIG_FILO --- It will make main call pci_init -3. to make: - make bin/filo.zelf - or - make bin/tg3--filo.zelf - - You can not use filo and ide_disk at the same time. - -Some input for boot: - -boot from BIOS ROM area -4G-128K -mem@0xfffe0000 -4G-512K -mem@0xfff80000 - -boot from suse -hda2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hda2 console=tty0 console=ttyS0,115200 -for suse install from CD -hdc:/boot/loader/linux initrd=/boot/loader/initrd ramdisk_size=65536 splash=silent showopts console=tty0 console=ttyS0,115200 - -boot from RH -for RH install from CD -hdc:/isolinux/vmlinuz initrd=/isolinux/initrd.img expert nofb acpi=off devfs=nomount ramdisk_size=65536 console=ttyS0,115200 - -for serial ATA support (using port1 and port2 only) -1) if your kernel think SATA as SCSI -hde2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/sda2 console=tty0 console=ttyS0,115200 -2) if your kernel think SATA as normal IDE -hde2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hde2 console=tty0 console=ttyS0,115200 - -for usb support -uda1:/ram0_2.5_2.6.5_k8.2_mydisk7.elf - - -Yinghai Lu yhlu@tyan.com - -to do: - add menu to filo boot diff --git a/src/filo/README.usb b/src/filo/README.usb deleted file mode 100644 index 1724e7bb..00000000 --- a/src/filo/README.usb +++ /dev/null @@ -1,15 +0,0 @@ -It is from steven james's baremetal in linuxbios util. -yhlu seperate common functions from uhci.c to usb.c and create ohci.c to support ohci. -ohci.c mainly cames from kernel 2.4.22 dirvers/usb/host/usb-ohci.c. -it includes several parts -1. UHCI+OHCI--->USB: privide usb init and usb_control_msg and usb_bulk_msg interface -2. USB_SCSI: bulk only device -3. USB_X interface to FILO - -other changes in Etherboot -1. Add allot2 and forget2, it will produce the required aligned memory. - -todo: -1. EHCI support - -yhlu 6/2/2004 diff --git a/src/filo/drivers/ide_x.c b/src/filo/drivers/ide_x.c deleted file mode 100644 index 09c634e2..00000000 --- a/src/filo/drivers/ide_x.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* Derived from Etherboot 5.1 */ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_IDE -#include - -#define IDE_MAX_CONTROLLERS 4 -#define IDE_MAX_DRIVES (IDE_MAX_CONTROLLERS * 2) - -#define BSY_SET_DURING_SPINUP 1 -/* - * UBL, The Universal Talkware Boot Loader - * Copyright (C) 2000 Universal Talkware Inc. - * Copyright (C) 2002 Eric Biederman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ -struct controller { - uint16_t cmd_base; - uint16_t ctrl_base; -}; - -struct harddisk_info { - struct controller *ctrl; - uint16_t heads; - uint16_t cylinders; - uint16_t sectors_per_track; - uint8_t model_number[41]; - uint8_t slave; - sector_t sectors; - int address_mode; -#define ADDRESS_MODE_CHS 0 -#define ADDRESS_MODE_LBA 1 -#define ADDRESS_MODE_LBA48 2 -#define ADDRESS_MODE_PACKET 3 - uint32_t hw_sector_size; - unsigned drive_exists : 1; - unsigned slave_absent : 1; - unsigned removable : 1; -}; - -#define IDE_SECTOR_SIZE 0x200 -#define CDROM_SECTOR_SIZE 0x800 - -#define IDE_BASE0 (0x1F0u) /* primary controller */ -#define IDE_BASE1 (0x170u) /* secondary */ -#define IDE_BASE2 (0x1E8u) /* third */ -#define IDE_BASE3 (0x168u) /* fourth */ -#define IDE_BASE4 (0x1E0u) /* fifth */ -#define IDE_BASE5 (0x160u) /* sixth */ - -#define IDE_REG_EXTENDED_OFFSET (0x204u) - -#define IDE_REG_DATA(ctrl) ((ctrl)->cmd_base + 0u) /* word register */ -#define IDE_REG_ERROR(ctrl) ((ctrl)->cmd_base + 1u) -#define IDE_REG_PRECOMP(ctrl) ((ctrl)->cmd_base + 1u) -#define IDE_REG_FEATURE(ctrl) ((ctrl)->cmd_base + 1u) -#define IDE_REG_SECTOR_COUNT(ctrl) ((ctrl)->cmd_base + 2u) -#define IDE_REG_SECTOR_NUMBER(ctrl) ((ctrl)->cmd_base + 3u) -#define IDE_REG_LBA_LOW(ctrl) ((ctrl)->cmd_base + 3u) -#define IDE_REG_CYLINDER_LSB(ctrl) ((ctrl)->cmd_base + 4u) -#define IDE_REG_LBA_MID(ctrl) ((ctrl)->cmd_base + 4u) -#define IDE_REG_CYLINDER_MSB(ctrl) ((ctrl)->cmd_base + 5u) -#define IDE_REG_LBA_HIGH(ctrl) ((ctrl)->cmd_base + 5u) -#define IDE_REG_DRIVEHEAD(ctrl) ((ctrl)->cmd_base + 6u) -#define IDE_REG_DEVICE(ctrl) ((ctrl)->cmd_base + 6u) -#define IDE_REG_STATUS(ctrl) ((ctrl)->cmd_base + 7u) -#define IDE_REG_COMMAND(ctrl) ((ctrl)->cmd_base + 7u) -#define IDE_REG_ALTSTATUS(ctrl) ((ctrl)->ctrl_base + 2u) -#define IDE_REG_DEVICE_CONTROL(ctrl) ((ctrl)->ctrl_base + 2u) - -struct ide_pio_command -{ - uint8_t feature; - uint8_t sector_count; - uint8_t lba_low; - uint8_t lba_mid; - uint8_t lba_high; - uint8_t device; -# define IDE_DH_DEFAULT (0xA0) -# define IDE_DH_HEAD(x) ((x) & 0x0F) -# define IDE_DH_MASTER (0x00) -# define IDE_DH_SLAVE (0x10) -# define IDE_DH_LBA (0x40) -# define IDE_DH_CHS (0x00) - uint8_t command; - uint8_t sector_count2; - uint8_t lba_low2; - uint8_t lba_mid2; - uint8_t lba_high2; -}; - -#define IDE_DEFAULT_COMMAND { 0xFFu, 0x01, 0x00, 0x0000, IDE_DH_DEFAULT } - -#define IDE_ERR_ICRC 0x80 /* ATA Ultra DMA bad CRC */ -#define IDE_ERR_BBK 0x80 /* ATA bad block */ -#define IDE_ERR_UNC 0x40 /* ATA uncorrected error */ -#define IDE_ERR_MC 0x20 /* ATA media change */ -#define IDE_ERR_IDNF 0x10 /* ATA id not found */ -#define IDE_ERR_MCR 0x08 /* ATA media change request */ -#define IDE_ERR_ABRT 0x04 /* ATA command aborted */ -#define IDE_ERR_NTK0 0x02 /* ATA track 0 not found */ -#define IDE_ERR_NDAM 0x01 /* ATA address mark not found */ - -#define IDE_STATUS_BSY 0x80 /* busy */ -#define IDE_STATUS_RDY 0x40 /* ready */ -#define IDE_STATUS_DF 0x20 /* device fault */ -#define IDE_STATUS_WFT 0x20 /* write fault (old name) */ -#define IDE_STATUS_SKC 0x10 /* seek complete */ -#define IDE_STATUS_DRQ 0x08 /* data request */ -#define IDE_STATUS_CORR 0x04 /* corrected */ -#define IDE_STATUS_IDX 0x02 /* index */ -#define IDE_STATUS_ERR 0x01 /* error (ATA) */ -#define IDE_STATUS_CHK 0x01 /* check (ATAPI) */ - -#define IDE_CTRL_HD15 0x08 /* bit should always be set to one */ -#define IDE_CTRL_SRST 0x04 /* soft reset */ -#define IDE_CTRL_NIEN 0x02 /* disable interrupts */ - - -/* Most mandtory and optional ATA commands (from ATA-3), */ - -#define IDE_CMD_CFA_ERASE_SECTORS 0xC0 -#define IDE_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 -#define IDE_CMD_CFA_TRANSLATE_SECTOR 0x87 -#define IDE_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD -#define IDE_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 -#define IDE_CMD_CHECK_POWER_MODE1 0xE5 -#define IDE_CMD_CHECK_POWER_MODE2 0x98 -#define IDE_CMD_DEVICE_RESET 0x08 -#define IDE_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 -#define IDE_CMD_FLUSH_CACHE 0xE7 -#define IDE_CMD_FORMAT_TRACK 0x50 -#define IDE_CMD_IDENTIFY_DEVICE 0xEC -#define IDE_CMD_IDENTIFY_DEVICE_PACKET 0xA1 -#define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1 -#define IDE_CMD_IDLE1 0xE3 -#define IDE_CMD_IDLE2 0x97 -#define IDE_CMD_IDLE_IMMEDIATE1 0xE1 -#define IDE_CMD_IDLE_IMMEDIATE2 0x95 -#define IDE_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91 -#define IDE_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 -#define IDE_CMD_NOP 0x00 -#define IDE_CMD_PACKET 0xA0 -#define IDE_CMD_READ_BUFFER 0xE4 -#define IDE_CMD_READ_DMA 0xC8 -#define IDE_CMD_READ_DMA_QUEUED 0xC7 -#define IDE_CMD_READ_MULTIPLE 0xC4 -#define IDE_CMD_READ_SECTORS 0x20 -#define IDE_CMD_READ_SECTORS_EXT 0x24 -#define IDE_CMD_READ_VERIFY_SECTORS 0x40 -#define IDE_CMD_RECALIBRATE 0x10 -#define IDE_CMD_SEEK 0x70 -#define IDE_CMD_SET_FEATURES 0xEF -#define IDE_CMD_SET_MAX_ADDR_EXT 0x24 -#define IDE_CMD_SET_MULTIPLE_MODE 0xC6 -#define IDE_CMD_SLEEP1 0xE6 -#define IDE_CMD_SLEEP2 0x99 -#define IDE_CMD_STANDBY1 0xE2 -#define IDE_CMD_STANDBY2 0x96 -#define IDE_CMD_STANDBY_IMMEDIATE1 0xE0 -#define IDE_CMD_STANDBY_IMMEDIATE2 0x94 -#define IDE_CMD_WRITE_BUFFER 0xE8 -#define IDE_CMD_WRITE_DMA 0xCA -#define IDE_CMD_WRITE_DMA_QUEUED 0xCC -#define IDE_CMD_WRITE_MULTIPLE 0xC5 -#define IDE_CMD_WRITE_SECTORS 0x30 -#define IDE_CMD_WRITE_VERIFY 0x3C - -/* IDE_CMD_SET_FEATURE sub commands */ -#define IDE_FEATURE_CFA_ENABLE_8BIT_PIO 0x01 -#define IDE_FEATURE_ENABLE_WRITE_CACHE 0x02 -#define IDE_FEATURE_SET_TRANSFER_MODE 0x03 -#define IDE_FEATURE_ENABLE_POWER_MANAGEMENT 0x05 -#define IDE_FEATURE_ENABLE_POWERUP_IN_STANDBY 0x06 -#define IDE_FEATURE_STANDBY_SPINUP_DRIVE 0x07 -#define IDE_FEATURE_CFA_ENABLE_POWER_MODE1 0x0A -#define IDE_FEATURE_DISABLE_MEDIA_STATUS_NOTIFICATION 0x31 -#define IDE_FEATURE_ENABLE_AUTOMATIC_ACOUSTIC_MANAGEMENT 0x42 -#define IDE_FEATURE_SET_MAXIMUM_HOST_INTERFACE_SECTOR_TIMES 0x43 -#define IDE_FEATURE_DISABLE_READ_LOOKAHEAD 0x55 -#define IDE_FEATURE_ENABLE_RELEASE_INTERRUPT 0x5D -#define IDE_FEATURE_ENABLE_SERVICE_INTERRUPT 0x5E -#define IDE_FEATURE_DISABLE_REVERTING_TO_POWERON_DEFAULTS 0x66 -#define IDE_FEATURE_CFA_DISABLE_8BIT_PIO 0x81 -#define IDE_FEATURE_DISABLE_WRITE_CACHE 0x82 -#define IDE_FEATURE_DISABLE_POWER_MANAGEMENT 0x85 -#define IDE_FEATURE_DISABLE_POWERUP_IN_STANDBY 0x86 -#define IDE_FEATURE_CFA_DISABLE_POWER_MODE1 0x8A -#define IDE_FEATURE_ENABLE_MEDIA_STATUS_NOTIFICATION 0x95 -#define IDE_FEATURE_ENABLE_READ_LOOKAHEAD 0xAA -#define IDE_FEATURE_DISABLE_AUTOMATIC_ACOUSTIC_MANAGEMENT 0xC2 -#define IDE_FEATURE_ENABLE_REVERTING_TO_POWERON_DEFAULTS 0xCC -#define IDE_FEATURE_DISABLE_SERVICE_INTERRUPT 0xDE - -static unsigned short ide_base[] = { - IDE_BASE0, - IDE_BASE1, - IDE_BASE2, - IDE_BASE3, - 0 -}; - -static struct controller controllers[IDE_MAX_CONTROLLERS]; -static struct harddisk_info harddisk_info[IDE_MAX_DRIVES]; - -static unsigned char ide_buffer[IDE_SECTOR_SIZE]; - -static int await_ide(int (*done)(struct controller *ctrl), - struct controller *ctrl, unsigned long timeout) -{ - int result; - for(;;) { - result = done(ctrl); - if (result) { - return 0; - } - //poll_interruptions(); - if ((timeout == 0) || (currticks() > timeout)) { - break; - } - } - printf("IDE time out\n"); - return -1; -} - -/* The maximum time any IDE command can last 31 seconds, - * So if any IDE commands takes this long we know we have problems. - */ -#define IDE_TIMEOUT (32*TICKS_PER_SEC) - -static int not_bsy(struct controller *ctrl) -{ - return !(inb(IDE_REG_STATUS(ctrl)) & IDE_STATUS_BSY); -} - -/* IDE drives assert BSY bit within 400 nsec when SRST is set. - * Use 2 msec since our tick is 1 msec */ -#define IDE_RESET_PULSE (2*TICKS_PER_SEC / 18) - -static int bsy(struct controller *ctrl) -{ - return inb(IDE_REG_STATUS(ctrl)) & IDE_STATUS_BSY; -} - -#if !BSY_SET_DURING_SPINUP -static int timeout(struct controller *ctrl) -{ - return 0; -} -#endif - -static void print_status(struct controller *ctrl) -{ - debug("IDE: status=%#x, err=%#x\n", - inb(IDE_REG_STATUS(ctrl)), inb(IDE_REG_ERROR(ctrl))); -} - -static int ide_software_reset(struct controller *ctrl) -{ - /* Wait a little bit in case this is immediately after - * hardware reset. - */ - mdelay(2); - /* A software reset should not be delivered while the bsy bit - * is set. If the bsy bit does not clear in a reasonable - * amount of time give up. - */ - debug("Waiting for ide%d to become ready for reset... ", - ctrl - controllers); - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - debug("failed\n"); - return -1; - } - debug("ok\n"); - - /* Disable Interrupts and reset the ide bus */ - outb(IDE_CTRL_HD15 | IDE_CTRL_SRST | IDE_CTRL_NIEN, - IDE_REG_DEVICE_CONTROL(ctrl)); - /* If BSY bit is not asserted within 400ns, no device there */ - if (await_ide(bsy, ctrl, currticks() + IDE_RESET_PULSE) < 0) { - return -1; - } - outb(IDE_CTRL_HD15 | IDE_CTRL_NIEN, IDE_REG_DEVICE_CONTROL(ctrl)); - mdelay(2); - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - return 0; -} - -static void pio_set_registers( - struct controller *ctrl, const struct ide_pio_command *cmd) -{ - uint8_t device; - /* Disable Interrupts */ - outb(IDE_CTRL_HD15 | IDE_CTRL_NIEN, IDE_REG_DEVICE_CONTROL(ctrl)); - - /* Possibly switch selected device */ - device = inb(IDE_REG_DEVICE(ctrl)); - outb(cmd->device, IDE_REG_DEVICE(ctrl)); - if ((device & (1UL << 4)) != (cmd->device & (1UL << 4))) { - /* Allow time for the selected drive to switch, - * The linux ide code suggests 50ms is the right - * amount of time to use here. - */ - mdelay(50); - } - outb(cmd->feature, IDE_REG_FEATURE(ctrl)); - if (cmd->command == IDE_CMD_READ_SECTORS_EXT) { - outb(cmd->sector_count2, IDE_REG_SECTOR_COUNT(ctrl)); - outb(cmd->lba_low2, IDE_REG_LBA_LOW(ctrl)); - outb(cmd->lba_mid2, IDE_REG_LBA_MID(ctrl)); - outb(cmd->lba_high2, IDE_REG_LBA_HIGH(ctrl)); - } - outb(cmd->sector_count, IDE_REG_SECTOR_COUNT(ctrl)); - outb(cmd->lba_low, IDE_REG_LBA_LOW(ctrl)); - outb(cmd->lba_mid, IDE_REG_LBA_MID(ctrl)); - outb(cmd->lba_high, IDE_REG_LBA_HIGH(ctrl)); - outb(cmd->command, IDE_REG_COMMAND(ctrl)); -} - - -static int pio_non_data(struct controller *ctrl, const struct ide_pio_command *cmd) -{ - /* Wait until the busy bit is clear */ - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - - pio_set_registers(ctrl, cmd); - ndelay(400); - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - /* FIXME is there more error checking I could do here? */ - return 0; -} - -static int pio_data_in(struct controller *ctrl, const struct ide_pio_command *cmd, - void *buffer, size_t bytes) -{ - unsigned int status; - - /* FIXME handle commands with multiple blocks */ - /* Wait until the busy bit is clear */ - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - - /* How do I tell if INTRQ is asserted? */ - pio_set_registers(ctrl, cmd); - ndelay(400); - if (await_ide(not_bsy, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - status = inb(IDE_REG_STATUS(ctrl)); - if (!(status & IDE_STATUS_DRQ)) { - print_status(ctrl); - return -1; - } - insw(IDE_REG_DATA(ctrl), buffer, bytes/2); - status = inb(IDE_REG_STATUS(ctrl)); - if (status & IDE_STATUS_DRQ) { - print_status(ctrl); - return -1; - } - return 0; -} - -static int pio_packet(struct harddisk_info *info, int in, - const void *packet, int packet_len, - void *buffer, int buffer_len) -{ - unsigned int status; - struct ide_pio_command cmd; - - memset(&cmd, 0, sizeof(cmd)); - - /* Wait until the busy bit is clear */ - if (await_ide(not_bsy, info->ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - - /* Issue a PACKET command */ - cmd.lba_mid = (uint8_t) buffer_len; - cmd.lba_high = (uint8_t) (buffer_len >> 8); - cmd.device = IDE_DH_DEFAULT | info->slave; - cmd.command = IDE_CMD_PACKET; - pio_set_registers(info->ctrl, &cmd); - ndelay(400); - if (await_ide(not_bsy, info->ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - status = inb(IDE_REG_STATUS(info->ctrl)); - if (!(status & IDE_STATUS_DRQ)) { - debug("no drq after PACKET\n"); - print_status(info->ctrl); - return -1; - } - - /* Send the packet */ - outsw(IDE_REG_DATA(info->ctrl), packet, packet_len/2); - - if (await_ide(not_bsy, info->ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } - status = inb(IDE_REG_STATUS(info->ctrl)); - if (buffer_len == 0) { - if (status & IDE_STATUS_DRQ) { - debug("drq after non-data command\n"); - print_status(info->ctrl); - return -1; - } - return 0; - } - - if (!(status & IDE_STATUS_DRQ)) { - debug("no drq after sending packet\n"); - print_status(info->ctrl); - return -1; - } - - insw(IDE_REG_DATA(info->ctrl), buffer, buffer_len/2); - - status = inb(IDE_REG_STATUS(info->ctrl)); - if (status & IDE_STATUS_DRQ) { - debug("drq after insw\n"); - print_status(info->ctrl); - return -1; - } - return 0; -} - -static inline int ide_read_sector_chs( - struct harddisk_info *info, void *buffer, unsigned long sector) -{ - struct ide_pio_command cmd; - unsigned int track; - unsigned int offset; - unsigned int cylinder; - - memset(&cmd, 0, sizeof(cmd)); - cmd.sector_count = 1; - - //debug("ide_read_sector_chs: sector= %ld.\n",sector); - - track = sector / info->sectors_per_track; - /* Sector number */ - offset = 1 + (sector % info->sectors_per_track); - cylinder = track / info->heads; - cmd.lba_low = offset; - cmd.lba_mid = cylinder & 0xff; - cmd.lba_high = (cylinder >> 8) & 0xff; - cmd.device = IDE_DH_DEFAULT | - IDE_DH_HEAD(track % info->heads) | - info->slave | - IDE_DH_CHS; - cmd.command = IDE_CMD_READ_SECTORS; - return pio_data_in(info->ctrl, &cmd, buffer, IDE_SECTOR_SIZE); -} - -static inline int ide_read_sector_lba( - struct harddisk_info *info, void *buffer, unsigned long sector) -{ - struct ide_pio_command cmd; - memset(&cmd, 0, sizeof(cmd)); - - cmd.sector_count = 1; - cmd.lba_low = sector & 0xff; - cmd.lba_mid = (sector >> 8) & 0xff; - cmd.lba_high = (sector >> 16) & 0xff; - cmd.device = IDE_DH_DEFAULT | - ((sector >> 24) & 0x0f) | - info->slave | - IDE_DH_LBA; - cmd.command = IDE_CMD_READ_SECTORS; - //debug("%s: sector= %ld, device command= 0x%x.\n",__FUNCTION__,(unsigned long) sector, cmd.device); - return pio_data_in(info->ctrl, &cmd, buffer, IDE_SECTOR_SIZE); -} - -static inline int ide_read_sector_lba48( - struct harddisk_info *info, void *buffer, sector_t sector) -{ - struct ide_pio_command cmd; - memset(&cmd, 0, sizeof(cmd)); - //debug("ide_read_sector_lba48: sector= %ld.\n",(unsigned long) sector); - - cmd.sector_count = 1; - cmd.lba_low = sector & 0xff; - cmd.lba_mid = (sector >> 8) & 0xff; - cmd.lba_high = (sector >> 16) & 0xff; - cmd.lba_low2 = (sector >> 24) & 0xff; - cmd.lba_mid2 = (sector >> 32) & 0xff; - cmd.lba_high2 = (sector >> 40) & 0xff; - cmd.device = info->slave | IDE_DH_LBA; - cmd.command = IDE_CMD_READ_SECTORS_EXT; - return pio_data_in(info->ctrl, &cmd, buffer, IDE_SECTOR_SIZE); -} - -static inline int ide_read_sector_packet( - struct harddisk_info *info, void *buffer, sector_t sector) -{ - char packet[12]; - static uint8_t cdbuffer[CDROM_SECTOR_SIZE]; - static struct harddisk_info *last_disk = 0; - static sector_t last_sector = (sector_t) -1; - uint8_t *buf; - uint32_t hw_sector; - - //debug("sector=%Ld\n", sector); - - if (info->hw_sector_size == CDROM_SECTOR_SIZE) { - buf = cdbuffer; - hw_sector = sector >> 2; - } else { - buf = buffer; - hw_sector = sector; - } - - if (buf==buffer || info != last_disk || hw_sector != last_sector) { - //debug("hw_sector=%u\n", hw_sector); - memset(packet, 0, sizeof packet); - packet[0] = 0x28; /* READ */ - packet[2] = hw_sector >> 24; - packet[3] = hw_sector >> 16; - packet[4] = hw_sector >> 8; - packet[5] = hw_sector >> 0; - packet[7] = 0; - packet[8] = 1; /* length */ - - if (pio_packet(info, 1, packet, sizeof packet, - buf, info->hw_sector_size) != 0) { - debug("read error\n"); - return -1; - } - last_disk = info; - last_sector = hw_sector; - } - - if (buf != buffer) - memcpy(buffer, &cdbuffer[(sector & 3) << 9], IDE_SECTOR_SIZE); - return 0; -} - -int ide_read(int drive, sector_t sector, void *buffer) -{ - struct harddisk_info *info = &harddisk_info[drive]; - int result; - - //debug("drive=%d, sector=%ld\n",drive,(unsigned long) sector); - /* Report the buffer is empty */ - if (sector > info->sectors) { - return -1; - } - if (info->address_mode == ADDRESS_MODE_CHS) { - result = ide_read_sector_chs(info, buffer, sector); - } - else if (info->address_mode == ADDRESS_MODE_LBA) { - result = ide_read_sector_lba(info, buffer, sector); - } - else if (info->address_mode == ADDRESS_MODE_LBA48) { - result = ide_read_sector_lba48(info, buffer, sector); - } - else if (info->address_mode == ADDRESS_MODE_PACKET) { - result = ide_read_sector_packet(info, buffer, sector); - } - else { - result = -1; - } - return result; -} - -static int init_drive_x(struct harddisk_info *info, struct controller *ctrl, - int slave, int drive, unsigned char *buffer, int ident_command) -{ - uint16_t* drive_info; - struct ide_pio_command cmd; - int i; - - - info->ctrl = ctrl; - info->heads = 0u; - info->cylinders = 0u; - info->sectors_per_track = 0u; - info->address_mode = IDE_DH_CHS; - info->sectors = 0ul; - info->drive_exists = 0; - info->slave_absent = 0; - info->removable = 0; - info->hw_sector_size = IDE_SECTOR_SIZE; - info->slave = slave?IDE_DH_SLAVE: IDE_DH_MASTER; - - debug("Testing for hd%c\n", 'a'+drive); - - /* Select the drive that we are testing */ - outb(IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | info->slave, - IDE_REG_DEVICE(ctrl)); - mdelay(50); - - /* Test to see if the drive registers exist, - * In many cases this quickly rules out a missing drive. - */ - for(i = 0; i < 4; i++) { - outb(0xaa + i, (ctrl->cmd_base) + 2 + i); - } - for(i = 0; i < 4; i++) { - if (inb((ctrl->cmd_base) + 2 + i) != 0xaa + i) { - return 1; - } - } - for(i = 0; i < 4; i++) { - outb(0x55 + i, (ctrl->cmd_base) + 2 + i); - } - for(i = 0; i < 4; i++) { - if (inb((ctrl->cmd_base) + 2 + i) != 0x55 + i) { - return 1; - } - } - debug("Probing for hd%c\n", 'a'+drive); - - memset(&cmd, 0, sizeof(cmd)); - cmd.device = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | info->slave; - cmd.command = ident_command; - - - if (pio_data_in(ctrl, &cmd, buffer, IDE_SECTOR_SIZE) < 0) { - /* Well, if that command didn't work, we probably don't have drive. */ - return 1; - } - - /* Now suck the data out */ - drive_info = (uint16_t *)buffer; - if (drive_info[2] == 0x37C8) { - /* If the response is incomplete spin up the drive... */ - memset(&cmd, 0, sizeof(cmd)); - cmd.device = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | - info->slave; - cmd.feature = IDE_FEATURE_STANDBY_SPINUP_DRIVE; - if (pio_non_data(ctrl, &cmd) < 0) { - /* If the command doesn't work give up on the drive */ - return 1; - } - - } - if ((drive_info[2] == 0x37C8) || (drive_info[2] == 0x8C73)) { - /* The response is incomplete retry the drive info command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.device = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | - info->slave; - cmd.command = ident_command; - if(pio_data_in(ctrl, &cmd, buffer, IDE_SECTOR_SIZE) < 0) { - /* If the command didn't work give up on the drive. */ - return 1; - } - } - if ((drive_info[2] != 0x37C8) && - (drive_info[2] != 0x738C) && - (drive_info[2] != 0x8C73) && - (drive_info[2] != 0xC837) && - (drive_info[2] != 0x0000)) { - debugx("Invalid IDE Configuration: %hx\n", drive_info[2]); - return 1; - } - for(i = 27; i < 47; i++) { - info->model_number[((i-27)<< 1)] = (drive_info[i] >> 8) & 0xff; - info->model_number[((i-27)<< 1)+1] = drive_info[i] & 0xff; - } - info->model_number[40] = '\0'; - info->drive_exists = 1; - - /* See if LBA is supported */ - if (ident_command == IDE_CMD_IDENTIFY_PACKET_DEVICE) { - info->address_mode = ADDRESS_MODE_PACKET; - info->removable = 1; /* XXX */ - } else if (drive_info[49] & (1 << 9)) { - info->address_mode = ADDRESS_MODE_LBA; - info->sectors = (drive_info[61] << 16) | (drive_info[60]); -// debug("LBA mode, sectors=%Ld\n", info->sectors); - /* Enable LBA48 mode if it is present */ - if (drive_info[83] & (1 <<10)) { - /* Should LBA48 depend on LBA? */ - info->address_mode = ADDRESS_MODE_LBA48; - info->sectors = - (((sector_t)drive_info[103]) << 48) | - (((sector_t)drive_info[102]) << 32) | - (((sector_t)drive_info[101]) << 16) | - (((sector_t)drive_info[100]) << 0); -// debug("LBA48 mode, sectors=%Ld\n", info->sectors); - } - } else { - info->address_mode = ADDRESS_MODE_CHS; - info->heads = drive_info[3]; - info->cylinders = drive_info[1]; - info->sectors_per_track = drive_info[6]; - info->sectors = - info->sectors_per_track * - info->heads * - info->cylinders; - debug("CHS mode, sectors_per_track=[%d], heads=[%d], cylinders=[%d]\n", - info->sectors_per_track, - info->heads, - info->cylinders); -// debug("sectors=%Ld\n", info->sectors); - } - /* See if we have a slave */ - if (!info->slave && (((drive_info[93] >> 14) & 3) == 1)) { - info->slave_absent = !(drive_info[93] & (1 << 5)); - } - - /* See if we need to put the device in CFA power mode 1 */ - if ((drive_info[160] & ((1 << 15) | (1 << 13)| (1 << 12))) == - ((1 << 15) | (1 << 13)| (1 << 12))) { - memset(&cmd, 0, sizeof(cmd)); - cmd.device = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | info->slave; - cmd.feature = IDE_FEATURE_CFA_ENABLE_POWER_MODE1; - if (pio_non_data(ctrl, &cmd) < 0) { - /* If I need to power up the drive, and I can't - * give up. - */ - debugx("Cannot power up CFA device\n"); - return 1; - } - } - - /* Some extra steps for older drives.. */ - if (info->address_mode != ADDRESS_MODE_PACKET) { - /* Initialize drive parameters - * This is an obsolete command (disappeared as of ATA-6) - * but old drives need it before accessing media. */ - memset(&cmd, 0, sizeof(cmd)); - cmd.device = IDE_DH_DEFAULT | IDE_DH_HEAD(drive_info[3] - 1) - | info->slave; - cmd.sector_count = drive_info[6]; - cmd.command = IDE_CMD_INITIALIZE_DRIVE_PARAMETERS; - debug("Init device params... "); - if (pio_non_data(ctrl, &cmd) < 0) { - debug("failed (ok for newer drives)\n"); - } - else{ - debug("ok\n"); - } - } - - printf("hd%c: %s", - 'a'+drive, - (info->address_mode==ADDRESS_MODE_CHS) ? "CHS" : - (info->address_mode==ADDRESS_MODE_LBA) ? "LBA" : - (info->address_mode==ADDRESS_MODE_LBA48) ? "LBA48" : - (info->address_mode==ADDRESS_MODE_PACKET) ? "ATAPI" : "???"); -#if 0 -// can not pass compiler - if (info->sectors > (10LL*1000*1000*1000/512)) - printf(" %uGB", (unsigned) (info->sectors / (1000*1000*1000/512))); - else if (info->sectors > (10*1000*1000/512)) - printf(" %uMB", (unsigned) (info->sectors / (1000*1000/512))); - else if (info->sectors > 0) - printf(" %uKB", (unsigned) (info->sectors / 2)); -#endif - printf(": %s\n", info->model_number); - return 0; -} - -/* Experimental floating bus detection - * As Eric mentions, we get stuck when the bus has no drive - * and floating high. To avoid this, try some heuristics. - * This is based on a paper on Phoenix website. --ts1 */ -static int ide_bus_floating(struct controller *ctrl) -{ - unsigned long timeout; - unsigned char status; - - /* Test 1: if status reads 0xff, probably no device is present - * on the bus. Repeat this for 20msec. */ - timeout = currticks() + 20 * TICKS_PER_SEC / 18; - status = 0; - do { - /* Take logical OR to avoid chattering */ - status |= inb(IDE_REG_STATUS(ctrl)); - /* If it makes 0xff, it's possible to be floating, - * do test2 to ensure. */ - if (status == 0xff) - goto test2; - /* If BSY bit is not set, it's harmless to continue probing. */ - if ((status & IDE_STATUS_BSY) == 0) - return 0; - } while (currticks() < timeout); - /* Timed out. Logical ORed status didn't make 0xFF. - * We have something there. */ - return 0; - -test2: - /* Test 2: write something to registers, then read back and - * compare. Note that ATA spec inhibits this while BSY is set, - * but for many drives this works. This is a confirmation step anyway. - */ - outb(0xaa, ctrl->cmd_base + 2); - outb(0x55, ctrl->cmd_base + 3); - outb(0xff, ctrl->cmd_base + 4); - if (inb(ctrl->cmd_base+2) == 0xaa - && inb(ctrl->cmd_base+3) == 0x55 - && inb(ctrl->cmd_base+4) == 0xff) { - /* We have some registers there. - * Though this does not mean it is not a NIC or something... */ - return 0; - } - - /* Status port is 0xFF, and other registers are not there. - * Most certainly this bus is floating. */ - debugx("Detected floating bus\n"); - return 1; -} - -static int init_controller(struct controller *ctrl, int drive, unsigned char *buffer) -{ - struct harddisk_info *info; - - /* Put the drives ide channel in a know state and wait - * for the drives to spinup. - * - * In practice IDE disks tend not to respond to commands until - * they have spun up. This makes IDE hard to deal with - * immediately after power up, as the delays can be quite - * long, so we must be very careful here. - * - * There are two pathological cases that must be dealt with: - * - * - The BSY bit not being set while the IDE drives spin up. - * In this cases only a hard coded delay will work. As - * I have not reproduced it, and this is out of spec for - * IDE drives the work around can be enabled by setting - * BSY_SET_DURING_SPINUP to 0. - * - * - The BSY bit floats high when no drives are plugged in. - * This case will not be detected except by timing out but - * we avoid the problems by only probing devices we are - * supposed to boot from. If we don't do the probe we - * will not experience the problem. - * - * So speed wise I am only slow if the BSY bit is not set - * or not reported by the IDE controller during spinup, which - * is quite rare. - * - */ -#if !BSY_SET_DURING_SPINUP - if (await_ide(timeout, ctrl, currticks() + IDE_TIMEOUT) < 0) { - return -1; - } -#endif - /* ts1: Try some heuristics to avoid waiting for floating bus */ - if (ide_bus_floating(ctrl)) - return -1; - - if (ide_software_reset(ctrl) < 0) { - return -1; - } - - /* Note: I have just done a software reset. It may be - * reasonable to just read the boot time signatures - * off of the drives to see if they are present. - * - * For now I will go with just sending commands to the drives - * and assuming filtering out missing drives by detecting registers - * that won't set and commands that fail to execute properly. - */ - - /* Now initialize the individual drives */ - info = &harddisk_info[drive]; - init_drive_x(info, ctrl, 0, drive, buffer, IDE_CMD_IDENTIFY_DEVICE); - if (!info->drive_exists) - init_drive_x(info, ctrl, 0, drive, buffer, - IDE_CMD_IDENTIFY_PACKET_DEVICE); - if (info->drive_exists && !info->slave_absent) { - drive++; - info++; - init_drive_x(info, ctrl, 1, drive, buffer, - IDE_CMD_IDENTIFY_DEVICE); - if (!info->drive_exists) - init_drive_x(info, ctrl, 1, drive, buffer, - IDE_CMD_IDENTIFY_PACKET_DEVICE); - } - - return 0; -} - -static int -atapi_request_sense(struct harddisk_info *info, uint8_t *asc, uint8_t *ascq) -{ - uint8_t packet[12]; - uint8_t buf[18]; - int i; - - memset(packet, 0, sizeof packet); - packet[0] = 0x03; /* REQUEST SENSE */ - packet[4] = sizeof buf; - if (pio_packet(info, 1, packet, sizeof packet, buf, sizeof buf) != 0) - return -1; - - for (i = 0; i < sizeof buf; i++) - debug("%02x ", buf[i]); - debug("\n"); - - if (asc) - *asc = buf[12]; - if (ascq) - *ascq = buf[13]; - return 0; -} - -static int atapi_detect_medium(struct harddisk_info *info) -{ - uint8_t packet[12]; - uint8_t buf[8]; - uint32_t block_len, sectors; - unsigned long timeout; - uint8_t asc, ascq; - int in_progress; - - memset(packet, 0, sizeof packet); - packet[0] = 0x25; /* READ CAPACITY */ - - /* Retry READ CAPACITY for 5 seconds unless MEDIUM NOT PRESENT - * is reported by the drive. If the drive reports "IN PROGRESS", - * 30 seconds is added. */ - timeout = currticks() + 5*TICKS_PER_SEC; - in_progress = 0; - while (currticks() < timeout) { - if (pio_packet(info, 1, packet, sizeof packet, buf, sizeof buf) - == 0) - goto ok; - - if (atapi_request_sense(info, &asc, &ascq) == 0) { - if (asc == 0x3a) { /* MEDIUM NOT PRESENT */ - debug("Device reports MEDIUM NOT PRESENT\n"); - return -1; - } - - if (asc == 0x04 && ascq == 0x01 && !in_progress) { - /* IN PROGRESS OF BECOMING READY */ - printf("Waiting for drive to detect " - "the medium... "); - /* Allow 30 seconds more */ - timeout = currticks() + 30*TICKS_PER_SEC; - in_progress = 1; - } - } - - mdelay(100); - } - debug("read capacity failed\n"); - return -1; -ok: - - block_len = (uint32_t) buf[4] << 24 - | (uint32_t) buf[5] << 16 - | (uint32_t) buf[6] << 8 - | (uint32_t) buf[7] << 0; - debug("block_len=%u\n", block_len); - if (block_len != IDE_SECTOR_SIZE && block_len != CDROM_SECTOR_SIZE) { - debugx("Unsupported sector size %u\n", block_len); - return -1; - } - info->hw_sector_size = block_len; - - sectors = (uint32_t) buf[0] << 24 - | (uint32_t) buf[1] << 16 - | (uint32_t) buf[2] << 8 - | (uint32_t) buf[3] << 0; - - debug("sectors=%u\n", sectors); - if (info->hw_sector_size == CDROM_SECTOR_SIZE) - sectors <<= 2; /* # of sectors in 512-byte "soft" sector */ - if (sectors != info->sectors) - printf("%dMB medium detected\n", sectors>>(20-9)); - info->sectors = sectors; - return 0; -} - -static int detect_medium(struct harddisk_info *info) -{ - if (info->address_mode == ADDRESS_MODE_PACKET) { - if (atapi_detect_medium(info) != 0) - return -1; - } else { - debug("not implemented for non-ATAPI device\n"); - return -1; - } - return 0; -} - -static int find_ide_controller_compat(struct controller *ctrl, int index) -{ - if (index >= IDE_MAX_CONTROLLERS) - return -1; - ctrl->cmd_base = ide_base[index]; - ctrl->ctrl_base = ide_base[index] + IDE_REG_EXTENDED_OFFSET; - return 0; -} - -#ifdef SUPPORT_PCI -static int find_ide_controller(struct controller *ctrl, int ctrl_index) -{ - int pci_index; - struct pci_device *dev; - unsigned int mask; - uint32_t x; - - /* A PCI IDE controller has two channels (pri, sec) */ - pci_index = ctrl_index >> 1; - - /* Find a IDE storage class device */ - dev = pci_find_device_2(-1, -1, 0x0101, 0x0180, -1, pci_index); - if (!dev) { - debug("PCI IDE #%d not found\n", pci_index); - return -1; - } - - debug("found PCI IDE controller %04x:%04x prog_if=%#x\n", - dev->vendor, dev->dev_id, ((dev->class>>8) & 0xff)); - - /* See how this controller is configured */ - mask = (ctrl_index & 1) ? 4 : 1; - debug("%s channel: ", (ctrl_index & 1) ? "secodary" : "primary"); - if ( (((dev->class>>8) & 0xff) & mask) || ((dev->class>>16)!= 0x0101)) { // 0x0180 and other must use native PCI mode - debug("native PCI mode\n"); - if ((ctrl_index & 1) == 0) { - - /* Primary channel */ - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0,&x); - ctrl->cmd_base = x; - pci_read_config_dword(dev, PCI_BASE_ADDRESS_1,&x); - ctrl->ctrl_base = x; - } else { - /* Secondary channel */ - pci_read_config_dword(dev, PCI_BASE_ADDRESS_2,&x); - ctrl->cmd_base = x; - pci_read_config_dword(dev, PCI_BASE_ADDRESS_3,&x); - ctrl->ctrl_base = x; - } - ctrl->cmd_base &= ~3; - ctrl->ctrl_base &= ~3; - } else { - debug("compatibility mode\n"); - if (find_ide_controller_compat(ctrl, ctrl_index) != 0) - return -1; - } - - debug("cmd_base=%#x ctrl_base=%#x\n", ctrl->cmd_base, ctrl->ctrl_base); -#if 0 - debug("cmd+0=%0#x\n", inb(ctrl->cmd_base+0)); - debug("cmd+1=%0#x\n", inb(ctrl->cmd_base+1)); - debug("cmd+2=%0#x\n", inb(ctrl->cmd_base+2)); - debug("cmd+3=%0#x\n", inb(ctrl->cmd_base+3)); - debug("cmd+4=%0#x\n", inb(ctrl->cmd_base+4)); - debug("cmd+5=%0#x\n", inb(ctrl->cmd_base+5)); - debug("cmd+6=%0#x\n", inb(ctrl->cmd_base+6)); - debug("cmd+7=%0#x\n", inb(ctrl->cmd_base+7)); - debug("ctrl+0=%0#x\n", inb(ctrl->ctrl_base+0)); - debug("ctrl+1=%0#x\n", inb(ctrl->ctrl_base+1)); - debug("ctrl+2=%0#x\n", inb(ctrl->ctrl_base+2)); - debug("ctrl+3=%0#x\n", inb(ctrl->ctrl_base+3)); -#endif - return 0; -} -#else /* !SUPPORT_PCI */ -# define find_ide_controller find_ide_controller_compat -#endif - -int ide_probe(int drive) -{ - struct controller *ctrl; - int ctrl_index; - struct harddisk_info *info; - - if (drive >= IDE_MAX_DRIVES) { - debugx("Unsupported drive number\n"); - return -1; - } - - /* A controller has two drives (master, slave) */ - ctrl_index = drive >> 1; - - ctrl = &controllers[ctrl_index]; - if (ctrl->cmd_base == 0) { - if (find_ide_controller(ctrl, ctrl_index) != 0) { - debugx("IDE channel %d not found\n", ctrl_index); - return -1; - } - if (init_controller(ctrl, drive & ~1, ide_buffer) != 0) { - printf("No drive detected on IDE channel %d\n", - ctrl_index); - return -1; - } - } - info = &harddisk_info[drive]; - if (!info->drive_exists) { - printf("Drive %d does not exist\n", drive); - return -1; - } - - if (info->removable) { - if (detect_medium(info) != 0) { - printf("Media detection failed\n"); - return -1; - } - } - - return 0; -} - -/* vim:set sts=8 sw=8: */ diff --git a/src/filo/fs/blockdev.c b/src/filo/fs/blockdev.c deleted file mode 100644 index f159ff2f..00000000 --- a/src/filo/fs/blockdev.c +++ /dev/null @@ -1,383 +0,0 @@ -#include - -#include -#include - -#define DEBUG_THIS DEBUG_BLOCKDEV -#include - -#define NUM_CACHE 64 -static unsigned char buf_cache[NUM_CACHE][512]; -static unsigned long cache_sect[NUM_CACHE]; - -static char dev_name[256]; - -int dev_type = -1; -int dev_drive = -1; -unsigned long part_start; -unsigned long part_length; -int using_devsize; - -static inline int has_pc_part_magic(unsigned char *sect) -{ - return sect[510]==0x55 && sect[511]==0xAA; -} - -static inline int is_pc_extended_part(unsigned char type) -{ - return type==5 || type==0xf || type==0x85; -} - -/* IBM-PC/MS-DOS style partitioning scheme */ -static int open_pc_partition(int part, unsigned long *start_p, - unsigned long *length_p) -{ - /* Layout of PC partition table */ - struct pc_partition { - unsigned char boot; - unsigned char head; - unsigned char sector; - unsigned char cyl; - unsigned char type; - unsigned char e_head; - unsigned char e_sector; - unsigned char e_cyl; - unsigned char start_sect[4]; /* unaligned little endian */ - unsigned char nr_sects[4]; /* ditto */ - } *p; - unsigned char buf[512]; - - /* PC partition probe */ - if (!devread(0, 0, sizeof(buf), buf)) { - debug("device read failed\n"); - return 0; - } - if (!has_pc_part_magic(buf)) { - debug("pc partition magic number not found\n"); - //debug_hexdump(buf, 512); - return PARTITION_UNKNOWN; - } - p = (struct pc_partition *) (buf + 0x1be); - if (part < 4) { - /* Primary partition */ - p += part; - if (p->type==0 || is_pc_extended_part(p->type)) { - printf("Partition %d does not exist\n", part+1); - return 0; - } - *start_p = get_le32(p->start_sect); - *length_p = get_le32(p->nr_sects); - return 1; - } else { - /* Extended partition */ - int i; - int cur_part; - unsigned long ext_start, cur_table; - /* Search for the extended partition - * which contains logical partitions */ - for (i = 0; i < 4; i++) { - if (is_pc_extended_part(p[i].type)) - break; - } - if (i >= 4) { - printf("Extended partition not found\n"); - return 0; - } - debug("Extended partition at %d\n", i+1); - /* Visit each logical partition labels */ - ext_start = get_le32(p[i].start_sect); - cur_table = ext_start; - cur_part = 4; - for (;;) { - debug("cur_part=%d at %lu\n", cur_part, cur_table); - if (!devread(cur_table, 0, sizeof(buf), buf)) - return 0; - if (!has_pc_part_magic(buf)) { - debug("no magic\n"); - break; - } - - p = (struct pc_partition *) (buf + 0x1be); - /* First entry is the logical partition */ - if (cur_part == part) { - if (p->type==0) { - printf("Partition %d is empty\n", part+1); - return 0; - } - *start_p = cur_table + get_le32(p->start_sect); - *length_p = get_le32(p->nr_sects); - return 1; - } - /* Second entry is link to next partition */ - if (!is_pc_extended_part(p[1].type)) { - debug("no link\n"); - break; - } - cur_table = ext_start + get_le32(p[1].start_sect); - - cur_part++; - } - printf("Logical partition %d not exist\n", part+1); - return 0; - } -} - -static void flush_cache(void) -{ - int i; - for (i = 0; i < NUM_CACHE; i++) - cache_sect[i] = (unsigned long) -1; -} - -static int parse_device_name(const char *name, int *type, int *drive, - int *part, uint64_t *offset, uint64_t *length) -{ - *offset = *length = 0; - - if (memcmp(name, "hd", 2) == 0) { - *type = DISK_IDE; - name += 2; - if (*name < 'a' || *name > 'z') { - printf("Invalid drive\n"); - return 0; - } - *drive = *name - 'a'; - name++; - } else if (memcmp(name, "mem", 3) == 0) { - *type = DISK_MEM; - name += 3; - *drive = 0; - } else if (memcmp(name, "ud", 2) == 0) { - *type = DISK_USB; - name += 2; - if (*name < 'a' || *name > 'z') { - printf("Invalid drive\n"); - return 0; - } - *drive = *name - 'a'; - name++; - } else { - printf("Unknown device type\n"); - return 0; - } - - *part = (int) simple_strtoull(name, (char **)&name, 0); - - if (*name == '@') { - name++; - *offset = strtoull_with_suffix(name, (char **)&name, 0); - if (*name == ',') - *length = strtoull_with_suffix(name+1, (char **)&name, 0); -// debug("offset=%#Lx length=%#Lx\n", *offset, *length); - } - - if (*name != '\0') { - printf("Can't parse device name\n"); - return 0; - } - - return 1; -} - -int devopen(const char *name, int *reopen) -{ - int type, drive, part; - uint64_t offset, length; - uint32_t disk_size = 0; - - /* Don't re-open the device that's already open */ - if (strcmp(name, dev_name) == 0) { - debug("already open\n"); - *reopen = 1; - return 1; - } - *reopen = 0; - - if (!parse_device_name(name, &type, &drive, &part, &offset, &length)) { - debug("failed to parse device name: %s\n", name); - return 0; - } - - /* Do simple sanity check first */ - if (offset & 0x1ff) { - printf("Device offset must be multiple of 512\n"); - return 0; - } - if (length & 0x1ff) { - debugx("WARNING: length is rounded up to multiple of 512\n"); - length = (length + 0x1ff) & ~0x1ff; - } - - switch (type) { -#ifdef IDE_DISK - case DISK_IDE: - if (ide_probe(drive) != 0) { - debug("failed to open ide\n"); - return 0; - } - disk_size = (uint32_t) -1; /* FIXME */ - break; -#endif - case DISK_MEM: - disk_size = 1 << (32 - 9); /* 4GB/512-byte */ - break; -#ifdef USB_DISK - case DISK_USB: - if (usb_probe(drive) != 0) { - debug("failed to open usb\n"); - return 0; - } - disk_size = (uint32_t) -1; /* FIXME */ - break; -#endif - default: - printf("Unknown device type %d\n", type); - return 0; - } - - if (dev_type != type || dev_drive != drive) - flush_cache(); - - /* start with whole disk */ - dev_type = type; - dev_drive = drive; - part_start = 0; - part_length = disk_size; - using_devsize = 1; - - if (part != 0) { - /* partition is specified */ - int ret; - ret = open_pc_partition(part - 1, &part_start, &part_length); - if (ret == PARTITION_UNKNOWN) { - ret = open_eltorito_image(part - 1, &part_start, &part_length); - if (ret == PARTITION_UNKNOWN) { - printf("Unrecognized partitioning scheme\n"); - return 0; - } - } - if (ret == 0) { - debug("can't open partition %d\n", part); - return 0; - } - - debug("Partition %d start %lu length %lu\n", part, - part_start, part_length); - } - - if (offset) { - if (offset >= (uint64_t) part_length << 9) { - printf("Device offset is too high\n"); - return 0; - } - part_start += offset >> 9; - part_length -= offset >> 9; - debug("after offset: start %lu, length %lu\n", part_start, part_length); - } - - if (length) { - if (length > (uint64_t) part_length << 9) { - printf("Specified length exceeds the size of device\n"); - return 0; - } - part_length = length >> 9; - debug("after length: length %lu\n", part_length); - using_devsize = 0; - } - - strncpy(dev_name, name, sizeof(dev_name)-1); - - return 1; -} - -/* Read a sector from opened device with simple/stupid buffer cache */ -static void *read_sector(unsigned long sector) -{ - unsigned int hash; - void *buf; - int i; - - /* If reading memory, just return the memory as the buffer */ - if (dev_type == DISK_MEM) { - unsigned long phys = sector << 9; - //debug("mem: %#lx\n", phys); - return phys_to_virt(phys); - } - - /* Search in the cache */ - hash = sector % NUM_CACHE; - buf = buf_cache[hash]; - if (cache_sect[hash] != sector) { - cache_sect[hash] = (unsigned long) -1; - switch (dev_type) { -#ifdef IDE_DISK - case DISK_IDE: - if (ide_read(dev_drive, sector, buf) != 0) - goto readerr; - break; -#endif -#ifdef USB_DISK - case DISK_USB: - if (usb_read(dev_drive, sector, buf) != 0) - goto readerr; - break; -#endif - default: - printf("read_sector: device not open\n"); - return 0; - } - cache_sect[hash] = sector; - } -#if 0 - printf("in read_sector:\n"); - for(i=0;i<128;i++) { - if((i%4)==0) printf("\n %08x:",i*4); - printf(" %08x ",(uint32_t)*((uint32_t *)buf+i)); - } -#endif - - return buf; - -readerr: - printf("Disk read error dev_type=%d drive=%d sector=%x\n", - dev_type, dev_drive, sector); - dev_name[0] = '\0'; /* force re-open the device next time */ - return 0; -} - -int devread(unsigned long sector, unsigned long byte_offset, - unsigned long byte_len, void *buf) -{ - char *sector_buffer; - char *dest = buf; - unsigned long len; - int i; - - sector += byte_offset >> 9; - byte_offset &= 0x1ff; - - if (sector + ((byte_len + 0x1ff) >> 9) > part_length) { - printf("Attempt to read out of device/partition\n"); - debug("sector=%x part_length=%x byte_len=%x\n", - sector, part_length, byte_len); - return 0; - } - - while (byte_len > 0) { - sector_buffer = read_sector(part_start + sector); - if (!sector_buffer) { - debug("read sector failed\n"); - return 0; - } - len = 512 - byte_offset; - if (len > byte_len) - len = byte_len; - memcpy(dest, sector_buffer + byte_offset, len); - sector++; - byte_offset = 0; - byte_len -= len; - dest += len; - } - - return 1; -} diff --git a/src/filo/fs/eltorito.c b/src/filo/fs/eltorito.c deleted file mode 100644 index 30b663d0..00000000 --- a/src/filo/fs/eltorito.c +++ /dev/null @@ -1,147 +0,0 @@ - -#include -#include -#include - -#define DEBUG_THIS DEBUG_ELTORITO -#include - -#define ELTORITO_PLATFORM_X86 0 -#define ELTORITO_PLATFORM_PPC 1 -#define ELTORITO_PLATFORM_MAC 2 -#include - -#ifndef ELTORITO_PLATFORM -#error "ELTORITO_PLATFORM is not defined for this arch" -#endif - -/* El Torito boot record at sector 0x11 of bootable CD */ -struct boot_record { - uint8_t ind; - uint8_t iso_id[5]; - uint8_t version; - uint8_t boot_id[32]; - uint8_t reserved[32]; - uint8_t catalog_offset[4]; -}; - -/* First entry of the catalog */ -struct validation_entry { - uint8_t header_id; - uint8_t platform; - uint8_t reserved[2]; - uint8_t id[24]; - uint8_t checksum[2]; - uint8_t key55; - uint8_t keyAA; -}; - -/* Initial/Default catalog entry */ -struct default_entry { - uint8_t boot_id; - uint8_t media_type; -#define MEDIA_MASK 0x0f -#define MEDIA_NOEMU 0 -#define MEDIA_1200_FD 1 -#define MEDIA_1440_FD 2 -#define MEDIA_2880_FD 3 -#define MEDIA_HD 4 - uint8_t load_segment[2]; - uint8_t system_type; - uint8_t reserved; - uint8_t sector_count[2]; - uint8_t start_sector[4]; - uint8_t reserved_too[20]; -}; - -/* Find El-Torito boot disk image */ -int open_eltorito_image(int part, unsigned long *offset_p, - unsigned long *length_p) -{ - struct boot_record boot_record; - uint32_t cat_offset; - uint8_t catalog[2048]; - struct validation_entry *ve; - int i, sum; - struct default_entry *de; - - /* We always use 512-byte "soft sector", but - * El-Torito uses 2048-byte CD-ROM sector */ - - /* Boot Record is at sector 0x11 */ - if (!devread(0x11<<2, 0, sizeof boot_record, &boot_record)) - return 0; - - if (boot_record.ind != 0 - || memcmp(boot_record.iso_id, "CD001", 5) != 0 - || memcmp(boot_record.boot_id, "EL TORITO SPECIFICATION", 23) - != 0) { - debug("No El-Torito signature\n"); - return PARTITION_UNKNOWN; - } - - if (part != 0) { - printf("El-Torito entries other than Initial/Default is not supported\n"); - return 0; - } - - cat_offset = get_le32(boot_record.catalog_offset); - debug("El-Torito boot catalog at sector %u\n", cat_offset); - if (!devread(cat_offset<<2, 0, 2048, catalog)) - return 0; - - /* Validate the catalog */ - ve = (void *) catalog; - //debug_hexdump(ve, sizeof *ve); - if (ve->header_id != 1 || ve->key55 != 0x55 || ve->keyAA != 0xAA) { - printf("Invalid El Torito boot catalog\n"); - return 0; - } - /* All words must sum up to zero */ - sum = 0; - for (i = 0; i < sizeof(*ve); i += 2) - sum += get_le16(&catalog[i]); - sum &= 0xffff; - if (sum != 0) { - printf("El Torito boot catalog verify failed\n"); - return 0; - } - debug("id='%.*s'\n", sizeof ve->id, ve->id); - - /* Platform check is warning only, because we won't directly execute - * the image. Just mounting it should be safe. */ - if (ve->platform != ELTORITO_PLATFORM){ - debugx("WARNING: Boot disk for different platform: %d\n", ve->platform); - } - - /* Just support initial/default entry for now */ - de = (void *) (ve + 1); - if (de->boot_id != 0x88) { - debugx("WARNING: Default boot entry is not bootable\n"); - } - - switch (de->media_type & MEDIA_MASK) { - case MEDIA_NOEMU: - printf("Disc doesn't use boot disk emulation\n"); - return 0; - case MEDIA_1200_FD: - *length_p = 1200*1024/512; - break; - case MEDIA_1440_FD: - *length_p = 1440*1024/512; - break; - case MEDIA_2880_FD: - *length_p = 2880*1024/512; - break; - case MEDIA_HD: - /* FIXME: read partition table and return first partition. - * Spec states emulation HD has only one partition and it must - * be the first partition */ - printf("Disc uses hard disk emulation - not supported\n"); - return 0; - } - *offset_p = get_le32(de->start_sector) << 2; - debug("offset=%#lx length=%#lx\n", *offset_p, *length_p); - - return 1; -} diff --git a/src/filo/fs/fat.h b/src/filo/fs/fat.h deleted file mode 100644 index 7fed6bac..00000000 --- a/src/filo/fs/fat.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -/* - * Defines for the FAT BIOS Parameter Block (embedded in the first block - * of the partition. - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; - -/* Note that some shorts are not aligned, and must therefore - * be declared as array of two bytes. - */ -struct fat_bpb { - __s8 ignored[3]; /* Boot strap short or near jump */ - __s8 system_id[8]; /* Name - can be used to special case - partition manager volumes */ - __u8 bytes_per_sect[2]; /* bytes per logical sector */ - __u8 sects_per_clust;/* sectors/cluster */ - __u8 reserved_sects[2]; /* reserved sectors */ - __u8 num_fats; /* number of FATs */ - __u8 dir_entries[2]; /* root directory entries */ - __u8 short_sectors[2]; /* number of sectors */ - __u8 media; /* media code (unused) */ - __u16 fat_length; /* sectors/FAT */ - __u16 secs_track; /* sectors per track */ - __u16 heads; /* number of heads */ - __u32 hidden; /* hidden sectors (unused) */ - __u32 long_sectors; /* number of sectors (if short_sectors == 0) */ - - /* The following fields are only used by FAT32 */ - __u32 fat32_length; /* sectors/FAT */ - __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __u32 root_cluster; /* first cluster in root directory */ - __u16 info_sector; /* filesystem info sector */ - __u16 backup_boot; /* backup boot sector */ - __u16 reserved2[6]; /* Unused */ -}; - -#define FAT_CVT_U16(bytarr) (* (__u16*)(bytarr)) - -/* - * Defines how to differentiate a 12-bit and 16-bit FAT. - */ - -#define FAT_MAX_12BIT_CLUST 4087 /* 4085 + 2 */ - -/* - * Defines for the file "attribute" byte - */ - -#define FAT_ATTRIB_OK_MASK 0x37 -#define FAT_ATTRIB_NOT_OK_MASK 0xC8 -#define FAT_ATTRIB_DIR 0x10 -#define FAT_ATTRIB_LONGNAME 0x0F - -/* - * Defines for FAT directory entries - */ - -#define FAT_DIRENTRY_LENGTH 32 - -#define FAT_DIRENTRY_ATTRIB(entry) \ - (*((unsigned char *) (entry+11))) -#define FAT_DIRENTRY_VALID(entry) \ - ( ((*((unsigned char *) entry)) != 0) \ - && ((*((unsigned char *) entry)) != 0xE5) \ - && !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) ) -#define FAT_DIRENTRY_FIRST_CLUSTER(entry) \ - ((*((unsigned short *) (entry+26)))+(*((unsigned short *) (entry+20)) << 16)) -#define FAT_DIRENTRY_FILELENGTH(entry) \ - (*((unsigned long *) (entry+28))) - -#define FAT_LONGDIR_ID(entry) \ - (*((unsigned char *) (entry))) -#define FAT_LONGDIR_ALIASCHECKSUM(entry) \ - (*((unsigned char *) (entry+13))) diff --git a/src/filo/fs/filesys.h b/src/filo/fs/filesys.h deleted file mode 100644 index f81bebe7..00000000 --- a/src/filo/fs/filesys.h +++ /dev/null @@ -1,233 +0,0 @@ -/* GRUB compatibility header */ - -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -//#include -#include - -#include - -/* This disables some portion of code */ -#define STAGE1_5 1 - -static inline int -substring (const char *s1, const char *s2) -{ - while (*s1 == *s2) - { - /* The strings match exactly. */ - if (! *(s1++)) - return 0; - s2 ++; - } - - /* S1 is a substring of S2. */ - if (*s1 == 0) - return -1; - - /* S1 isn't a substring. */ - return 1; -} - -#define grub_memmove memmove -#define grub_strcmp strcmp - -#define MAXINT 0x7fffffff - -/* This is only used by fsys_* to determine if it's hard disk. If it is, - * they try to guess filesystem type by partition type. I guess it is - * not necessory, so hardcoded to 0 (first floppy) --ts1 */ -#define current_drive 0 - -/* Ditto */ -#define current_slice 0 - -extern unsigned long part_start; -extern unsigned long part_length; -extern int filepos; -extern int filemax; -extern int fsmax; - -/* Error codes (descriptions are in common.c) */ -typedef enum -{ - ERR_NONE = 0, - ERR_BAD_FILENAME, - ERR_BAD_FILETYPE, - ERR_BAD_GZIP_DATA, - ERR_BAD_GZIP_HEADER, - ERR_BAD_PART_TABLE, - ERR_BAD_VERSION, - ERR_BELOW_1MB, - ERR_BOOT_COMMAND, - ERR_BOOT_FAILURE, - ERR_BOOT_FEATURES, - ERR_DEV_FORMAT, - ERR_DEV_VALUES, - ERR_EXEC_FORMAT, - ERR_FILELENGTH, - ERR_FILE_NOT_FOUND, - ERR_FSYS_CORRUPT, - ERR_FSYS_MOUNT, - ERR_GEOM, - ERR_NEED_LX_KERNEL, - ERR_NEED_MB_KERNEL, - ERR_NO_DISK, - ERR_NO_PART, - ERR_NUMBER_PARSING, - ERR_OUTSIDE_PART, - ERR_READ, - ERR_SYMLINK_LOOP, - ERR_UNRECOGNIZED, - ERR_WONT_FIT, - ERR_WRITE, - ERR_BAD_ARGUMENT, - ERR_UNALIGNED, - ERR_PRIVILEGED, - ERR_DEV_NEED_INIT, - ERR_NO_DISK_SPACE, - ERR_NUMBER_OVERFLOW, - - MAX_ERR_NUM -} grub_error_t; - -extern grub_error_t errnum; - -#define grub_open file_open -#define grub_read file_read -#define grub_seek file_seek -#define grub_close file_close - -/* instrumentation variables */ -/* (Not used in FILO) */ -extern void (*disk_read_hook) (int, int, int); -extern void (*disk_read_func) (int, int, int); - -#define FSYS_BUFLEN 0x8000 -extern char FSYS_BUF[FSYS_BUFLEN]; - -#define print_possibilities 0 - -#define SECTOR_SIZE 512 -#define SECTOR_BITS 9 - -#ifdef FSYS_FAT -int fat_mount (void); -int fat_read (char *buf, int len); -int fat_dir (char *dirname); -#endif - -#ifdef FSYS_EXT2FS -int ext2fs_mount (void); -int ext2fs_read (char *buf, int len); -int ext2fs_dir (char *dirname); -#endif - -#ifdef FSYS_MINIX -int minix_mount (void); -int minix_read (char *buf, int len); -int minix_dir (char *dirname); -#endif - -#ifdef FSYS_REISERFS -int reiserfs_mount (void); -int reiserfs_read (char *buf, int len); -int reiserfs_dir (char *dirname); -int reiserfs_embed (int *start_sector, int needed_sectors); -#endif - -#ifdef FSYS_JFS -int jfs_mount (void); -int jfs_read (char *buf, int len); -int jfs_dir (char *dirname); -int jfs_embed (int *start_sector, int needed_sectors); -#endif - -#ifdef FSYS_XFS -int xfs_mount (void); -int xfs_read (char *buf, int len); -int xfs_dir (char *dirname); -#endif - -#ifdef FSYS_ISO9660 -int iso9660_mount (void); -int iso9660_read (char *buf, int len); -int iso9660_dir (char *dirname); -#endif - -/* This is not a flag actually, but used as if it were a flag. */ -#define PC_SLICE_TYPE_HIDDEN_FLAG 0x10 - -#define PC_SLICE_TYPE_NONE 0 -#define PC_SLICE_TYPE_FAT12 1 -#define PC_SLICE_TYPE_FAT16_LT32M 4 -#define PC_SLICE_TYPE_EXTENDED 5 -#define PC_SLICE_TYPE_FAT16_GT32M 6 -#define PC_SLICE_TYPE_FAT32 0xb -#define PC_SLICE_TYPE_FAT32_LBA 0xc -#define PC_SLICE_TYPE_FAT16_LBA 0xe -#define PC_SLICE_TYPE_WIN95_EXTENDED 0xf -#define PC_SLICE_TYPE_EZD 0x55 -#define PC_SLICE_TYPE_MINIX 0x80 -#define PC_SLICE_TYPE_LINUX_MINIX 0x81 -#define PC_SLICE_TYPE_EXT2FS 0x83 -#define PC_SLICE_TYPE_LINUX_EXTENDED 0x85 -#define PC_SLICE_TYPE_VSTAFS 0x9e -#define PC_SLICE_TYPE_DELL_UTIL 0xde -#define PC_SLICE_TYPE_LINUX_RAID 0xfd - -/* For convinience. */ -/* Check if TYPE is a FAT partition type. Clear the hidden flag before - the check, to allow the user to mount a hidden partition in GRUB. */ -#define IS_PC_SLICE_TYPE_FAT(type) \ - ({ int _type = (type) & ~PC_SLICE_TYPE_HIDDEN_FLAG; \ - _type == PC_SLICE_TYPE_FAT12 \ - || _type == PC_SLICE_TYPE_FAT16_LT32M \ - || _type == PC_SLICE_TYPE_FAT16_GT32M \ - || _type == PC_SLICE_TYPE_FAT16_LBA \ - || _type == PC_SLICE_TYPE_FAT32 \ - || _type == PC_SLICE_TYPE_FAT32_LBA \ - || _type == PC_SLICE_TYPE_DELL_UTIL; }) - -#define IS_PC_SLICE_TYPE_MINIX(type) \ - (((type) == PC_SLICE_TYPE_MINIX) \ - || ((type) == PC_SLICE_TYPE_LINUX_MINIX)) - -#define IS_PC_SLICE_TYPE_BSD_WITH_FS(type,fs) 0 - -/* possible values for the *BSD-style partition type */ -#define FS_UNUSED 0 /* unused */ -#define FS_SWAP 1 /* swap */ -#define FS_V6 2 /* Sixth Edition */ -#define FS_V7 3 /* Seventh Edition */ -#define FS_SYSV 4 /* System V */ -#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ -#define FS_V8 6 /* Eighth Edition, 4K blocks */ -#define FS_BSDFFS 7 /* 4.2BSD fast file system */ -#define FS_MSDOS 8 /* MSDOS file system */ -#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */ -#define FS_OTHER 10 /* in use, but unknown/unsupported */ -#define FS_HPFS 11 /* OS/2 high-performance file system */ -#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ -#define FS_BOOT 13 /* partition contains bootstrap */ -#define FS_ADOS 14 /* AmigaDOS fast file system */ -#define FS_HFS 15 /* Macintosh HFS */ -#define FS_FILECORE 16 /* Acorn Filecore Filing System */ -#define FS_EXT2FS 17 /* Linux Extended 2 file system */ diff --git a/src/filo/fs/fsys_ext2fs.c b/src/filo/fs/fsys_ext2fs.c deleted file mode 100644 index 62c6e80f..00000000 --- a/src/filo/fs/fsys_ext2fs.c +++ /dev/null @@ -1,779 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999, 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_EXT2FS - -#include "shared.h" -#include "filesys.h" -#include -#include "string.h" - -static int mapblock1, mapblock2; - -/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ -#define DEV_BSIZE 512 - -/* include/linux/fs.h */ -#define BLOCK_SIZE 1024 /* initial block size for superblock read */ -/* made up, defaults to 1 but can be passed via mount_opts */ -#define WHICH_SUPER 1 -/* kind of from fs/ext2/super.c */ -#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ - -/* include/asm-i386/types.h */ -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; - -/* - * Constants relative to the data blocks, from ext2_fs.h - */ -#define EXT2_NDIR_BLOCKS 12 -#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS -#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) -#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) -#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) - -/* include/linux/ext2_fs.h */ -struct ext2_super_block - { - __u32 s_inodes_count; /* Inodes count */ - __u32 s_blocks_count; /* Blocks count */ - __u32 s_r_blocks_count; /* Reserved blocks count */ - __u32 s_free_blocks_count; /* Free blocks count */ - __u32 s_free_inodes_count; /* Free inodes count */ - __u32 s_first_data_block; /* First Data Block */ - __u32 s_log_block_size; /* Block size */ - __s32 s_log_frag_size; /* Fragment size */ - __u32 s_blocks_per_group; /* # Blocks per group */ - __u32 s_frags_per_group; /* # Fragments per group */ - __u32 s_inodes_per_group; /* # Inodes per group */ - __u32 s_mtime; /* Mount time */ - __u32 s_wtime; /* Write time */ - __u16 s_mnt_count; /* Mount count */ - __s16 s_max_mnt_count; /* Maximal mount count */ - __u16 s_magic; /* Magic signature */ - __u16 s_state; /* File system state */ - __u16 s_errors; /* Behaviour when detecting errors */ - __u16 s_pad; - __u32 s_lastcheck; /* time of last check */ - __u32 s_checkinterval; /* max. time between checks */ - __u32 s_creator_os; /* OS */ - __u32 s_rev_level; /* Revision level */ - __u16 s_def_resuid; /* Default uid for reserved blocks */ - __u16 s_def_resgid; /* Default gid for reserved blocks */ - __u32 s_reserved[235]; /* Padding to the end of the block */ - }; - -struct ext2_group_desc - { - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_pad; - __u32 bg_reserved[3]; - }; - -struct ext2_inode - { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Owner Uid */ - __u32 i_size; /* 4: Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* 12: Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* 20: Deletion Time */ - __u16 i_gid; /* Group Id */ - __u16 i_links_count; /* 24: Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* 32: File flags */ - union - { - struct - { - __u32 l_i_reserved1; - } - linux1; - struct - { - __u32 h_i_translator; - } - hurd1; - struct - { - __u32 m_i_reserved1; - } - masix1; - } - osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ - __u32 i_version; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ - union - { - struct - { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; - __u32 l_i_reserved2[2]; - } - linux2; - struct - { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; - } - hurd2; - struct - { - __u8 m_i_frag; /* Fragment number */ - __u8 m_i_fsize; /* Fragment size */ - __u16 m_pad1; - __u32 m_i_reserved2[2]; - } - masix2; - } - osd2; /* OS dependent 2 */ - }; - -/* linux/limits.h */ -#define NAME_MAX 255 /* # chars in a file name */ - -/* linux/posix_type.h */ -typedef long linux_off_t; - -/* linux/ext2fs.h */ -#define EXT2_NAME_LEN 255 -struct ext2_dir_entry - { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u8 name_len; /* Name length */ - __u8 file_type; - char name[EXT2_NAME_LEN]; /* File name */ - }; - -/* linux/ext2fs.h */ -/* - * EXT2_DIR_PAD defines the directory entries boundaries - * - * NOTE: It must be a multiple of 4 - */ -#define EXT2_DIR_PAD 4 -#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) -#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ - ~EXT2_DIR_ROUND) - - -/* ext2/super.c */ -#define log2(n) ffz(~(n)) - -#define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */ -#define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */ -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -/* made up, these are pointers into FSYS_BUF */ -/* read once, always stays there: */ -#define SUPERBLOCK \ - ((struct ext2_super_block *)(FSYS_BUF)) -#define GROUP_DESC \ - ((struct ext2_group_desc *) \ - ((int)SUPERBLOCK + sizeof(struct ext2_super_block))) -#define INODE \ - ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK))) -#define DATABLOCK1 \ - ((int)((int)INODE + sizeof(struct ext2_inode))) -#define DATABLOCK2 \ - ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))) - -/* linux/ext2_fs.h */ -#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) -#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s))) - -/* linux/ext2_fs.h */ -#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) -/* kind of from ext2/super.c */ -#define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s)) -/* linux/ext2fs.h */ -#define EXT2_DESC_PER_BLOCK(s) \ - (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) -/* linux/stat.h */ -#define S_IFMT 00170000 -#define S_IFLNK 0120000 -#define S_IFREG 0100000 -#define S_IFDIR 0040000 -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) - -/* include/asm-i386/bitops.h */ -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -static __inline__ unsigned long -ffz (unsigned long word) -{ - __asm__ ("bsfl %1,%0" -: "=r" (word) -: "r" (~word)); - return word; -} - -/* check filesystem types and read superblock into memory buffer */ -int -ext2fs_mount (void) -{ - int retval = 1; - - if ((((current_drive & 0x80) || (current_slice != 0)) - && (current_slice != PC_SLICE_TYPE_EXT2FS) - && (current_slice != PC_SLICE_TYPE_LINUX_RAID) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS)) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))) - || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE)) - || !devread (SBLOCK, 0, sizeof (struct ext2_super_block), - (char *) SUPERBLOCK) - || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC) - retval = 0; - - return retval; -} - -/* Takes a file system block number and reads it into BUFFER. */ -static int -ext2_rdfsb (int fsblock, int buffer) -{ -#ifdef E2DEBUG - printf ("fsblock %d buffer %d\n", fsblock, buffer); -#endif /* E2DEBUG */ - return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0, - EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); -} - -/* from - ext2/inode.c:ext2_bmap() -*/ -/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into - a physical block (the location in the file system) via an inode. */ -static int -ext2fs_block_map (int logical_block) -{ - -#ifdef E2DEBUG - unsigned char *i; - for (i = (unsigned char *) INODE; - i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); - i++) - { - printf ("%c", "0123456789abcdef"[*i >> 4]); - printf ("%c", "0123456789abcdef"[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printf ("\n"); - } - else - { - printf (" "); - } - } - printf ("logical block %d\n", logical_block); -#endif /* E2DEBUG */ - - /* if it is directly pointed to by the inode, return that physical addr */ - if (logical_block < EXT2_NDIR_BLOCKS) - { -#ifdef E2DEBUG - printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block])); - printf ("returning %d\n", INODE->i_block[logical_block]); -#endif /* E2DEBUG */ - return INODE->i_block[logical_block]; - } - /* else */ - logical_block -= EXT2_NDIR_BLOCKS; - /* try the indirect block */ - if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) - { - if (mapblock1 != 1 - && !ext2_rdfsb (INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 1; - return ((__u32 *) DATABLOCK1)[logical_block]; - } - /* else */ - logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); - /* now try the double indirect block */ - if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) - { - int bnum; - if (mapblock1 != 2 - && !ext2_rdfsb (INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 2; - if ((bnum = (((__u32 *) DATABLOCK1) - [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) - != mapblock2 - && !ext2_rdfsb (bnum, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock2 = bnum; - return ((__u32 *) DATABLOCK2) - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; - } - /* else */ - mapblock2 = -1; - logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); - if (mapblock1 != 3 - && !ext2_rdfsb (INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 3; - if (!ext2_rdfsb (((__u32 *) DATABLOCK1) - [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) - * 2)], - DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - if (!ext2_rdfsb (((__u32 *) DATABLOCK2) - [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) - & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)], - DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - return ((__u32 *) DATABLOCK2) - [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]; -} - -/* preconditions: all preconds of ext2fs_block_map */ -int -ext2fs_read (char *buf, int len) -{ - int logical_block; - int offset; - int map; - int ret = 0; - int size = 0; - -#ifdef E2DEBUG - static char hexdigit[] = "0123456789abcdef"; - unsigned char *i; - for (i = (unsigned char *) INODE; - i < ((unsigned char *) INODE + sizeof (struct ext2_inode)); - i++) - { - printf ("%c", hexdigit[*i >> 4]); - printf ("%c", hexdigit[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printf ("\n"); - } - else - { - printf (" "); - } - } -#endif /* E2DEBUG */ - while (len > 0) - { - /* find the (logical) block component of our location */ - logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); - offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); - map = ext2fs_block_map (logical_block); -#ifdef E2DEBUG - printf ("map=%d\n", map); -#endif /* E2DEBUG */ - if (map < 0) - break; - - size = EXT2_BLOCK_SIZE (SUPERBLOCK); - size -= offset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), - offset, size, buf); - - disk_read_func = NULL; - - buf += size; - len -= size; - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - - -/* Based on: - def_blk_fops points to - blkdev_open, which calls (I think): - sys_open() - do_open() - open_namei() - dir_namei() which accesses current->fs->root - fs->root was set during original mount: - (something)... which calls (I think): - ext2_read_super() - iget() - __iget() - read_inode() - ext2_read_inode() - uses desc_per_block_bits, which is set in ext2_read_super() - also uses group descriptors loaded during ext2_read_super() - lookup() - ext2_lookup() - ext2_find_entry() - ext2_getblk() - -*/ - -/* preconditions: ext2fs_mount already executed, therefore supblk in buffer - * known as SUPERBLOCK - * returns: 0 if error, nonzero iff we were able to find the file successfully - * postconditions: on a nonzero return, buffer known as INODE contains the - * inode of the file we were trying to look up - * side effects: messes up GROUP_DESC buffer area - */ -int -ext2fs_dir (char *dirname) -{ - int current_ino = EXT2_ROOT_INO; /* start at the root */ - int updir_ino = current_ino; /* the parent of the current directory */ - int group_id; /* which group the inode is in */ - int group_desc; /* fs pointer to that group */ - int desc; /* index within that group */ - int ino_blk; /* fs pointer of the inode's information */ - int str_chk = 0; /* used to hold the results of a string compare */ - struct ext2_group_desc *gdp; - struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */ - - char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ - int link_count = 0; - - char *rest; - char ch; /* temp char holder */ - - int off; /* offset within block of directory entry (off mod blocksize) */ - int loc; /* location within a directory */ - int blk; /* which data blk within dir entry (off div blocksize) */ - long map; /* fs pointer of a particular block from dir entry */ - struct ext2_dir_entry *dp; /* pointer to directory entry */ -#ifdef E2DEBUG - unsigned char *i; -#endif /* E2DEBUG */ - - /* loop invariants: - current_ino = inode to lookup - dirname = pointer to filename component we are cur looking up within - the directory known pointed to by current_ino (if any) - */ - - while (1) - { -#ifdef E2DEBUG - printf ("inode %d\n", current_ino); - printf ("dirname=%s\n", dirname); -#endif /* E2DEBUG */ - - /* look up an inode */ - group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group); - group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); - desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1); -#ifdef E2DEBUG - printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group, - EXT2_DESC_PER_BLOCK (SUPERBLOCK)); - printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc); -#endif /* E2DEBUG */ - if (!ext2_rdfsb ( - (WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block), - (int) GROUP_DESC)) - { - return 0; - } - gdp = GROUP_DESC; - ino_blk = gdp[desc].bg_inode_table + - (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group)) - >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); -#ifdef E2DEBUG - printf ("inode table fsblock=%d\n", ino_blk); -#endif /* E2DEBUG */ - if (!ext2_rdfsb (ino_blk, (int) INODE)) - { - return 0; - } - - /* reset indirect blocks! */ - mapblock2 = mapblock1 = -1; - - raw_inode = INODE + - ((current_ino - 1) - & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1)); -#ifdef E2DEBUG - printf ("ipb=%d, sizeof(inode)=%d\n", - (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)), - sizeof (struct ext2_inode)); - printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode); - printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE); - for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode; - i++) - { - printf ("%c", "0123456789abcdef"[*i >> 4]); - printf ("%c", "0123456789abcdef"[*i % 16]); - if (!((i + 1 - (unsigned char *) INODE) % 16)) - { - printf ("\n"); - } - else - { - printf (" "); - } - } - printf ("first word=%x\n", *((int *) raw_inode)); -#endif /* E2DEBUG */ - - /* copy inode to fixed location */ - memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode)); - -#ifdef E2DEBUG - printf ("first word=%x\n", *((int *) INODE)); -#endif /* E2DEBUG */ - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (INODE->i_mode)) - { - int len; - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - - /* Find out how long our remaining name is. */ - len = 0; - while (dirname[len] && !isspace (dirname[len])) - len++; - - /* Get the symlink size. */ - filemax = (INODE->i_size); - if (filemax + len > sizeof (linkbuf) - 2) - { - errnum = ERR_FILELENGTH; - return 0; - } - - if (len) - { - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - memmove (linkbuf + filemax, dirname, len); - } - linkbuf[filemax + len] = '\0'; - - /* Read the symlink data. */ - if (INODE->i_blocks) - { - /* Read the necessary blocks, and reset the file pointer. */ - len = grub_read (linkbuf, filemax); - filepos = 0; - if (!len) - return 0; - } - else - { - /* Copy the data directly from the inode. */ - len = filemax; - memmove (linkbuf, (char *) INODE->i_block, len); - } - -#ifdef E2DEBUG - printf ("symlink=%s\n", linkbuf); -#endif - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - current_ino = EXT2_ROOT_INO; - updir_ino = current_ino; - } - else - { - /* Relative, so look it up in our parent directory. */ - current_ino = updir_ino; - } - - /* Try again using the new name. */ - continue; - } - - /* if end of filename, INODE points to the file's inode */ - if (!*dirname || isspace (*dirname)) - { - if (!S_ISREG (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = (INODE->i_size); - return 1; - } - - /* else we have to traverse a directory */ - updir_ino = current_ino; - - /* skip over slashes */ - while (*dirname == '/') - dirname++; - - /* if this isn't a directory of sufficient size to hold our file, abort */ - if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - /* skip to next slash or end of filename (space) */ - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; - rest++); - - /* look through this directory and find the next filename component */ - /* invariant: rest points to slash after the next filename component */ - *rest = 0; - loc = 0; - - do - { - -#ifdef E2DEBUG - printf ("dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc); -#endif /* E2DEBUG */ - - /* if our location/byte offset into the directory exceeds the size, - give up */ - if (loc >= INODE->i_size) - { - if (print_possibilities < 0) - { -# if 0 - putchar ('\n'); -# endif - } - else - { - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - return (print_possibilities < 0); - } - - /* else, find the (logical) block component of our location */ - blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); - - /* we know which logical block of the directory entry we are looking - for, now we have to translate that to the physical (fs) block on - the disk */ - map = ext2fs_block_map (blk); -#ifdef E2DEBUG - printf ("fs block=%d\n", map); -#endif /* E2DEBUG */ - mapblock2 = -1; - if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); - dp = (struct ext2_dir_entry *) (DATABLOCK2 + off); - /* advance loc prematurely to next on-disk directory entry */ - loc += dp->rec_len; - - /* NOTE: ext2fs filenames are NOT null-terminated */ - -#ifdef E2DEBUG - printf ("directory entry ino=%d\n", dp->inode); - if (dp->inode) - printf ("entry=%s\n", dp->name); -#endif /* E2DEBUG */ - - if (dp->inode) - { - int saved_c = dp->name[dp->name_len]; - - dp->name[dp->name_len] = 0; - str_chk = substring (dirname, dp->name); - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/' - && (!*dirname || str_chk <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (dp->name); - } -# endif - - dp->name[dp->name_len] = saved_c; - } - - } - while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); - - current_ino = dp->inode; - *(dirname = rest) = ch; - } - /* never get here */ -} - -#endif /* FSYS_EXT2_FS */ diff --git a/src/filo/fs/fsys_fat.c b/src/filo/fs/fsys_fat.c deleted file mode 100644 index 3f85bd6c..00000000 --- a/src/filo/fs/fsys_fat.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_FAT - -#include "shared.h" -#include "filesys.h" -#include "fat.h" -#include -#include "string.h" - -struct fat_superblock -{ - int fat_offset; - int fat_length; - int fat_size; - int root_offset; - int root_max; - int data_offset; - - int num_sectors; - int num_clust; - int clust_eof_marker; - int sects_per_clust; - int sectsize_bits; - int clustsize_bits; - int root_cluster; - - int cached_fat; - int file_cluster; - int current_cluster_num; - int current_cluster; -}; - -/* pointer(s) into filesystem info buffer for DOS stuff */ -#define FAT_SUPER ( (struct fat_superblock *) \ - ( FSYS_BUF + 32256) )/* 512 bytes long */ -#define FAT_BUF ( FSYS_BUF + 30208 ) /* 4 sector FAT buffer */ -#define NAME_BUF ( FSYS_BUF + 29184 ) /* Filename buffer (833 bytes) */ - -#define FAT_CACHE_SIZE 2048 - -static __inline__ unsigned long -log2 (unsigned long word) -{ - __asm__ ("bsfl %1,%0" - : "=r" (word) - : "r" (word)); - return word; -} - -int -fat_mount (void) -{ - struct fat_bpb bpb; - __u32 magic, first_fat; - - /* Check partition type for harddisk */ - if (((current_drive & 0x80) || (current_slice != 0)) - && ! IS_PC_SLICE_TYPE_FAT (current_slice) - && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_MSDOS))) - return 0; - - /* Read bpb */ - if (! devread (0, 0, sizeof (bpb), (char *) &bpb)) - return 0; - - /* Check if the number of sectors per cluster is zero here, to avoid - zero division. */ - if (bpb.sects_per_clust == 0) - return 0; - - FAT_SUPER->sectsize_bits = log2 (FAT_CVT_U16 (bpb.bytes_per_sect)); - FAT_SUPER->clustsize_bits - = FAT_SUPER->sectsize_bits + log2 (bpb.sects_per_clust); - - /* Fill in info about super block */ - FAT_SUPER->num_sectors = FAT_CVT_U16 (bpb.short_sectors) - ? FAT_CVT_U16 (bpb.short_sectors) : bpb.long_sectors; - - /* FAT offset and length */ - FAT_SUPER->fat_offset = FAT_CVT_U16 (bpb.reserved_sects); - FAT_SUPER->fat_length = - bpb.fat_length ? bpb.fat_length : bpb.fat32_length; - - /* Rootdir offset and length for FAT12/16 */ - FAT_SUPER->root_offset = - FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length; - FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * FAT_CVT_U16(bpb.dir_entries); - - /* Data offset and number of clusters */ - FAT_SUPER->data_offset = - FAT_SUPER->root_offset - + ((FAT_SUPER->root_max - 1) >> FAT_SUPER->sectsize_bits) + 1; - FAT_SUPER->num_clust = - 2 + ((FAT_SUPER->num_sectors - FAT_SUPER->data_offset) - / bpb.sects_per_clust); - FAT_SUPER->sects_per_clust = bpb.sects_per_clust; - - if (!bpb.fat_length) - { - /* This is a FAT32 */ - if (FAT_CVT_U16(bpb.dir_entries)) - return 0; - - if (bpb.flags & 0x0080) - { - /* FAT mirroring is disabled, get active FAT */ - int active_fat = bpb.flags & 0x000f; - if (active_fat >= bpb.num_fats) - return 0; - FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length; - } - - FAT_SUPER->fat_size = 8; - FAT_SUPER->root_cluster = bpb.root_cluster; - - /* Yes the following is correct. FAT32 should be called FAT28 :) */ - FAT_SUPER->clust_eof_marker = 0xffffff8; - } - else - { - if (!FAT_SUPER->root_max) - return 0; - - FAT_SUPER->root_cluster = -1; - if (FAT_SUPER->num_clust > FAT_MAX_12BIT_CLUST) - { - FAT_SUPER->fat_size = 4; - FAT_SUPER->clust_eof_marker = 0xfff8; - } - else - { - FAT_SUPER->fat_size = 3; - FAT_SUPER->clust_eof_marker = 0xff8; - } - } - - - /* Now do some sanity checks */ - - if (FAT_CVT_U16(bpb.bytes_per_sect) != (1 << FAT_SUPER->sectsize_bits) - || FAT_CVT_U16(bpb.bytes_per_sect) != SECTOR_SIZE - || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits - - FAT_SUPER->sectsize_bits)) - || FAT_SUPER->num_clust <= 2 - || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) - > FAT_SUPER->fat_length)) - return 0; - - /* kbs: Media check on first FAT entry [ported from PUPA] */ - - if (!devread(FAT_SUPER->fat_offset, 0, - sizeof(first_fat), (char *)&first_fat)) - return 0; - - if (FAT_SUPER->fat_size == 8) - { - first_fat &= 0x0fffffff; - magic = 0x0fffff00; - } - else if (FAT_SUPER->fat_size == 4) - { - first_fat &= 0x0000ffff; - magic = 0xff00; - } - else - { - first_fat &= 0x00000fff; - magic = 0x0f00; - } - - if (first_fat != (magic | bpb.media)) - return 0; - - FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE; - return 1; -} - -int -fat_read (char *buf, int len) -{ - int logical_clust; - int offset; - int ret = 0; - int size; - int count = 64; - - if (FAT_SUPER->file_cluster < 0) - { - /* root directory for fat16 */ - size = FAT_SUPER->root_max - filepos; - if (size > len) - size = len; - if (!devread(FAT_SUPER->root_offset, filepos, size, buf)) - return 0; - filepos += size; - return size; - } - - logical_clust = filepos >> FAT_SUPER->clustsize_bits; - offset = (filepos & ((1 << FAT_SUPER->clustsize_bits) - 1)); - if (logical_clust < FAT_SUPER->current_cluster_num) - { - FAT_SUPER->current_cluster_num = 0; - FAT_SUPER->current_cluster = FAT_SUPER->file_cluster; - } - - while (len > 0) - { - int sector; - while (logical_clust > FAT_SUPER->current_cluster_num) - { - /* calculate next cluster */ - int fat_entry = - FAT_SUPER->current_cluster * FAT_SUPER->fat_size; - int next_cluster; - int cached_pos = (fat_entry - FAT_SUPER->cached_fat); - - if (cached_pos < 0 || - (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE) - { - FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1)); - cached_pos = (fat_entry - FAT_SUPER->cached_fat); - sector = FAT_SUPER->fat_offset - + FAT_SUPER->cached_fat / (2*SECTOR_SIZE); - if (!devread (sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF)) - return 0; - } - next_cluster = * (unsigned long *) (FAT_BUF + (cached_pos >> 1)); - if (FAT_SUPER->fat_size == 3) - { - if (cached_pos & 1) - next_cluster >>= 4; - next_cluster &= 0xFFF; - } - else if (FAT_SUPER->fat_size == 4) - next_cluster &= 0xFFFF; - - if (next_cluster >= FAT_SUPER->clust_eof_marker) - return ret; - if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - - FAT_SUPER->current_cluster = next_cluster; - FAT_SUPER->current_cluster_num++; - } - - sector = FAT_SUPER->data_offset + - ((FAT_SUPER->current_cluster - 2) << (FAT_SUPER->clustsize_bits - - FAT_SUPER->sectsize_bits)); - size = (1 << FAT_SUPER->clustsize_bits) - offset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread(sector, offset, size, buf); - - disk_read_func = NULL; - - len -= size; - buf += size; - ret += size; - filepos += size; - logical_clust++; - offset = 0; - if(count--==0) { - count = 32; - printf("."); - } - } - -// printf("\n"); - return errnum ? 0 : ret; -} - -int -fat_dir (char *dirname) -{ - char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH]; - char *filename = (char *) NAME_BUF; - int attrib = FAT_ATTRIB_DIR; -#ifndef STAGE1_5 - int do_possibilities = 0; -#endif - - /* XXX I18N: - * the positions 2,4,6 etc are high bytes of a 16 bit unicode char - */ - static unsigned char longdir_pos[] = - { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 }; - int slot = -2; - int alias_checksum = -1; - - FAT_SUPER->file_cluster = FAT_SUPER->root_cluster; - filepos = 0; - FAT_SUPER->current_cluster_num = MAXINT; - - /* main loop to find desired directory entry */ - loop: - - /* if we have a real file (and we're not just printing possibilities), - then this is where we want to exit */ - - if (!*dirname || isspace (*dirname)) - { - if (attrib & FAT_ATTRIB_DIR) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - return 1; - } - - /* continue with the file/directory name interpretation */ - - while (*dirname == '/') - dirname++; - - if (!(attrib & FAT_ATTRIB_DIR)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - /* Directories don't have a file size */ - filemax = MAXINT; - - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - - *rest = 0; - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/') - do_possibilities = 1; -# endif - - while (1) - { - if (fat_read (dir_buf, FAT_DIRENTRY_LENGTH) != FAT_DIRENTRY_LENGTH - || dir_buf[0] == 0) - { - if (!errnum) - { -# ifndef STAGE1_5 - if (print_possibilities < 0) - { -#if 0 - putchar ('\n'); -#endif - return 1; - } -# endif /* STAGE1_5 */ - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - - return 0; - } - - if (FAT_DIRENTRY_ATTRIB (dir_buf) == FAT_ATTRIB_LONGNAME) - { - /* This is a long filename. The filename is build from back - * to front and may span multiple entries. To bind these - * entries together they all contain the same checksum over - * the short alias. - * - * The id field tells if this is the first entry (the last - * part) of the long filename, and also at which offset this - * belongs. - * - * We just write the part of the long filename this entry - * describes and continue with the next dir entry. - */ - int i, offset; - unsigned char id = FAT_LONGDIR_ID(dir_buf); - - if ((id & 0x40)) - { - id &= 0x3f; - slot = id; - filename[slot * 13] = 0; - alias_checksum = FAT_LONGDIR_ALIASCHECKSUM(dir_buf); - } - - if (id != slot || slot == 0 - || alias_checksum != FAT_LONGDIR_ALIASCHECKSUM(dir_buf)) - { - alias_checksum = -1; - continue; - } - - slot--; - offset = slot * 13; - - for (i=0; i < 13; i++) - filename[offset+i] = dir_buf[longdir_pos[i]]; - continue; - } - - if (!FAT_DIRENTRY_VALID (dir_buf)) - continue; - - if (alias_checksum != -1 && slot == 0) - { - int i; - unsigned char sum; - - slot = -2; - for (sum = 0, i = 0; i< 11; i++) - sum = ((sum >> 1) | (sum << 7)) + dir_buf[i]; - - if (sum == alias_checksum) - { -# ifndef STAGE1_5 - if (do_possibilities) - goto print_filename; -# endif /* STAGE1_5 */ - - if (substring (dirname, filename) == 0) - break; - } - } - - /* XXX convert to 8.3 filename format here */ - { - int i, j, c; - - for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i])) - && !isspace (c); i++); - - filename[i++] = '.'; - - for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j])) - && !isspace (c); j++); - - if (j == 0) - i--; - - filename[i + j] = 0; - } - -# ifndef STAGE1_5 - if (do_possibilities) - { - print_filename: - if (substring (dirname, filename) <= 0) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (filename); - } - continue; - } -# endif /* STAGE1_5 */ - - if (substring (dirname, filename) == 0) - break; - } - - *(dirname = rest) = ch; - - attrib = FAT_DIRENTRY_ATTRIB (dir_buf); - filemax = FAT_DIRENTRY_FILELENGTH (dir_buf); - filepos = 0; - FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf); - FAT_SUPER->current_cluster_num = MAXINT; - - /* go back to main loop at top of function */ - goto loop; -} - -#endif /* FSYS_FAT */ diff --git a/src/filo/fs/fsys_iso9660.c b/src/filo/fs/fsys_iso9660.c deleted file mode 100644 index 9e667914..00000000 --- a/src/filo/fs/fsys_iso9660.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader) - * including Rock Ridge Extensions support - * - * Copyright (C) 1998, 1999 Kousuke Takai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * References: - * linux/fs/isofs/rock.[ch] - * mkisofs-1.11.1/diag/isoinfo.c - * mkisofs-1.11.1/iso9660.h - * (all are written by Eric Youngdale) - * - * Modifications by: - * Leonid Lisovskiy 2003 - */ - -/* - * Modified to make it work with FILO - * 2003-10 by SONE Takeshi - */ - -#ifdef FSYS_ISO9660 - -#include -#include "string.h" -#include "shared.h" -#include "filesys.h" -#include "iso9660.h" -#define DEBUG_THIS 1 -#include - -struct iso_superblock { - unsigned long vol_sector; - - unsigned long file_start; -}; - -#define ISO_SUPER ((struct iso_superblock *)(FSYS_BUF)) -#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048)) -#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 4096)) -#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 6144)) -#define NAME_BUF ((unsigned char *)(FSYS_BUF + 8192)) - - -static inline unsigned long -log2 (unsigned long word) -{ - asm volatile ("bsfl %1,%0" -: "=r" (word) -: "r" (word)); - return word; -} - -static int -iso9660_devread (int sector, int byte_offset, int byte_len, char *buf) -{ - /* FILO uses 512-byte "soft" sector, and ISO-9660 uses 2048-byte - * CD-ROM sector */ - return devread(sector<<2, byte_offset, byte_len, buf); -} - -int -iso9660_mount (void) -{ - unsigned int sector; - - /* - * Because there is no defined slice type ID for ISO-9660 filesystem, - * this test will pass only either (1) if entire disk is used, or - * (2) if current partition is BSD style sub-partition whose ID is - * ISO-9660. - */ - /*if ((current_partition != 0xFFFFFF) - && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660)) - return 0;*/ - - /* - * Currently, only FIRST session of MultiSession disks are supported !!! - */ - for (sector = 16 ; sector < 32 ; sector++) - { - if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC)) - break; - /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */ - if (CHECK4(&PRIMDESC->type, ISO_VD_PRIMARY, 'C', 'D', '0') - && CHECK2(PRIMDESC->id + 3, '0', '1')) - { - ISO_SUPER->vol_sector = sector; - ISO_SUPER->file_start = 0; - fsmax = PRIMDESC->volume_space_size.l; - return 1; - } - } - - return 0; -} - -int -iso9660_dir (char *dirname) -{ - struct iso_directory_record *idr; - RR_ptr_t rr_ptr; - struct rock_ridge *ce_ptr; - unsigned int pathlen; - int size; - unsigned int extent; - unsigned int rr_len; - unsigned char file_type; - unsigned char rr_flag; - - idr = &PRIMDESC->root_directory_record; - ISO_SUPER->file_start = 0; - - do - { - while (*dirname == '/') /* skip leading slashes */ - dirname++; - /* pathlen = strcspn(dirname, "/\n\t "); */ - for (pathlen = 0 ; - dirname[pathlen] - && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ; - pathlen++) - ; - - size = idr->size.l; - extent = idr->extent.l; - - while (size > 0) - { - if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC)) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - extent++; - - idr = (struct iso_directory_record *)DIRREC; - for (; idr->length.l > 0; - idr = (struct iso_directory_record *)((char *)idr + idr->length.l) ) - { - const char *name = idr->name; - unsigned int name_len = idr->name_len.l; - - file_type = (idr->flags.l & 2) ? ISO_DIRECTORY : ISO_REGULAR; - if (name_len == 1) - { - if ((name[0] == 0) || /* self */ - (name[0] == 1)) /* parent */ - continue; - } - if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1')) - { - name_len -= 2; /* truncate trailing file version */ - if (name_len > 1 && name[name_len - 1] == '.') - name_len--; /* truncate trailing dot */ - } - - /* - * Parse Rock-Ridge extension - */ - rr_len = (idr->length.l - idr->name_len.l - - (unsigned char)sizeof(struct iso_directory_record) - + (unsigned char)sizeof(idr->name)); - rr_ptr.ptr = ((unsigned char *)idr + idr->name_len.l - + sizeof(struct iso_directory_record) - - sizeof(idr->name)); - if (rr_ptr.i & 1) - rr_ptr.i++, rr_len--; - ce_ptr = NULL; - rr_flag = RR_FLAG_NM | RR_FLAG_PX; - - while (rr_len >= 4) - { - if (rr_ptr.rr->version != 1) - { -#ifndef STAGE1_5 - if (debug) - printf( - "Non-supported version (%d) RockRidge chunk " - "`%c%c'\n", rr_ptr.rr->version, - rr_ptr.rr->signature & 0xFF, - rr_ptr.rr->signature >> 8); -#endif - } - else if (rr_ptr.rr->signature == RRMAGIC('R', 'R') - && rr_ptr.rr->len >= 5) - rr_flag &= rr_ptr.rr->u.rr.flags.l; - else if (rr_ptr.rr->signature == RRMAGIC('N', 'M')) - { - name = rr_ptr.rr->u.nm.name; - name_len = rr_ptr.rr->len - 5; - rr_flag &= ~RR_FLAG_NM; - } - else if (rr_ptr.rr->signature == RRMAGIC('P', 'X') - && rr_ptr.rr->len >= 36) - { - file_type = ((rr_ptr.rr->u.px.mode.l & POSIX_S_IFMT) - == POSIX_S_IFREG - ? ISO_REGULAR - : ((rr_ptr.rr->u.px.mode.l & POSIX_S_IFMT) - == POSIX_S_IFDIR - ? ISO_DIRECTORY : ISO_OTHER)); - rr_flag &= ~RR_FLAG_PX; - } - else if (rr_ptr.rr->signature == RRMAGIC('C', 'E') - && rr_ptr.rr->len >= 28) - ce_ptr = rr_ptr.rr; - if (!rr_flag) - /* - * There is no more extension we expects... - */ - break; - rr_len -= rr_ptr.rr->len; - rr_ptr.ptr += rr_ptr.rr->len; - if (rr_len < 4 && ce_ptr != NULL) - { - /* preserve name before loading new extent. */ - if( RRCONT_BUF <= (unsigned char *)name - && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE ) - { - memcpy(NAME_BUF, name, name_len); - name = NAME_BUF; - } - rr_ptr.ptr = RRCONT_BUF + ce_ptr->u.ce.offset.l; - rr_len = ce_ptr->u.ce.size.l; - if (!iso9660_devread(ce_ptr->u.ce.extent.l, 0, ISO_SECTOR_SIZE, RRCONT_BUF)) - { - errnum = 0; /* this is not fatal. */ - break; - } - ce_ptr = NULL; - } - } /* rr_len >= 4 */ - - filemax = MAXINT; - if (name_len >= pathlen - && !__builtin_memcmp(name, dirname, pathlen)) - { - if (dirname[pathlen] == '/' || !print_possibilities) - { - /* - * DIRNAME is directory component of pathname, - * or we are to open a file. - */ - if (pathlen == name_len) - { - if (dirname[pathlen] == '/') - { - if (file_type != ISO_DIRECTORY) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - goto next_dir_level; - } - if (file_type != ISO_REGULAR) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - ISO_SUPER->file_start = idr->extent.l; - filepos = 0; - filemax = idr->size.l; - return 1; - } - } - else /* Completion */ - { -#ifndef STAGE1_5 - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - memcpy(NAME_BUF, name, name_len); - NAME_BUF[name_len] = '\0'; - print_a_completion (NAME_BUF); -#endif - } - } - } /* for */ - - size -= ISO_SECTOR_SIZE; - } /* size>0 */ - - if (dirname[pathlen] == '/' || print_possibilities >= 0) - { - errnum = ERR_FILE_NOT_FOUND; - return 0; - } - -next_dir_level: - dirname += pathlen; - - } while (*dirname == '/'); - - return 1; -} - -int -iso9660_read (char *buf, int len) -{ - int sector, blkoffset, size, ret; - - if (ISO_SUPER->file_start == 0) - return 0; - - ret = 0; - blkoffset = filepos & (ISO_SECTOR_SIZE - 1); - sector = filepos >> ISO_SECTOR_BITS; - while (len > 0) - { - size = ISO_SECTOR_SIZE - blkoffset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - if (!iso9660_devread(ISO_SUPER->file_start + sector, blkoffset, size, buf)) - return 0; - - disk_read_func = NULL; - - len -= size; - buf += size; - ret += size; - filepos += size; - sector++; - blkoffset = 0; - } - - return ret; -} - -#endif /* FSYS_ISO9660 */ - diff --git a/src/filo/fs/fsys_jfs.c b/src/filo/fs/fsys_jfs.c deleted file mode 100644 index 307f8363..00000000 --- a/src/filo/fs/fsys_jfs.c +++ /dev/null @@ -1,403 +0,0 @@ -/* fsys_jfs.c - an implementation for the IBM JFS file system */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_JFS - -#include "shared.h" -#include "filesys.h" -#include "jfs.h" - -#define MAX_LINK_COUNT 8 - -#define DTTYPE_INLINE 0 -#define DTTYPE_PAGE 1 - -struct jfs_info -{ - int bsize; - int l2bsize; - int bdlog; - int xindex; - int xlastindex; - int sindex; - int slastindex; - int de_index; - int dttype; - xad_t *xad; - ldtentry_t *de; -}; - -static struct jfs_info jfs; - -#define xtpage ((xtpage_t *)FSYS_BUF) -#define dtpage ((dtpage_t *)((char *)FSYS_BUF + 4096)) -#define fileset ((dinode_t *)((char *)FSYS_BUF + 8192)) -#define inode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t))) -#define dtroot ((dtroot_t *)(&inode->di_btroot)) - -static ldtentry_t de_always[2] = { - {1, -1, 2, {'.', '.'}}, - {1, -1, 1, {'.'}} -}; - -static int -isinxt (s64 key, s64 offset, s64 len) -{ - return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; -} - -static xad_t * -first_extent (dinode_t *di) -{ - xtpage_t *xtp; - - jfs.xindex = 2; - xtp = (xtpage_t *)&di->di_btroot; - jfs.xad = &xtp->xad[2]; - if (xtp->header.flag & BT_LEAF) { - jfs.xlastindex = xtp->header.nextindex; - } else { - do { - devread (addressXAD (jfs.xad) << jfs.bdlog, 0, - sizeof(xtpage_t), (char *)xtpage); - jfs.xad = &xtpage->xad[2]; - } while (!(xtpage->header.flag & BT_LEAF)); - jfs.xlastindex = xtpage->header.nextindex; - } - - return jfs.xad; -} - -static xad_t * -next_extent (void) -{ - if (++jfs.xindex < jfs.xlastindex) { - } else if (xtpage->header.next) { - devread (xtpage->header.next << jfs.bdlog, 0, - sizeof(xtpage_t), (char *)xtpage); - jfs.xlastindex = xtpage->header.nextindex; - jfs.xindex = XTENTRYSTART; - jfs.xad = &xtpage->xad[XTENTRYSTART]; - } else { - return NULL; - } - return ++jfs.xad; -} - - -static void -di_read (u32 inum, dinode_t *di) -{ - s64 key; - u32 xd, ioffset; - s64 offset; - xad_t *xad; - pxd_t pxd; - - key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize; - xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT; - ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE; - xad = first_extent (fileset); - do { - offset = offsetXAD (xad); - if (isinxt (key, offset, lengthXAD (xad))) { - devread ((addressXAD (xad) + key - offset) << jfs.bdlog, - 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd); - devread (addressPXD (&pxd) << jfs.bdlog, - ioffset, DISIZE, (char *)di); - break; - } - } while ((xad = next_extent ())); -} - -static ldtentry_t * -next_dentry (void) -{ - ldtentry_t *de; - s8 *stbl; - - if (jfs.dttype == DTTYPE_INLINE) { - if (jfs.sindex < jfs.slastindex) { - return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]]; - } - } else { - de = (ldtentry_t *)dtpage->slot; - stbl = (s8 *)&de[(int)dtpage->header.stblindex]; - if (jfs.sindex < jfs.slastindex) { - return &de[(int)stbl[jfs.sindex++]]; - } else if (dtpage->header.next) { - devread (dtpage->header.next << jfs.bdlog, 0, - sizeof(dtpage_t), (char *)dtpage); - jfs.slastindex = dtpage->header.nextindex; - jfs.sindex = 1; - return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]]; - } - } - - return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL; -} - -static ldtentry_t * -first_dentry (void) -{ - dtroot_t *dtr; - pxd_t *xd; - idtentry_t *de; - - dtr = (dtroot_t *)&inode->di_btroot; - jfs.sindex = 0; - jfs.de_index = 0; - - de_always[0].inumber = inode->di_parent; - de_always[1].inumber = inode->di_number; - if (dtr->header.flag & BT_LEAF) { - jfs.dttype = DTTYPE_INLINE; - jfs.slastindex = dtr->header.nextindex; - } else { - de = (idtentry_t *)dtpage->slot; - jfs.dttype = DTTYPE_PAGE; - xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd; - for (;;) { - devread (addressPXD (xd) << jfs.bdlog, 0, - sizeof(dtpage_t), (char *)dtpage); - if (dtpage->header.flag & BT_LEAF) - break; - xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd; - } - jfs.slastindex = dtpage->header.nextindex; - } - - return next_dentry (); -} - - -static dtslot_t * -next_dslot (int next) -{ - return (jfs.dttype == DTTYPE_INLINE) - ? (dtslot_t *)&dtroot->slot[next] - : &((dtslot_t *)dtpage->slot)[next]; -} - -static void -uni2ansi (UniChar *uni, char *ansi, int len) -{ - for (; len; len--, uni++) - *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni; -} - -int -jfs_mount (void) -{ - struct jfs_superblock super; - - if (part_length < MINJFS >> SECTOR_BITS - || !devread (SUPER1_OFF >> SECTOR_BITS, 0, - sizeof(struct jfs_superblock), (char *)&super) - || (super.s_magic != JFS_MAGIC) - || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I, - 0, DISIZE, (char*)fileset)) { - return 0; - } - - jfs.bsize = super.s_bsize; - jfs.l2bsize = super.s_l2bsize; - jfs.bdlog = jfs.l2bsize - SECTOR_BITS; - - return 1; -} - -int -jfs_read (char *buf, int len) -{ - xad_t *xad; - s64 endofprev, endofcur; - s64 offset, xadlen; - int toread, startpos, endpos; - - startpos = filepos; - endpos = filepos + len; - endofprev = (1ULL << 62) - 1; - xad = first_extent (inode); - do { - offset = offsetXAD (xad); - xadlen = lengthXAD (xad); - if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) { - endofcur = (offset + xadlen) << jfs.l2bsize; - toread = (endofcur >= endpos) - ? len : (endofcur - filepos); - - disk_read_func = disk_read_hook; - devread (addressXAD (xad) << jfs.bdlog, - filepos - (offset << jfs.l2bsize), toread, buf); - disk_read_func = NULL; - - buf += toread; - len -= toread; - filepos += toread; - } else if (offset > endofprev) { - toread = ((offset << jfs.l2bsize) >= endpos) - ? len : ((offset - endofprev) << jfs.l2bsize); - len -= toread; - filepos += toread; - for (; toread; toread--) { - *buf++ = 0; - } - continue; - } - endofprev = offset + xadlen; - xad = next_extent (); - } while (len > 0 && xad); - - return filepos - startpos; -} - -int -jfs_dir (char *dirname) -{ - char *ptr, *rest, ch; - ldtentry_t *de; - dtslot_t *ds; - u32 inum, parent_inum; - s64 di_size; - u32 di_mode; - int namlen, cmp, n, link_count; - char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX]; - - parent_inum = inum = ROOT_I; - link_count = 0; - for (;;) { - di_read (inum, inode); - di_size = inode->di_size; - di_mode = inode->di_mode; - - if ((di_mode & IFMT) == IFLNK) { - if (++link_count > MAX_LINK_COUNT) { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - if (di_size < (di_mode & INLINEEA ? 256 : 128)) { - grub_memmove (linkbuf, inode->di_fastsymlink, di_size); - n = di_size; - } else if (di_size < JFS_PATH_MAX - 1) { - filepos = 0; - filemax = di_size; - n = jfs_read (linkbuf, filemax); - } else { - errnum = ERR_FILELENGTH; - return 0; - } - - inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum; - while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++)); - linkbuf[n] = 0; - dirname = linkbuf; - continue; - } - - if (!*dirname || isspace (*dirname)) { - if ((di_mode & IFMT) != IFREG) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - filepos = 0; - filemax = di_size; - return 1; - } - - if ((di_mode & IFMT) != IFDIR) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - for (; *dirname == '/'; dirname++); - - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - *rest = 0; - - de = first_dentry (); - for (;;) { - namlen = de->namlen; - if (de->next == -1) { - uni2ansi (de->name, namebuf, namlen); - namebuf[namlen] = 0; - } else { - uni2ansi (de->name, namebuf, DTLHDRDATALEN); - ptr = namebuf; - ptr += DTLHDRDATALEN; - namlen -= DTLHDRDATALEN; - ds = next_dslot (de->next); - while (ds->next != -1) { - uni2ansi (ds->name, ptr, DTSLOTDATALEN); - ptr += DTSLOTDATALEN; - namlen -= DTSLOTDATALEN; - ds = next_dslot (ds->next); - } - uni2ansi (ds->name, ptr, namlen); - ptr += namlen; - *ptr = 0; - } - - cmp = (!*dirname) ? -1 : substring (dirname, namebuf); -#ifndef STAGE1_5 - if (print_possibilities && ch != '/' - && cmp <= 0) { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (namebuf); - } else -#endif - if (cmp == 0) { - parent_inum = inum; - inum = de->inumber; - *(dirname = rest) = ch; - break; - } - de = next_dentry (); - if (de == NULL) { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - } - } -} - -int -jfs_embed (int *start_sector, int needed_sectors) -{ - struct jfs_superblock super; - - if (needed_sectors > 63 - || !devread (SUPER1_OFF >> SECTOR_BITS, 0, - sizeof (struct jfs_superblock), - (char *)&super) - || (super.s_magic != JFS_MAGIC)) { - return 0; - } - - *start_sector = 1; - return 1; -} - -#endif /* FSYS_JFS */ diff --git a/src/filo/fs/fsys_minix.c b/src/filo/fs/fsys_minix.c deleted file mode 100644 index 5c76796a..00000000 --- a/src/filo/fs/fsys_minix.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Restrictions: - This is MINIX V1 only (yet) - Disk creation is like: - mkfs.minix -c DEVICE -*/ - -#ifdef FSYS_MINIX - -#include "shared.h" -#include "filesys.h" - -/* #define DEBUG_MINIX */ - -/* indirect blocks */ -static int mapblock1, mapblock2, namelen; - -/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ -#define DEV_BSIZE 512 - -/* include/linux/fs.h */ -#define BLOCK_SIZE_BITS 10 -#define BLOCK_SIZE (1<. Oh well. */ -#define MINIX_LINK_MAX 250 -#define MINIX2_LINK_MAX 65530 - -#define MINIX_I_MAP_SLOTS 8 -#define MINIX_Z_MAP_SLOTS 64 -#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ -#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ -#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ -#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ -#define MINIX_VALID_FS 0x0001 /* Clean fs. */ -#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ - -#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) -#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) - -#define MINIX_V1 0x0001 /* original minix fs */ -#define MINIX_V2 0x0002 /* minix V2 fs */ - -/* originally this is : -#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version - here we have */ -#define INODE_VERSION(inode) (SUPERBLOCK->s_version) - -/* - * This is the original minix inode layout on disk. - * Note the 8-bit gid and atime and ctime. - */ -struct minix_inode { - __u16 i_mode; - __u16 i_uid; - __u32 i_size; - __u32 i_time; - __u8 i_gid; - __u8 i_nlinks; - __u16 i_zone[9]; -}; - -/* - * The new minix inode has all the time entries, as well as - * long block numbers and a third indirect block (7+1+1+1 - * instead of 7+1+1). Also, some previously 8-bit values are - * now 16-bit. The inode is now 64 bytes instead of 32. - */ -struct minix2_inode { - __u16 i_mode; - __u16 i_nlinks; - __u16 i_uid; - __u16 i_gid; - __u32 i_size; - __u32 i_atime; - __u32 i_mtime; - __u32 i_ctime; - __u32 i_zone[10]; -}; - -/* - * minix super-block data on disk - */ -struct minix_super_block { - __u16 s_ninodes; - __u16 s_nzones; - __u16 s_imap_blocks; - __u16 s_zmap_blocks; - __u16 s_firstdatazone; - __u16 s_log_zone_size; - __u32 s_max_size; - __u16 s_magic; - __u16 s_state; - __u32 s_zones; -}; - -struct minix_dir_entry { - __u16 inode; - char name[0]; -}; - -/* made up, these are pointers into FSYS_BUF */ -/* read once, always stays there: */ -#define SUPERBLOCK \ - ((struct minix_super_block *)(FSYS_BUF)) -#define INODE \ - ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE)) -#define DATABLOCK1 \ - ((int)((int)INODE + sizeof(struct minix_inode))) -#define DATABLOCK2 \ - ((int)((int)DATABLOCK1 + BLOCK_SIZE)) - -/* linux/stat.h */ -#define S_IFMT 00170000 -#define S_IFLNK 0120000 -#define S_IFREG 0100000 -#define S_IFDIR 0040000 -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) - -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -/* check filesystem types and read superblock into memory buffer */ -int -minix_mount (void) -{ - if (((current_drive & 0x80) || current_slice != 0) - && ! IS_PC_SLICE_TYPE_MINIX (current_slice) - && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)) - return 0; /* The partition is not of MINIX type */ - - if (part_length < (SBLOCK + - (sizeof (struct minix_super_block) / DEV_BSIZE))) - return 0; /* The partition is too short */ - - if (!devread (SBLOCK, 0, sizeof (struct minix_super_block), - (char *) SUPERBLOCK)) - return 0; /* Cannot read superblock */ - - switch (SUPERBLOCK->s_magic) - { - case MINIX_SUPER_MAGIC: - namelen = 14; - break; - case MINIX_SUPER_MAGIC2: - namelen = 30; - break; - default: - return 0; /* Unsupported type */ - } - - return 1; -} - -/* Takes a file system block number and reads it into BUFFER. */ -static int -minix_rdfsb (int fsblock, int buffer) -{ - return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0, - BLOCK_SIZE, (char *) buffer); -} - -/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into - a physical block (the location in the file system) via an inode. */ -static int -minix_block_map (int logical_block) -{ - int i; - - if (logical_block < 7) - return INODE->i_zone[logical_block]; - - logical_block -= 7; - if (logical_block < 512) - { - i = INODE->i_zone[7]; - - if (!i || ((mapblock1 != 1) - && !minix_rdfsb (i, DATABLOCK1))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 1; - return ((__u16 *) DATABLOCK1) [logical_block]; - } - - logical_block -= 512; - i = INODE->i_zone[8]; - if (!i || ((mapblock1 != 2) - && !minix_rdfsb (i, DATABLOCK1))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock1 = 2; - i = ((__u16 *) DATABLOCK1)[logical_block >> 9]; - if (!i || ((mapblock2 != i) - && !minix_rdfsb (i, DATABLOCK2))) - { - errnum = ERR_FSYS_CORRUPT; - return -1; - } - mapblock2 = i; - return ((__u16 *) DATABLOCK2)[logical_block & 511]; -} - -/* read from INODE into BUF */ -int -minix_read (char *buf, int len) -{ - int logical_block; - int offset; - int map; - int ret = 0; - int size = 0; - - while (len > 0) - { - /* find the (logical) block component of our location */ - logical_block = filepos >> BLOCK_SIZE_BITS; - offset = filepos & (BLOCK_SIZE - 1); - map = minix_block_map (logical_block); -#ifdef DEBUG_MINIX - printf ("map=%d\n", map); -#endif - if (map < 0) - break; - - size = BLOCK_SIZE; - size -= offset; - if (size > len) - size = len; - - disk_read_func = disk_read_hook; - - devread (map * (BLOCK_SIZE / DEV_BSIZE), - offset, size, buf); - - disk_read_func = NULL; - - buf += size; - len -= size; - filepos += size; - ret += size; - } - - if (errnum) - ret = 0; - - return ret; -} - -/* preconditions: minix_mount already executed, therefore supblk in buffer - known as SUPERBLOCK - returns: 0 if error, nonzero iff we were able to find the file successfully - postconditions: on a nonzero return, buffer known as INODE contains the - inode of the file we were trying to look up - side effects: none yet */ -int -minix_dir (char *dirname) -{ - int current_ino = MINIX_ROOT_INO; /* start at the root */ - int updir_ino = current_ino; /* the parent of the current directory */ - int ino_blk; /* fs pointer of the inode's info */ - - int str_chk = 0; /* used ot hold the results of a string - compare */ - - struct minix_inode * raw_inode; /* inode info for current_ino */ - - char linkbuf[PATH_MAX]; /* buffer for following sym-links */ - int link_count = 0; - - char * rest; - char ch; - - int off; /* offset within block of directory - entry */ - int loc; /* location within a directory */ - int blk; /* which data blk within dir entry */ - long map; /* fs pointer of a particular block from - dir entry */ - struct minix_dir_entry * dp; /* pointer to directory entry */ - - /* loop invariants: - current_ino = inode to lookup - dirname = pointer to filename component we are cur looking up within - the directory known pointed to by current_ino (if any) */ - -#ifdef DEBUG_MINIX - printf ("\n"); -#endif - - while (1) - { -#ifdef DEBUG_MINIX - printf ("inode %d, dirname %s\n", current_ino, dirname); -#endif - - ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks - + (current_ino - 1) / MINIX_INODES_PER_BLOCK); - if (! minix_rdfsb (ino_blk, (int) INODE)) - return 0; - - /* reset indirect blocks! */ - mapblock2 = mapblock1 = -1; - - raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK); - - /* copy inode to fixed location */ - memmove ((void *) INODE, (void *) raw_inode, - sizeof (struct minix_inode)); - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (INODE->i_mode)) - { - int len; - - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } -#ifdef DEBUG_MINIX - printf ("S_ISLNK (%s)\n", dirname); -#endif - - /* Find out how long our remaining name is. */ - len = 0; - while (dirname[len] && !isspace (dirname[len])) - len++; - - /* Get the symlink size. */ - filemax = (INODE->i_size); - if (filemax + len > sizeof (linkbuf) - 2) - { - errnum = ERR_FILELENGTH; - return 0; - } - - if (len) - { - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - memmove (linkbuf + filemax, dirname, len); - } - linkbuf[filemax + len] = '\0'; - - /* Read the necessary blocks, and reset the file pointer. */ - len = grub_read (linkbuf, filemax); - filepos = 0; - if (!len) - return 0; - -#ifdef DEBUG_MINIX - printf ("symlink=%s\n", linkbuf); -#endif - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - current_ino = MINIX_ROOT_INO; - updir_ino = current_ino; - } - else - { - /* Relative, so look it up in our parent directory. */ - current_ino = updir_ino; - } - - /* Try again using the new name. */ - continue; - } - - /* If end of filename, INODE points to the file's inode */ - if (!*dirname || isspace (*dirname)) - { - if (!S_ISREG (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filemax = (INODE->i_size); - return 1; - } - - /* else we have to traverse a directory */ - updir_ino = current_ino; - - /* skip over slashes */ - while (*dirname == '/') - dirname++; - - /* if this isn't a directory of sufficient size to hold our file, - abort */ - if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - /* skip to next slash or end of filename (space) */ - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; - rest++); - - /* look through this directory and find the next filename component */ - /* invariant: rest points to slash after the next filename component */ - *rest = 0; - loc = 0; - - do - { -#ifdef DEBUG_MINIX - printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc); -#endif - - /* if our location/byte offset into the directory exceeds the size, - give up */ - if (loc >= INODE->i_size) - { - if (print_possibilities < 0) - { -#if 0 - putchar ('\n'); -#endif - } - else - { - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - } - return (print_possibilities < 0); - } - - /* else, find the (logical) block component of our location */ - blk = loc >> BLOCK_SIZE_BITS; - - /* we know which logical block of the directory entry we are looking - for, now we have to translate that to the physical (fs) block on - the disk */ - map = minix_block_map (blk); -#ifdef DEBUG_MINIX - printf ("fs block=%d\n", map); -#endif - mapblock2 = -1; - if ((map < 0) || !minix_rdfsb (map, DATABLOCK2)) - { - errnum = ERR_FSYS_CORRUPT; - *rest = ch; - return 0; - } - off = loc & (BLOCK_SIZE - 1); - dp = (struct minix_dir_entry *) (DATABLOCK2 + off); - /* advance loc prematurely to next on-disk directory entry */ - loc += sizeof (dp->inode) + namelen; - - /* NOTE: minix filenames are NULL terminated if < NAMELEN - else exact */ - -#ifdef DEBUG_MINIX - printf ("directory entry ino=%d\n", dp->inode); - if (dp->inode) - printf ("entry=%s\n", dp->name); -#endif - - if (dp->inode) - { - int saved_c = dp->name[namelen]; - - dp->name[namelen] = 0; - str_chk = substring (dirname, dp->name); - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/' - && (!*dirname || str_chk <= 0)) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (dp->name); - } -# endif - - dp->name[namelen] = saved_c; - } - - } - while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); - - current_ino = dp->inode; - *(dirname = rest) = ch; - } - /* never get here */ -} - -#endif /* FSYS_MINIX */ diff --git a/src/filo/fs/fsys_reiserfs.c b/src/filo/fs/fsys_reiserfs.c deleted file mode 100644 index fbc2d74a..00000000 --- a/src/filo/fs/fsys_reiserfs.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_REISERFS -#include "shared.h" -#include "filesys.h" -#include -#include "string.h" - -#undef REISERDEBUG - -/* Some parts of this code (mainly the structures and defines) are - * from the original reiser fs code, as found in the linux kernel. - */ - -/* include/asm-i386/types.h */ -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; -typedef unsigned long long __u64; - -/* linux/posix_type.h */ -typedef long linux_off_t; - -/* linux/little_endian.h */ -#define __cpu_to_le64(x) ((__u64) (x)) -#define __le64_to_cpu(x) ((__u64) (x)) -#define __cpu_to_le32(x) ((__u32) (x)) -#define __le32_to_cpu(x) ((__u32) (x)) -#define __cpu_to_le16(x) ((__u16) (x)) -#define __le16_to_cpu(x) ((__u16) (x)) - -/* include/linux/reiser_fs.h */ -/* This is the new super block of a journaling reiserfs system */ -struct reiserfs_super_block -{ - __u32 s_block_count; /* blocks count */ - __u32 s_free_blocks; /* free blocks count */ - __u32 s_root_block; /* root block number */ - __u32 s_journal_block; /* journal block number */ - __u32 s_journal_dev; /* journal device number */ - __u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */ - __u32 s_journal_trans_max; /* max number of blocks in a transaction. */ - __u32 s_journal_magic; /* random value made on fs creation */ - __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */ - __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */ - __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */ - __u16 s_blocksize; /* block size */ - __u16 s_oid_maxsize; /* max size of object id array */ - __u16 s_oid_cursize; /* current size of object id array */ - __u16 s_state; /* valid or error */ - char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */ - __u16 s_tree_height; /* height of disk tree */ - __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */ - __u16 s_version; - char s_unused[128]; /* zero filled by mkreiserfs */ -}; - -#define REISERFS_MAX_SUPPORTED_VERSION 2 -#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" -#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" - -#define MAX_HEIGHT 7 - -/* must be correct to keep the desc and commit structs at 4k */ -#define JOURNAL_TRANS_HALF 1018 - -/* first block written in a commit. */ -struct reiserfs_journal_desc { - __u32 j_trans_id; /* id of commit */ - __u32 j_len; /* length of commit. len +1 is the commit block */ - __u32 j_mount_id; /* mount id of this trans*/ - __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */ - char j_magic[12]; -}; - -/* last block written in a commit */ -struct reiserfs_journal_commit { - __u32 j_trans_id; /* must match j_trans_id from the desc block */ - __u32 j_len; /* ditto */ - __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */ - char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */ -}; - -/* this header block gets written whenever a transaction is considered - fully flushed, and is more recent than the last fully flushed - transaction. - fully flushed means all the log blocks and all the real blocks are - on disk, and this transaction does not need to be replayed. -*/ -struct reiserfs_journal_header { - /* id of last fully flushed transaction */ - __u32 j_last_flush_trans_id; - /* offset in the log of where to start replay after a crash */ - __u32 j_first_unflushed_offset; - /* mount id to detect very old transactions */ - __u32 j_mount_id; -}; - -/* magic string to find desc blocks in the journal */ -#define JOURNAL_DESC_MAGIC "ReIsErLB" - - -/* - * directories use this key as well as old files - */ -struct offset_v1 -{ - /* - * for regular files this is the offset to the first byte of the - * body, contained in the object-item, as measured from the start of - * the entire body of the object. - * - * for directory entries, k_offset consists of hash derived from - * hashing the name and using few bits (23 or more) of the resulting - * hash, and generation number that allows distinguishing names with - * hash collisions. If number of collisions overflows generation - * number, we return EEXIST. High order bit is 0 always - */ - __u32 k_offset; - __u32 k_uniqueness; -}; - -struct offset_v2 -{ - /* - * for regular files this is the offset to the first byte of the - * body, contained in the object-item, as measured from the start of - * the entire body of the object. - * - * for directory entries, k_offset consists of hash derived from - * hashing the name and using few bits (23 or more) of the resulting - * hash, and generation number that allows distinguishing names with - * hash collisions. If number of collisions overflows generation - * number, we return EEXIST. High order bit is 0 always - */ - __u64 k_offset:60; - __u64 k_type: 4; -}; - - -struct key -{ - /* packing locality: by default parent directory object id */ - __u32 k_dir_id; - /* object identifier */ - __u32 k_objectid; - /* the offset and node type (old and new form) */ - union - { - struct offset_v1 v1; - struct offset_v2 v2; - } - u; -}; - -#define KEY_SIZE (sizeof (struct key)) - -/* Header of a disk block. More precisely, header of a formatted leaf - or internal node, and not the header of an unformatted node. */ -struct block_head -{ - __u16 blk_level; /* Level of a block in the tree. */ - __u16 blk_nr_item; /* Number of keys/items in a block. */ - __u16 blk_free_space; /* Block free space in bytes. */ - struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes - only) */ -}; -#define BLKH_SIZE (sizeof (struct block_head)) -#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */ - -struct item_head -{ - struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/ - - union - { - __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this - is an indirect item. This equals 0xFFFF iff this is a direct item or - stat data item. Note that the key, not this field, is used to determine - the item type, and thus which field this union contains. */ - __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory - entries in the directory item. */ - } - u; - __u16 ih_item_len; /* total size of the item body */ - __u16 ih_item_location; /* an offset to the item body within the block */ - __u16 ih_version; /* ITEM_VERSION_1 for all old items, - ITEM_VERSION_2 for new ones. - Highest bit is set by fsck - temporary, cleaned after all done */ -}; -/* size of item header */ -#define IH_SIZE (sizeof (struct item_head)) - -#define ITEM_VERSION_1 0 -#define ITEM_VERSION_2 1 -#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \ - ? (ih)->ih_key.u.v1.k_offset \ - : (ih)->ih_key.u.v2.k_offset) - -#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \ - ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \ - : (ih)->ih_key.u.v2.k_type == V2_##type) - -struct disk_child -{ - unsigned long dc_block_number; /* Disk child's block number. */ - unsigned short dc_size; /* Disk child's used space. */ -}; - -#define DC_SIZE (sizeof (struct disk_child)) - -/* Stat Data on disk. - * - * Note that reiserfs has two different forms of stat data. Luckily - * the fields needed by grub are at the same position. - */ -struct stat_data -{ - __u16 sd_mode; /* file type, permissions */ - __u16 sd_notused1[3]; /* fields not needed by reiserfs */ - __u32 sd_size; /* file size */ - __u32 sd_size_hi; /* file size high 32 bits (since version 2) */ -}; - -struct reiserfs_de_head -{ - __u32 deh_offset; /* third component of the directory entry key */ - __u32 deh_dir_id; /* objectid of the parent directory of the - object, that is referenced by directory entry */ - __u32 deh_objectid;/* objectid of the object, that is referenced by - directory entry */ - __u16 deh_location;/* offset of name in the whole item */ - __u16 deh_state; /* whether 1) entry contains stat data (for - future), and 2) whether entry is hidden - (unlinked) */ -}; - -#define DEH_SIZE (sizeof (struct reiserfs_de_head)) - -#define DEH_Statdata (1 << 0) /* not used now */ -#define DEH_Visible (1 << 2) - -#define SD_OFFSET 0 -#define SD_UNIQUENESS 0 -#define DOT_OFFSET 1 -#define DOT_DOT_OFFSET 2 -#define DIRENTRY_UNIQUENESS 500 - -#define V1_TYPE_STAT_DATA 0x0 -#define V1_TYPE_DIRECT 0xffffffff -#define V1_TYPE_INDIRECT 0xfffffffe -#define V1_TYPE_DIRECTORY_MAX 0xfffffffd -#define V2_TYPE_STAT_DATA 0 -#define V2_TYPE_INDIRECT 1 -#define V2_TYPE_DIRECT 2 -#define V2_TYPE_DIRENTRY 3 - -#define REISERFS_ROOT_OBJECTID 2 -#define REISERFS_ROOT_PARENT_OBJECTID 1 -#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) -/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */ -#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) -#define REISERFS_OLD_BLOCKSIZE 4096 - -#define S_ISREG(mode) (((mode) & 0170000) == 0100000) -#define S_ISDIR(mode) (((mode) & 0170000) == 0040000) -#define S_ISLNK(mode) (((mode) & 0170000) == 0120000) - -#define PATH_MAX 1024 /* include/linux/limits.h */ -#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ - -/* The size of the node cache */ -#define FSYSREISER_CACHE_SIZE 24*1024 -#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE -#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3 - -/* Info about currently opened file */ -struct fsys_reiser_fileinfo -{ - __u32 k_dir_id; - __u32 k_objectid; -}; - -/* In memory info about the currently mounted filesystem */ -struct fsys_reiser_info -{ - /* The last read item head */ - struct item_head *current_ih; - /* The last read item */ - char *current_item; - /* The information for the currently opened file */ - struct fsys_reiser_fileinfo fileinfo; - /* The start of the journal */ - __u32 journal_block; - /* The size of the journal */ - __u32 journal_block_count; - /* The first valid descriptor block in journal - (relative to journal_block) */ - __u32 journal_first_desc; - - /* The ReiserFS version. */ - __u16 version; - /* The current depth of the reiser tree. */ - __u16 tree_depth; - /* SECTOR_SIZE << blocksize_shift == blocksize. */ - __u8 blocksize_shift; - /* 1 << full_blocksize_shift == blocksize. */ - __u8 fullblocksize_shift; - /* The reiserfs block size (must be a power of 2) */ - __u16 blocksize; - /* The number of cached tree nodes */ - __u16 cached_slots; - /* The number of valid transactions in journal */ - __u16 journal_transactions; - - unsigned int blocks[MAX_HEIGHT]; - unsigned int next_key_nr[MAX_HEIGHT]; -}; - -/* The cached s+tree blocks in FSYS_BUF, see below - * for a more detailed description. - */ -#define ROOT ((char *) ((int) FSYS_BUF)) -#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift)) -#define LEAF CACHE (DISK_LEAF_NODE_LEVEL) - -#define BLOCKHEAD(cache) ((struct block_head *) cache) -#define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE)) -#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE)) -#define DC(cache) ((struct disk_child *) \ - ((int) cache + BLKH_SIZE + KEY_SIZE * nr_item)) -/* The fsys_reiser_info block. - */ -#define INFO \ - ((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE)) -/* - * The journal cache. For each transaction it contains the number of - * blocks followed by the real block numbers of this transaction. - * - * If the block numbers of some transaction won't fit in this space, - * this list is stopped with a 0xffffffff marker and the remaining - * uncommitted transactions aren't cached. - */ -#define JOURNAL_START ((__u32 *) (INFO + 1)) -#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN)) - - -static __inline__ unsigned long -log2 (unsigned long word) -{ - __asm__ ("bsfl %1,%0" - : "=r" (word) - : "r" (word)); - return word; -} - -static __inline__ int -is_power_of_two (unsigned long word) -{ - return (word & -word) == word; -} - -static int -journal_read (int block, int len, char *buffer) -{ - return devread ((INFO->journal_block + block) << INFO->blocksize_shift, - 0, len, buffer); -} - -/* Read a block from ReiserFS file system, taking the journal into - * account. If the block nr is in the journal, the block from the - * journal taken. - */ -static int -block_read (int blockNr, int start, int len, char *buffer) -{ - int transactions = INFO->journal_transactions; - int desc_block = INFO->journal_first_desc; - int journal_mask = INFO->journal_block_count - 1; - int translatedNr = blockNr; - __u32 *journal_table = JOURNAL_START; - while (transactions-- > 0) - { - int i = 0; - int j_len; - if (*journal_table != 0xffffffff) - { - /* Search for the blockNr in cached journal */ - j_len = *journal_table++; - while (i++ < j_len) - { - if (*journal_table++ == blockNr) - { - journal_table += j_len - i; - goto found; - } - } - } - else - { - /* This is the end of cached journal marker. The remaining - * transactions are still on disk. - */ - struct reiserfs_journal_desc desc; - struct reiserfs_journal_commit commit; - - if (! journal_read (desc_block, sizeof (desc), (char *) &desc)) - return 0; - - j_len = desc.j_len; - while (i < j_len && i < JOURNAL_TRANS_HALF) - if (desc.j_realblock[i++] == blockNr) - goto found; - - if (j_len >= JOURNAL_TRANS_HALF) - { - int commit_block = (desc_block + 1 + j_len) & journal_mask; - if (! journal_read (commit_block, - sizeof (commit), (char *) &commit)) - return 0; - while (i < j_len) - if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr) - goto found; - } - } - goto not_found; - - found: - translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask); -#ifdef REISERDEBUG - printf ("block_read: block %d is mapped to journal block %d.\n", - blockNr, translatedNr - INFO->journal_block); -#endif - /* We must continue the search, as this block may be overwritten - * in later transactions. - */ - not_found: - desc_block = (desc_block + 2 + j_len) & journal_mask; - } - return devread (translatedNr << INFO->blocksize_shift, start, len, buffer); -} - -/* Init the journal data structure. We try to cache as much as - * possible in the JOURNAL_START-JOURNAL_END space, but if it is full - * we can still read the rest from the disk on demand. - * - * The first number of valid transactions and the descriptor block of the - * first valid transaction are held in INFO. The transactions are all - * adjacent, but we must take care of the journal wrap around. - */ -static int -journal_init (void) -{ - unsigned int block_count = INFO->journal_block_count; - unsigned int desc_block; - unsigned int commit_block; - unsigned int next_trans_id; - struct reiserfs_journal_header header; - struct reiserfs_journal_desc desc; - struct reiserfs_journal_commit commit; - __u32 *journal_table = JOURNAL_START; - - journal_read (block_count, sizeof (header), (char *) &header); - desc_block = header.j_first_unflushed_offset; - if (desc_block >= block_count) - return 0; - - INFO->journal_first_desc = desc_block; - next_trans_id = header.j_last_flush_trans_id + 1; - -#ifdef REISERDEBUG - printf ("journal_init: last flushed %d\n", - header.j_last_flush_trans_id); -#endif - - while (1) - { - journal_read (desc_block, sizeof (desc), (char *) &desc); - if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0 - || desc.j_trans_id != next_trans_id - || desc.j_mount_id != header.j_mount_id) - /* no more valid transactions */ - break; - - commit_block = (desc_block + desc.j_len + 1) & (block_count - 1); - journal_read (commit_block, sizeof (commit), (char *) &commit); - if (desc.j_trans_id != commit.j_trans_id - || desc.j_len != commit.j_len) - /* no more valid transactions */ - break; - -#ifdef REISERDEBUG - printf ("Found valid transaction %d/%d at %d.\n", - desc.j_trans_id, desc.j_mount_id, desc_block); -#endif - - next_trans_id++; - if (journal_table < JOURNAL_END) - { - if ((journal_table + 1 + desc.j_len) >= JOURNAL_END) - { - /* The table is almost full; mark the end of the cached - * journal.*/ - *journal_table = 0xffffffff; - journal_table = JOURNAL_END; - } - else - { - int i; - /* Cache the length and the realblock numbers in the table. - * The block number of descriptor can easily be computed. - * and need not to be stored here. - */ - *journal_table++ = desc.j_len; - for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++) - { - *journal_table++ = desc.j_realblock[i]; -#ifdef REISERDEBUG - printf ("block %d is in journal %d.\n", - desc.j_realblock[i], desc_block); -#endif - } - for ( ; i < desc.j_len; i++) - { - *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF]; -#ifdef REISERDEBUG - printf ("block %d is in journal %d.\n", - commit.j_realblock[i-JOURNAL_TRANS_HALF], - desc_block); -#endif - } - } - } - desc_block = (commit_block + 1) & (block_count - 1); - } -#ifdef REISERDEBUG - printf ("Transaction %d/%d at %d isn't valid.\n", - desc.j_trans_id, desc.j_mount_id, desc_block); -#endif - - INFO->journal_transactions - = next_trans_id - header.j_last_flush_trans_id - 1; - return errnum == 0; -} - -/* check filesystem types and read superblock into memory buffer */ -int -reiserfs_mount (void) -{ - struct reiserfs_super_block super; - int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; - - if (part_length < superblock + (sizeof (super) >> SECTOR_BITS) - || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), - (char *) &super) - || (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0 - && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0) - || (/* check that this is not a copy inside the journal log */ - super.s_journal_block * super.s_blocksize - <= REISERFS_DISK_OFFSET_IN_BYTES)) - { - /* Try old super block position */ - superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; - if (part_length < superblock + (sizeof (super) >> SECTOR_BITS) - || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), - (char *) &super)) - return 0; - - if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0 - && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0) - { - /* pre journaling super block ? */ - if (substring (REISERFS_SUPER_MAGIC_STRING, - (char*) ((int) &super + 20)) > 0) - return 0; - - super.s_blocksize = REISERFS_OLD_BLOCKSIZE; - super.s_journal_block = 0; - super.s_version = 0; - } - } - - /* check the version number. */ - if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION) - return 0; - - INFO->version = super.s_version; - INFO->blocksize = super.s_blocksize; - INFO->fullblocksize_shift = log2 (super.s_blocksize); - INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS; - INFO->cached_slots = - (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1; - -#ifdef REISERDEBUG - printf ("reiserfs_mount: version=%d, blocksize=%d\n", - INFO->version, INFO->blocksize); -#endif /* REISERDEBUG */ - - /* Clear node cache. */ - memset (INFO->blocks, 0, sizeof (INFO->blocks)); - - if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE - || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE - || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize) - return 0; - - /* Initialize journal code. If something fails we end with zero - * journal_transactions, so we don't access the journal at all. - */ - INFO->journal_transactions = 0; - if (super.s_journal_block != 0 && super.s_journal_dev == 0) - { - INFO->journal_block = super.s_journal_block; - INFO->journal_block_count = super.s_journal_size; - if (is_power_of_two (INFO->journal_block_count)) - journal_init (); - - /* Read in super block again, maybe it is in the journal */ - block_read (superblock >> INFO->blocksize_shift, - 0, sizeof (struct reiserfs_super_block), (char *) &super); - } - - if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT)) - return 0; - - INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level; - -#ifdef REISERDEBUG - printf ("root read_in: block=%d, depth=%d\n", - super.s_root_block, INFO->tree_depth); -#endif /* REISERDEBUG */ - - if (INFO->tree_depth >= MAX_HEIGHT) - return 0; - if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL) - { - /* There is only one node in the whole filesystem, - * which is simultanously leaf and root */ - memcpy (LEAF, ROOT, INFO->blocksize); - } - return 1; -} - -/***************** TREE ACCESSING METHODS *****************************/ - -/* I assume you are familiar with the ReiserFS tree, if not go to - * http://www.namesys.com/content_table.html - * - * My tree node cache is organized as following - * 0 ROOT node - * 1 LEAF node (if the ROOT is also a LEAF it is copied here - * 2-n other nodes on current path from bottom to top. - * if there is not enough space in the cache, the top most are - * omitted. - * - * I have only two methods to find a key in the tree: - * search_stat(dir_id, objectid) searches for the stat entry (always - * the first entry) of an object. - * next_key() gets the next key in tree order. - * - * This means, that I can only sequential reads of files are - * efficient, but this really doesn't hurt for grub. - */ - -/* Read in the node at the current path and depth into the node cache. - * You must set INFO->blocks[depth] before. - */ -static char * -read_tree_node (unsigned int blockNr, int depth) -{ - char* cache = CACHE(depth); - int num_cached = INFO->cached_slots; - if (depth < num_cached) - { - /* This is the cached part of the path. Check if same block is - * needed. - */ - if (blockNr == INFO->blocks[depth]) - return cache; - } - else - cache = CACHE(num_cached); - -#ifdef REISERDEBUG - printf (" next read_in: block=%d (depth=%d)\n", - blockNr, depth); -#endif /* REISERDEBUG */ - if (! block_read (blockNr, 0, INFO->blocksize, cache)) - return 0; - /* Make sure it has the right node level */ - if (BLOCKHEAD (cache)->blk_level != depth) - { - errnum = ERR_FSYS_CORRUPT; - return 0; - } - - INFO->blocks[depth] = blockNr; - return cache; -} - -/* Get the next key, i.e. the key following the last retrieved key in - * tree order. INFO->current_ih and - * INFO->current_info are adapted accordingly. */ -static int -next_key (void) -{ - int depth; - struct item_head *ih = INFO->current_ih + 1; - char *cache; - -#ifdef REISERDEBUG - printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n", - INFO->current_ih->ih_key.k_dir_id, - INFO->current_ih->ih_key.k_objectid, - INFO->current_ih->ih_key.u.v1.k_offset, - INFO->current_ih->ih_key.u.v1.k_uniqueness, - INFO->current_ih->ih_version); -#endif /* REISERDEBUG */ - - if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item]) - { - depth = DISK_LEAF_NODE_LEVEL; - /* The last item, was the last in the leaf node. - * Read in the next block - */ - do - { - if (depth == INFO->tree_depth) - { - /* There are no more keys at all. - * Return a dummy item with MAX_KEY */ - ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key; - goto found; - } - depth++; -#ifdef REISERDEBUG - printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]); -#endif /* REISERDEBUG */ - } - while (INFO->next_key_nr[depth] == 0); - - if (depth == INFO->tree_depth) - cache = ROOT; - else if (depth <= INFO->cached_slots) - cache = CACHE (depth); - else - { - cache = read_tree_node (INFO->blocks[depth], depth); - if (! cache) - return 0; - } - - do - { - int nr_item = BLOCKHEAD (cache)->blk_nr_item; - int key_nr = INFO->next_key_nr[depth]++; -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item); -#endif /* REISERDEBUG */ - if (key_nr == nr_item) - /* This is the last item in this block, set the next_key_nr to 0 */ - INFO->next_key_nr[depth] = 0; - - cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth); - if (! cache) - return 0; - } - while (depth > DISK_LEAF_NODE_LEVEL); - - ih = ITEMHEAD; - } - found: - INFO->current_ih = ih; - INFO->current_item = &LEAF[ih->ih_item_location]; -#ifdef REISERDEBUG - printf (" new ih: key %d:%d:%d:%d version:%d\n", - INFO->current_ih->ih_key.k_dir_id, - INFO->current_ih->ih_key.k_objectid, - INFO->current_ih->ih_key.u.v1.k_offset, - INFO->current_ih->ih_key.u.v1.k_uniqueness, - INFO->current_ih->ih_version); -#endif /* REISERDEBUG */ - return 1; -} - -/* preconditions: reiserfs_mount already executed, therefore - * INFO block is valid - * returns: 0 if error (errnum is set), - * nonzero iff we were able to find the key successfully. - * postconditions: on a nonzero return, the current_ih and - * current_item fields describe the key that equals the - * searched key. INFO->next_key contains the next key after - * the searched key. - * side effects: messes around with the cache. - */ -static int -search_stat (__u32 dir_id, __u32 objectid) -{ - char *cache; - int depth; - int nr_item; - int i; - struct item_head *ih; -#ifdef REISERDEBUG - printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid); -#endif /* REISERDEBUG */ - - depth = INFO->tree_depth; - cache = ROOT; - - while (depth > DISK_LEAF_NODE_LEVEL) - { - struct key *key; - nr_item = BLOCKHEAD (cache)->blk_nr_item; - - key = KEY (cache); - - for (i = 0; i < nr_item; i++) - { - if (key->k_dir_id > dir_id - || (key->k_dir_id == dir_id - && (key->k_objectid > objectid - || (key->k_objectid == objectid - && (key->u.v1.k_offset - | key->u.v1.k_uniqueness) > 0)))) - break; - key++; - } - -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); -#endif /* REISERDEBUG */ - INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1; - cache = read_tree_node (DC (cache)[i].dc_block_number, --depth); - if (! cache) - return 0; - } - - /* cache == LEAF */ - nr_item = BLOCKHEAD (LEAF)->blk_nr_item; - ih = ITEMHEAD; - for (i = 0; i < nr_item; i++) - { - if (ih->ih_key.k_dir_id == dir_id - && ih->ih_key.k_objectid == objectid - && ih->ih_key.u.v1.k_offset == 0 - && ih->ih_key.u.v1.k_uniqueness == 0) - { -#ifdef REISERDEBUG - printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); -#endif /* REISERDEBUG */ - INFO->current_ih = ih; - INFO->current_item = &LEAF[ih->ih_item_location]; - return 1; - } - ih++; - } - errnum = ERR_FSYS_CORRUPT; - return 0; -} - -int -reiserfs_read (char *buf, int len) -{ - unsigned int blocksize; - unsigned int offset; - unsigned int to_read; - char *prev_buf = buf; - -#ifdef REISERDEBUG - printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n", - filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1); -#endif /* REISERDEBUG */ - - if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid - || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1) - { - search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid); - goto get_next_key; - } - - while (! errnum) - { - if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid) - break; - - offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1; - blocksize = INFO->current_ih->ih_item_len; - -#ifdef REISERDEBUG - printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n", - filepos, len, offset, blocksize); -#endif /* REISERDEBUG */ - - if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT) - && offset < blocksize) - { -#ifdef REISERDEBUG - printf ("direct_read: offset=%d, blocksize=%d\n", - offset, blocksize); -#endif /* REISERDEBUG */ - to_read = blocksize - offset; - if (to_read > len) - to_read = len; - - if (disk_read_hook != NULL) - { - disk_read_func = disk_read_hook; - - block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL], - (INFO->current_item - LEAF + offset), to_read, buf); - - disk_read_func = NULL; - } - else - memcpy (buf, INFO->current_item + offset, to_read); - goto update_buf_len; - } - else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT)) - { - blocksize = (blocksize >> 2) << INFO->fullblocksize_shift; -#ifdef REISERDEBUG - printf ("indirect_read: offset=%d, blocksize=%d\n", - offset, blocksize); -#endif /* REISERDEBUG */ - - while (offset < blocksize) - { - __u32 blocknr = ((__u32 *) INFO->current_item) - [offset >> INFO->fullblocksize_shift]; - int blk_offset = offset & (INFO->blocksize-1); - - to_read = INFO->blocksize - blk_offset; - if (to_read > len) - to_read = len; - - disk_read_func = disk_read_hook; - - /* Journal is only for meta data. Data blocks can be read - * directly without using block_read - */ - devread (blocknr << INFO->blocksize_shift, - blk_offset, to_read, buf); - - disk_read_func = NULL; - update_buf_len: - len -= to_read; - buf += to_read; - offset += to_read; - filepos += to_read; - if (len == 0) - goto done; - } - } - get_next_key: - next_key (); - } - done: - return errnum ? 0 : buf - prev_buf; -} - - -/* preconditions: reiserfs_mount already executed, therefore - * INFO block is valid - * returns: 0 if error, nonzero iff we were able to find the file successfully - * postconditions: on a nonzero return, INFO->fileinfo contains the info - * of the file we were trying to look up, filepos is 0 and filemax is - * the size of the file. - */ -int -reiserfs_dir (char *dirname) -{ - struct reiserfs_de_head *de_head; - char *rest, ch; - __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0; -#ifndef STAGE1_5 - int do_possibilities = 0; -#endif /* ! STAGE1_5 */ - char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ - int link_count = 0; - int mode; - - dir_id = REISERFS_ROOT_PARENT_OBJECTID; - objectid = REISERFS_ROOT_OBJECTID; - - while (1) - { -#ifdef REISERDEBUG - printf ("dirname=%s\n", dirname); -#endif /* REISERDEBUG */ - - /* Search for the stat info first. */ - if (! search_stat (dir_id, objectid)) - return 0; - -#ifdef REISERDEBUG - printf ("sd_mode=%x sd_size=%d\n", - ((struct stat_data *) INFO->current_item)->sd_mode, - ((struct stat_data *) INFO->current_item)->sd_size); -#endif /* REISERDEBUG */ - - mode = ((struct stat_data *) INFO->current_item)->sd_mode; - - /* If we've got a symbolic link, then chase it. */ - if (S_ISLNK (mode)) - { - int len; - if (++link_count > MAX_LINK_COUNT) - { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - - /* Get the symlink size. */ - filemax = ((struct stat_data *) INFO->current_item)->sd_size; - - /* Find out how long our remaining name is. */ - len = 0; - while (dirname[len] && !isspace (dirname[len])) - len++; - - if (filemax + len > sizeof (linkbuf) - 1) - { - errnum = ERR_FILELENGTH; - return 0; - } - - /* Copy the remaining name to the end of the symlink data. - Note that DIRNAME and LINKBUF may overlap! */ - grub_memmove (linkbuf + filemax, dirname, len+1); - - INFO->fileinfo.k_dir_id = dir_id; - INFO->fileinfo.k_objectid = objectid; - filepos = 0; - if (! next_key () - || reiserfs_read (linkbuf, filemax) != filemax) - { - if (! errnum) - errnum = ERR_FSYS_CORRUPT; - return 0; - } - -#ifdef REISERDEBUG - printf ("symlink=%s\n", linkbuf); -#endif /* REISERDEBUG */ - - dirname = linkbuf; - if (*dirname == '/') - { - /* It's an absolute link, so look it up in root. */ - dir_id = REISERFS_ROOT_PARENT_OBJECTID; - objectid = REISERFS_ROOT_OBJECTID; - } - else - { - /* Relative, so look it up in our parent directory. */ - dir_id = parent_dir_id; - objectid = parent_objectid; - } - - /* Now lookup the new name. */ - continue; - } - - /* if we have a real file (and we're not just printing possibilities), - then this is where we want to exit */ - - if (! *dirname || isspace (*dirname)) - { - if (! S_ISREG (mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - filepos = 0; - filemax = ((struct stat_data *) INFO->current_item)->sd_size; - - /* If this is a new stat data and size is > 4GB set filemax to - * maximum - */ - if (INFO->current_ih->ih_version == ITEM_VERSION_2 - && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0) - filemax = 0xffffffff; - - INFO->fileinfo.k_dir_id = dir_id; - INFO->fileinfo.k_objectid = objectid; - return next_key (); - } - - /* continue with the file/directory name interpretation */ - while (*dirname == '/') - dirname++; - if (! S_ISDIR (mode)) - { - errnum = ERR_BAD_FILETYPE; - return 0; - } - for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++); - *rest = 0; - -# ifndef STAGE1_5 - if (print_possibilities && ch != '/') - do_possibilities = 1; -# endif /* ! STAGE1_5 */ - - while (1) - { - char *name_end; - int num_entries; - - if (! next_key ()) - return 0; -#ifdef REISERDEBUG - printf ("ih: key %d:%d:%d:%d version:%d\n", - INFO->current_ih->ih_key.k_dir_id, - INFO->current_ih->ih_key.k_objectid, - INFO->current_ih->ih_key.u.v1.k_offset, - INFO->current_ih->ih_key.u.v1.k_uniqueness, - INFO->current_ih->ih_version); -#endif /* REISERDEBUG */ - - if (INFO->current_ih->ih_key.k_objectid != objectid) - break; - - name_end = INFO->current_item + INFO->current_ih->ih_item_len; - de_head = (struct reiserfs_de_head *) INFO->current_item; - num_entries = INFO->current_ih->u.ih_entry_count; - while (num_entries > 0) - { - char *filename = INFO->current_item + de_head->deh_location; - char tmp = *name_end; - if ((de_head->deh_state & DEH_Visible)) - { - int cmp; - /* Directory names in ReiserFS are not null - * terminated. We write a temporary 0 behind it. - * NOTE: that this may overwrite the first block in - * the tree cache. That doesn't hurt as long as we - * don't call next_key () in between. - */ - *name_end = 0; - cmp = substring (dirname, filename); - *name_end = tmp; -# ifndef STAGE1_5 - if (do_possibilities) - { - if (cmp <= 0) - { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - *name_end = 0; - print_a_completion (filename); - *name_end = tmp; - } - } - else -# endif /* ! STAGE1_5 */ - if (cmp == 0) - goto found; - } - /* The beginning of this name marks the end of the next name. - */ - name_end = filename; - de_head++; - num_entries--; - } - } - -# ifndef STAGE1_5 - if (print_possibilities < 0) - return 1; -# endif /* ! STAGE1_5 */ - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - - found: - - *rest = ch; - dirname = rest; - - parent_dir_id = dir_id; - parent_objectid = objectid; - dir_id = de_head->deh_dir_id; - objectid = de_head->deh_objectid; - - } - - return 1; -} - -int -reiserfs_embed (int *start_sector, int needed_sectors) -{ - struct reiserfs_super_block super; - int num_sectors; - - if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, - sizeof (struct reiserfs_super_block), (char *) &super)) - return 0; - - *start_sector = 1; /* reserve first sector for stage1 */ - if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0 - || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0) - && (/* check that this is not a super block copy inside - * the journal log */ - super.s_journal_block * super.s_blocksize - > REISERFS_DISK_OFFSET_IN_BYTES)) - num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; - else - num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; - - return (needed_sectors <= num_sectors); -} -#endif /* FSYS_REISERFS */ diff --git a/src/filo/fs/fsys_xfs.c b/src/filo/fs/fsys_xfs.c deleted file mode 100644 index b551c07a..00000000 --- a/src/filo/fs/fsys_xfs.c +++ /dev/null @@ -1,624 +0,0 @@ -/* fsys_xfs.c - an implementation for the SGI XFS file system */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2001,2002 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifdef FSYS_XFS - -#include "shared.h" -#include "filesys.h" -#include "xfs.h" - -#define MAX_LINK_COUNT 8 - -typedef struct xad { - xfs_fileoff_t offset; - xfs_fsblock_t start; - xfs_filblks_t len; -} xad_t; - -struct xfs_info { - int bsize; - int dirbsize; - int isize; - unsigned int agblocks; - int bdlog; - int blklog; - int inopblog; - int agblklog; - int agnolog; - unsigned int nextents; - xfs_daddr_t next; - xfs_daddr_t daddr; - xfs_dablk_t forw; - xfs_dablk_t dablk; - xfs_bmbt_rec_32_t *xt; - xfs_bmbt_ptr_t ptr0; - int btnode_ptr0_off; - int i8param; - int dirpos; - int dirmax; - int blkoff; - int fpos; - xfs_ino_t rootino; -}; - -static struct xfs_info xfs; - -#define dirbuf ((char *)FSYS_BUF) -#define filebuf ((char *)FSYS_BUF + 4096) -#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192)) -#define icore (inode->di_core) - -#define mask32lo(n) (((__uint32_t)1 << (n)) - 1) - -#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1)) -#define XFS_INO_OFFSET_BITS xfs.inopblog -#define XFS_INO_AGBNO_BITS xfs.agblklog -#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog) -#define XFS_INO_AGNO_BITS xfs.agnolog - -static inline xfs_agblock_t -agino2agbno (xfs_agino_t agino) -{ - return agino >> XFS_INO_OFFSET_BITS; -} - -static inline xfs_agnumber_t -ino2agno (xfs_ino_t ino) -{ - return ino >> XFS_INO_AGINO_BITS; -} - -static inline xfs_agino_t -ino2agino (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS); -} - -static inline int -ino2offset (xfs_ino_t ino) -{ - return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS); -} - -static inline __const__ __uint16_t -le16 (__uint16_t x) -{ - __asm__("xchgb %b0,%h0" \ - : "=q" (x) \ - : "0" (x)); \ - return x; -} - -static inline __const__ __uint32_t -le32 (__uint32_t x) -{ -#if 0 - /* 386 doesn't have bswap. */ - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - /* This is slower but this works on all x86 architectures. */ - __asm__("xchgb %b0, %h0" \ - "\n\troll $16, %0" \ - "\n\txchgb %b0, %h0" \ - : "=q" (x) : "0" (x)); -#endif - return x; -} - -static inline __const__ __uint64_t -le64 (__uint64_t x) -{ - __uint32_t h = x >> 32; - __uint32_t l = x & ((1ULL<<32)-1); - return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h))); -} - - -static xfs_fsblock_t -xt_start (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | - (((xfs_fsblock_t)le32 (r->l2)) << 11) | - (((xfs_fsblock_t)le32 (r->l3)) >> 21); -} - -static xfs_fileoff_t -xt_offset (xfs_bmbt_rec_32_t *r) -{ - return (((xfs_fileoff_t)le32 (r->l0) & - mask32lo(31)) << 23) | - (((xfs_fileoff_t)le32 (r->l1)) >> 9); -} - -static xfs_filblks_t -xt_len (xfs_bmbt_rec_32_t *r) -{ - return le32(r->l3) & mask32lo(21); -} - -static inline int -xfs_highbit32(__uint32_t v) -{ - int i; - - if (--v) { - for (i = 0; i < 31; i++, v >>= 1) { - if (v == 0) - return i; - } - } - return 0; -} - -static int -isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len) -{ - return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; -} - -static xfs_daddr_t -agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno) -{ - return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog; -} - -static xfs_daddr_t -fsb2daddr (xfs_fsblock_t fsbno) -{ - return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog), - (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog))); -} - -#undef offsetof -#define offsetof(t,m) ((int)&(((t *)0)->m)) - -static inline int -btroot_maxrecs (void) -{ - int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize; - - return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)); -} - -static int -di_read (xfs_ino_t ino) -{ - xfs_agino_t agino; - xfs_agnumber_t agno; - xfs_agblock_t agbno; - xfs_daddr_t daddr; - int offset; - - agno = ino2agno (ino); - agino = ino2agino (ino); - agbno = agino2agbno (agino); - offset = ino2offset (ino); - daddr = agb2daddr (agno, agbno); - - devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode); - - xfs.ptr0 = *(xfs_bmbt_ptr_t *) - (inode->di_u.di_c + sizeof(xfs_bmdr_block_t) - + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t)); - - return 1; -} - -static void -init_extents (void) -{ - xfs_bmbt_ptr_t ptr0; - xfs_btree_lblock_t h; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - xfs.xt = inode->di_u.di_bmx; - xfs.nextents = le32 (icore.di_nextents); - break; - case XFS_DINODE_FMT_BTREE: - ptr0 = xfs.ptr0; - for (;;) { - xfs.daddr = fsb2daddr (le64(ptr0)); - devread (xfs.daddr, 0, - sizeof(xfs_btree_lblock_t), (char *)&h); - if (!h.bb_level) { - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - return; - } - devread (xfs.daddr, xfs.btnode_ptr0_off, - sizeof(xfs_bmbt_ptr_t), (char *)&ptr0); - } - } -} - -static xad_t * -next_extent (void) -{ - static xad_t xad; - - switch (icore.di_format) { - case XFS_DINODE_FMT_EXTENTS: - if (xfs.nextents == 0) - return NULL; - break; - case XFS_DINODE_FMT_BTREE: - if (xfs.nextents == 0) { - xfs_btree_lblock_t h; - if (xfs.next == 0) - return NULL; - xfs.daddr = xfs.next; - devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h); - xfs.nextents = le16(h.bb_numrecs); - xfs.next = fsb2daddr (le64(h.bb_rightsib)); - xfs.fpos = sizeof(xfs_btree_block_t); - } - /* Yeah, I know that's slow, but I really don't care */ - devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf); - xfs.xt = (xfs_bmbt_rec_32_t *)filebuf; - xfs.fpos += sizeof(xfs_bmbt_rec_32_t); - } - xad.offset = xt_offset (xfs.xt); - xad.start = xt_start (xfs.xt); - xad.len = xt_len (xfs.xt); - ++xfs.xt; - --xfs.nextents; - - return &xad; -} - -/* - * Name lies - the function reads only first 100 bytes - */ -static void -xfs_dabread (void) -{ - xad_t *xad; - xfs_fileoff_t offset;; - - init_extents (); - while ((xad = next_extent ())) { - offset = xad->offset; - if (isinxt (xfs.dablk, offset, xad->len)) { - devread (fsb2daddr (xad->start + xfs.dablk - offset), - 0, 100, dirbuf); - break; - } - } -} - -static inline xfs_ino_t -sf_ino (char *sfe, int namelen) -{ - void *p = sfe + namelen + 3; - - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p); -} - -static inline xfs_ino_t -sf_parent_ino (void) -{ - return (xfs.i8param == 0) - ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent)) - : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent)); -} - -static inline int -roundup8 (int n) -{ - return ((n+7)&~7); -} - -static char * -next_dentry (xfs_ino_t *ino) -{ - int namelen = 1; - int toread; - static char *usual[2] = {".", ".."}; - static xfs_dir2_sf_entry_t *sfe; - char *name = usual[0]; - - if (xfs.dirpos >= xfs.dirmax) { - if (xfs.forw == 0) - return NULL; - xfs.dablk = xfs.forw; - xfs_dabread (); -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); -#undef h - xfs.dirpos = 0; - } - - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - switch (xfs.dirpos) { - case -2: - *ino = 0; - break; - case -1: - *ino = sf_parent_ino (); - ++name; - ++namelen; - sfe = (xfs_dir2_sf_entry_t *) - (inode->di_u.di_c - + sizeof(xfs_dir2_sf_hdr_t) - - xfs.i8param); - break; - default: - namelen = sfe->namelen; - *ino = sf_ino ((char *)sfe, namelen); - name = sfe->name; - sfe = (xfs_dir2_sf_entry_t *) - ((char *)sfe + namelen + 11 - xfs.i8param); - } - break; - case XFS_DINODE_FMT_BTREE: - case XFS_DINODE_FMT_EXTENTS: -#define dau ((xfs_dir2_data_union_t *)dirbuf) - for (;;) { - if (xfs.blkoff >= xfs.dirbsize) { - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos &= ~(xfs.dirbsize - 1); - filepos |= xfs.blkoff; - } - xfs_read (dirbuf, 4); - xfs.blkoff += 4; - if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) { - toread = roundup8 (le16(dau->unused.length)) - 4; - xfs.blkoff += toread; - filepos += toread; - continue; - } - break; - } - xfs_read ((char *)dirbuf + 4, 5); - *ino = le64 (dau->entry.inumber); - namelen = dau->entry.namelen; -#undef dau - toread = roundup8 (namelen + 11) - 9; - xfs_read (dirbuf, toread); - name = (char *)dirbuf; - xfs.blkoff += toread + 5; - } - ++xfs.dirpos; - name[namelen] = 0; - - return name; -} - -static char * -first_dentry (xfs_ino_t *ino) -{ - xfs.forw = 0; - switch (icore.di_format) { - case XFS_DINODE_FMT_LOCAL: - xfs.dirmax = inode->di_u.di_dir2sf.hdr.count; - xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4; - xfs.dirpos = -2; - break; - case XFS_DINODE_FMT_EXTENTS: - case XFS_DINODE_FMT_BTREE: - filepos = 0; - xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t)); - if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) { -#define tail ((xfs_dir2_block_tail_t *)dirbuf) - filepos = xfs.dirbsize - sizeof(*tail); - xfs_read (dirbuf, sizeof(*tail)); - xfs.dirmax = le32 (tail->count) - le32 (tail->stale); -#undef tail - } else { - xfs.dablk = (1ULL << 35) >> xfs.blklog; -#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) -#define n ((xfs_da_intnode_t *)dirbuf) - for (;;) { - xfs_dabread (); - if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC)) - || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) { - xfs.dirmax = le16 (h->count) - le16 (h->stale); - xfs.forw = le32 (h->info.forw); - break; - } - xfs.dablk = le32 (n->btree[0].before); - } -#undef n -#undef h - } - xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); - filepos = xfs.blkoff; - xfs.dirpos = 0; - } - return next_dentry (ino); -} - -int -xfs_mount (void) -{ - xfs_sb_t super; - - if (!devread (0, 0, sizeof(super), (char *)&super) - || (le32(super.sb_magicnum) != XFS_SB_MAGIC) - || ((le16(super.sb_versionnum) - & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) { - return 0; - } - - xfs.bsize = le32 (super.sb_blocksize); - xfs.blklog = super.sb_blocklog; - xfs.bdlog = xfs.blklog - SECTOR_BITS; - xfs.rootino = le64 (super.sb_rootino); - xfs.isize = le16 (super.sb_inodesize); - xfs.agblocks = le32 (super.sb_agblocks); - xfs.dirbsize = xfs.bsize << super.sb_dirblklog; - - xfs.inopblog = super.sb_inopblog; - xfs.agblklog = super.sb_agblklog; - xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount)); - - xfs.btnode_ptr0_off = - ((xfs.bsize - sizeof(xfs_btree_block_t)) / - (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t))) - * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t); - - return 1; -} - -int -xfs_read (char *buf, int len) -{ - xad_t *xad; - xfs_fileoff_t endofprev, endofcur, offset; - xfs_filblks_t xadlen; - int toread, startpos, endpos; - - if (icore.di_format == XFS_DINODE_FMT_LOCAL) { - grub_memmove (buf, inode->di_u.di_c + filepos, len); - filepos += len; - return len; - } - - startpos = filepos; - endpos = filepos + len; - endofprev = (xfs_fileoff_t)-1; - init_extents (); - while (len > 0 && (xad = next_extent ())) { - offset = xad->offset; - xadlen = xad->len; - if (isinxt (filepos >> xfs.blklog, offset, xadlen)) { - endofcur = (offset + xadlen) << xfs.blklog; - toread = (endofcur >= endpos) - ? len : (endofcur - filepos); - - disk_read_func = disk_read_hook; - devread (fsb2daddr (xad->start), - filepos - (offset << xfs.blklog), toread, buf); - disk_read_func = NULL; - - buf += toread; - len -= toread; - filepos += toread; - } else if (offset > endofprev) { - toread = ((offset << xfs.blklog) >= endpos) - ? len : ((offset - endofprev) << xfs.blklog); - len -= toread; - filepos += toread; - for (; toread; toread--) { - *buf++ = 0; - } - continue; - } - endofprev = offset + xadlen; - } - - return filepos - startpos; -} - -int -xfs_dir (char *dirname) -{ - xfs_ino_t ino, parent_ino, new_ino; - xfs_fsize_t di_size; - int di_mode; - int cmp, n, link_count; - char linkbuf[xfs.bsize]; - char *rest, *name, ch; - - parent_ino = ino = xfs.rootino; - link_count = 0; - for (;;) { - di_read (ino); - di_size = le64 (icore.di_size); - di_mode = le16 (icore.di_mode); - - if ((di_mode & IFMT) == IFLNK) { - if (++link_count > MAX_LINK_COUNT) { - errnum = ERR_SYMLINK_LOOP; - return 0; - } - if (di_size < xfs.bsize - 1) { - filepos = 0; - filemax = di_size; - n = xfs_read (linkbuf, filemax); - } else { - errnum = ERR_FILELENGTH; - return 0; - } - - ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino; - while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++)); - linkbuf[n] = 0; - dirname = linkbuf; - continue; - } - - if (!*dirname || isspace (*dirname)) { - if ((di_mode & IFMT) != IFREG) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - filepos = 0; - filemax = di_size; - return 1; - } - - if ((di_mode & IFMT) != IFDIR) { - errnum = ERR_BAD_FILETYPE; - return 0; - } - - for (; *dirname == '/'; dirname++); - - for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); - *rest = 0; - - name = first_dentry (&new_ino); - for (;;) { - cmp = (!*dirname) ? -1 : substring (dirname, name); -#ifndef STAGE1_5 - if (print_possibilities && ch != '/' && cmp <= 0) { - if (print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion (name); - } else -#endif - if (cmp == 0) { - parent_ino = ino; - if (new_ino) - ino = new_ino; - *(dirname = rest) = ch; - break; - } - name = next_dentry (&new_ino); - if (name == NULL) { - if (print_possibilities < 0) - return 1; - - errnum = ERR_FILE_NOT_FOUND; - *rest = ch; - return 0; - } - } - } -} - -#endif /* FSYS_XFS */ diff --git a/src/filo/fs/iso9660.h b/src/filo/fs/iso9660.h deleted file mode 100644 index 06a79062..00000000 --- a/src/filo/fs/iso9660.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader) - * including Rock Ridge Extensions support - * - * Copyright (C) 1998, 1999 Kousuke Takai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * References: - * linux/fs/isofs/rock.[ch] - * mkisofs-1.11.1/diag/isoinfo.c - * mkisofs-1.11.1/iso9660.h - * (all are written by Eric Youngdale) - */ - -/* - * Modified by SONE Takeshi to work with FILO - */ - -#ifndef _ISO9660_H_ -#define _ISO9660_H_ - -#define ISO_SECTOR_BITS (11) -#define ISO_SECTOR_SIZE (1<= file system block size >= PBSIZE >= DISIZE - */ -#define PBSIZE 512 /* physical block size (in byte) */ -#define DISIZE 512 /* on-disk inode size (in byte) */ -#define L2DISIZE 9 -#define INOSPERIAG 4096 /* number of disk inodes per iag */ -#define L2INOSPERIAG 12 -#define INOSPEREXT 32 /* number of disk inode per extent */ -#define L2INOSPEREXT 5 - -/* Minimum number of bytes supported for a JFS partition */ -#define MINJFS (0x1000000) - -/* - * fixed byte offset address - */ -#define SUPER1_OFF 0x8000 /* primary superblock */ - -#define AITBL_OFF (SUPER1_OFF + PSIZE + (PSIZE << 1)) - -/* - * fixed reserved inode number - */ -/* aggregate inode */ -#define AGGREGATE_I 1 /* aggregate inode map inode */ -#define FILESYSTEM_I 16 /* 1st/only fileset inode in ait: - * fileset inode map inode - */ - -/* per fileset inode */ -#define ROOT_I 2 /* fileset root inode */ - -/* - * directory configuration - */ -#define JFS_NAME_MAX 255 -#define JFS_PATH_MAX PSIZE - -typedef unsigned char u8; -typedef char s8; -typedef unsigned short u16; -typedef short s16; -typedef unsigned int u32; -typedef int s32; -typedef unsigned long long u64; -typedef long long s64; - -typedef u16 UniChar; - -/* these from jfs_btree.h */ - -/* btpaget_t flag */ -#define BT_TYPE 0x07 /* B+-tree index */ -#define BT_ROOT 0x01 /* root page */ -#define BT_LEAF 0x02 /* leaf page */ -#define BT_INTERNAL 0x04 /* internal page */ -#define BT_RIGHTMOST 0x10 /* rightmost page */ -#define BT_LEFTMOST 0x20 /* leftmost page */ - -/* those are from jfs_types.h */ - -struct timestruc_t { - u32 tv_sec; - u32 tv_nsec; -}; - -/* - * physical xd (pxd) - */ -typedef struct { - unsigned len:24; - unsigned addr1:8; - u32 addr2; -} pxd_t; - -/* xd_t field extraction */ -#define lengthPXD(pxd) ((pxd)->len) -#define addressPXD(pxd) (((s64)((pxd)->addr1)) << 32 | ((pxd)->addr2)) - -/* - * data extent descriptor (dxd) - */ -typedef struct { - unsigned flag:8; /* 1: flags */ - unsigned rsrvd:24; /* 3: */ - u32 size; /* 4: size in byte */ - unsigned len:24; /* 3: length in unit of fsblksize */ - unsigned addr1:8; /* 1: address in unit of fsblksize */ - u32 addr2; /* 4: address in unit of fsblksize */ -} dxd_t; /* - 16 - */ - -/* - * DASD limit information - stored in directory inode - */ -typedef struct dasd { - u8 thresh; /* Alert Threshold (in percent) */ - u8 delta; /* Alert Threshold delta (in percent) */ - u8 rsrvd1; - u8 limit_hi; /* DASD limit (in logical blocks) */ - u32 limit_lo; /* DASD limit (in logical blocks) */ - u8 rsrvd2[3]; - u8 used_hi; /* DASD usage (in logical blocks) */ - u32 used_lo; /* DASD usage (in logical blocks) */ -} dasd_t; - - -/* from jfs_superblock.h */ - -#define JFS_MAGIC 0x3153464A /* "JFS1" */ - -struct jfs_superblock -{ - u32 s_magic; /* 4: magic number */ - u32 s_version; /* 4: version number */ - - s64 s_size; /* 8: aggregate size in hardware/LVM blocks; - * VFS: number of blocks - */ - s32 s_bsize; /* 4: aggregate block size in bytes; - * VFS: fragment size - */ - s16 s_l2bsize; /* 2: log2 of s_bsize */ - s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ - s32 s_pbsize; /* 4: hardware/LVM block size in bytes */ - s16 s_l2pbsize; /* 2: log2 of s_pbsize */ - s16 pad; /* 2: padding necessary for alignment */ - - u32 s_agsize; /* 4: allocation group size in aggr. blocks */ - - u32 s_flag; /* 4: aggregate attributes: - * see jfs_filsys.h - */ - u32 s_state; /* 4: mount/unmount/recovery state: - * see jfs_filsys.h - */ - s32 s_compress; /* 4: > 0 if data compression */ - - pxd_t s_ait2; /* 8: first extent of secondary - * aggregate inode table - */ - - pxd_t s_aim2; /* 8: first extent of secondary - * aggregate inode map - */ - u32 s_logdev; /* 4: device address of log */ - s32 s_logserial; /* 4: log serial number at aggregate mount */ - pxd_t s_logpxd; /* 8: inline log extent */ - - pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ - - struct timestruc_t s_time; /* 8: time last updated */ - - s32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for - * the fsck service log. - * N.B. These blocks are divided among the - * versions kept. This is not a per - * version size. - * N.B. These blocks are included in the - * length field of s_fsckpxd. - */ - s8 s_fscklog; /* 1: which fsck service log is most recent - * 0 => no service log data yet - * 1 => the first one - * 2 => the 2nd one - */ - char s_fpack[11]; /* 11: file system volume name - * N.B. This must be 11 bytes to - * conform with the OS/2 BootSector - * requirements - */ - - /* extendfs() parameter under s_state & FM_EXTENDFS */ - s64 s_xsize; /* 8: extendfs s_size */ - pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ - pxd_t s_xlogpxd; /* 8: extendfs logpxd */ - /* - 128 byte boundary - */ - - /* - * DFS VFS support (preliminary) - */ - char s_attach; /* 1: VFS: flag: set when aggregate is attached - */ - u8 rsrvd4[7]; /* 7: reserved - set to 0 */ - - u64 totalUsable; /* 8: VFS: total of 1K blocks which are - * available to "normal" (non-root) users. - */ - u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for - * exclusive use of root. This value can be 0, - * and if it is then totalUsable will be equal - * to # of blocks in aggregate. I believe this - * means that minFree + totalUsable = # blocks. - * In that case, we don't need to store both - * totalUsable and minFree since we can compute - * one from the other. I would guess minFree - * would be the one we should store, and - * totalUsable would be the one we should - * compute. (Just a guess...) - */ - - u64 realFree; /* 8: VFS: # of free 1K blocks can be used by - * "normal" users. It may be this is something - * we should compute when asked for instead of - * storing in the superblock. I don't know how - * often this information is needed. - */ - /* - * graffiti area - */ -}; - -/* from jfs_dtree.h */ - -/* - * entry segment/slot - * - * an entry consists of type dependent head/only segment/slot and - * additional segments/slots linked vi next field; - * N.B. last/only segment of entry is terminated by next = -1; - */ -/* - * directory page slot - */ -typedef struct { - s8 next; /* 1: */ - s8 cnt; /* 1: */ - UniChar name[15]; /* 30: */ -} dtslot_t; /* (32) */ - -#define DTSLOTDATALEN 15 - -/* - * internal node entry head/only segment - */ -typedef struct { - pxd_t xd; /* 8: child extent descriptor */ - - s8 next; /* 1: */ - u8 namlen; /* 1: */ - UniChar name[11]; /* 22: 2-byte aligned */ -} idtentry_t; /* (32) */ - -/* - * leaf node entry head/only segment - * - * For legacy filesystems, name contains 13 unichars -- no index field - */ -typedef struct { - u32 inumber; /* 4: 4-byte aligned */ - s8 next; /* 1: */ - u8 namlen; /* 1: */ - UniChar name[11]; /* 22: 2-byte aligned */ - u32 index; /* 4: index into dir_table */ -} ldtentry_t; /* (32) */ - -#define DTLHDRDATALEN 11 - -/* - * dir_table used for directory traversal during readdir -*/ - -/* - * Maximum entry in inline directory table - */ - -typedef struct dir_table_slot { - u8 rsrvd; /* 1: */ - u8 flag; /* 1: 0 if free */ - u8 slot; /* 1: slot within leaf page of entry */ - u8 addr1; /* 1: upper 8 bits of leaf page address */ - u32 addr2; /* 4: lower 32 bits of leaf page address -OR- - index of next entry when this entry was deleted */ -} dir_table_slot_t; /* (8) */ - -/* - * directory root page (in-line in on-disk inode): - * - * cf. dtpage_t below. - */ -typedef union { - struct { - dasd_t DASD; /* 16: DASD limit/usage info F226941 */ - - u8 flag; /* 1: */ - s8 nextindex; /* 1: next free entry in stbl */ - s8 freecnt; /* 1: free count */ - s8 freelist; /* 1: freelist header */ - - u32 idotdot; /* 4: parent inode number */ - - s8 stbl[8]; /* 8: sorted entry index table */ - } header; /* (32) */ - - dtslot_t slot[9]; -} dtroot_t; - -/* - * directory regular page: - * - * entry slot array of 32 byte slot - * - * sorted entry slot index table (stbl): - * contiguous slots at slot specified by stblindex, - * 1-byte per entry - * 512 byte block: 16 entry tbl (1 slot) - * 1024 byte block: 32 entry tbl (1 slot) - * 2048 byte block: 64 entry tbl (2 slot) - * 4096 byte block: 128 entry tbl (4 slot) - * - * data area: - * 512 byte block: 16 - 2 = 14 slot - * 1024 byte block: 32 - 2 = 30 slot - * 2048 byte block: 64 - 3 = 61 slot - * 4096 byte block: 128 - 5 = 123 slot - * - * N.B. index is 0-based; index fields refer to slot index - * except nextindex which refers to entry index in stbl; - * end of entry stot list or freelist is marked with -1. - */ -typedef union { - struct { - s64 next; /* 8: next sibling */ - s64 prev; /* 8: previous sibling */ - - u8 flag; /* 1: */ - s8 nextindex; /* 1: next entry index in stbl */ - s8 freecnt; /* 1: */ - s8 freelist; /* 1: slot index of head of freelist */ - - u8 maxslot; /* 1: number of slots in page slot[] */ - s8 stblindex; /* 1: slot index of start of stbl */ - u8 rsrvd[2]; /* 2: */ - - pxd_t self; /* 8: self pxd */ - } header; /* (32) */ - - dtslot_t slot[128]; -} dtpage_t; - -/* from jfs_xtree.h */ - -/* - * extent allocation descriptor (xad) - */ -typedef struct xad { - unsigned flag:8; /* 1: flag */ - unsigned rsvrd:16; /* 2: reserved */ - unsigned off1:8; /* 1: offset in unit of fsblksize */ - u32 off2; /* 4: offset in unit of fsblksize */ - unsigned len:24; /* 3: length in unit of fsblksize */ - unsigned addr1:8; /* 1: address in unit of fsblksize */ - u32 addr2; /* 4: address in unit of fsblksize */ -} xad_t; /* (16) */ - -/* xad_t field extraction */ -#define offsetXAD(xad) (((s64)((xad)->off1)) << 32 | ((xad)->off2)) -#define addressXAD(xad) (((s64)((xad)->addr1)) << 32 | ((xad)->addr2)) -#define lengthXAD(xad) ((xad)->len) - -/* possible values for maxentry */ -#define XTPAGEMAXSLOT 256 -#define XTENTRYSTART 2 - -/* - * xtree page: - */ -typedef union { - struct xtheader { - s64 next; /* 8: */ - s64 prev; /* 8: */ - - u8 flag; /* 1: */ - u8 rsrvd1; /* 1: */ - s16 nextindex; /* 2: next index = number of entries */ - s16 maxentry; /* 2: max number of entries */ - s16 rsrvd2; /* 2: */ - - pxd_t self; /* 8: self */ - } header; /* (32) */ - - xad_t xad[XTPAGEMAXSLOT]; /* 16 * maxentry: xad array */ -} xtpage_t; - -/* from jfs_dinode.h */ - -struct dinode { - /* - * I. base area (128 bytes) - * ------------------------ - * - * define generic/POSIX attributes - */ - u32 di_inostamp; /* 4: stamp to show inode belongs to fileset */ - s32 di_fileset; /* 4: fileset number */ - u32 di_number; /* 4: inode number, aka file serial number */ - u32 di_gen; /* 4: inode generation number */ - - pxd_t di_ixpxd; /* 8: inode extent descriptor */ - - s64 di_size; /* 8: size */ - s64 di_nblocks; /* 8: number of blocks allocated */ - - u32 di_nlink; /* 4: number of links to the object */ - - u32 di_uid; /* 4: user id of owner */ - u32 di_gid; /* 4: group id of owner */ - - u32 di_mode; /* 4: attribute, format and permission */ - - struct timestruc_t di_atime; /* 8: time last data accessed */ - struct timestruc_t di_ctime; /* 8: time last status changed */ - struct timestruc_t di_mtime; /* 8: time last data modified */ - struct timestruc_t di_otime; /* 8: time created */ - - dxd_t di_acl; /* 16: acl descriptor */ - - dxd_t di_ea; /* 16: ea descriptor */ - - s32 di_next_index; /* 4: Next available dir_table index */ - - s32 di_acltype; /* 4: Type of ACL */ - - /* - * Extension Areas. - * - * Historically, the inode was partitioned into 4 128-byte areas, - * the last 3 being defined as unions which could have multiple - * uses. The first 96 bytes had been completely unused until - * an index table was added to the directory. It is now more - * useful to describe the last 3/4 of the inode as a single - * union. We would probably be better off redesigning the - * entire structure from scratch, but we don't want to break - * commonality with OS/2's JFS at this time. - */ - union { - struct { - /* - * This table contains the information needed to - * find a directory entry from a 32-bit index. - * If the index is small enough, the table is inline, - * otherwise, an x-tree root overlays this table - */ - dir_table_slot_t _table[12]; /* 96: inline */ - - dtroot_t _dtroot; /* 288: dtree root */ - } _dir; /* (384) */ -#define di_dirtable u._dir._table -#define di_dtroot u._dir._dtroot -#define di_parent di_dtroot.header.idotdot -#define di_DASD di_dtroot.header.DASD - - struct { - union { - u8 _data[96]; /* 96: unused */ - struct { - void *_imap; /* 4: unused */ - u32 _gengen; /* 4: generator */ - } _imap; - } _u1; /* 96: */ -#define di_gengen u._file._u1._imap._gengen - - union { - xtpage_t _xtroot; - struct { - u8 unused[16]; /* 16: */ - dxd_t _dxd; /* 16: */ - union { - u32 _rdev; /* 4: */ - u8 _fastsymlink[128]; - } _u; - u8 _inlineea[128]; - } _special; - } _u2; - } _file; -#define di_xtroot u._file._u2._xtroot -#define di_dxd u._file._u2._special._dxd -#define di_btroot di_xtroot -#define di_inlinedata u._file._u2._special._u -#define di_rdev u._file._u2._special._u._rdev -#define di_fastsymlink u._file._u2._special._u._fastsymlink -#define di_inlineea u._file._u2._special._inlineea - } u; -}; - -typedef struct dinode dinode_t; - -/* di_mode */ -#define IFMT 0xF000 /* S_IFMT - mask of file type */ -#define IFDIR 0x4000 /* S_IFDIR - directory */ -#define IFREG 0x8000 /* S_IFREG - regular file */ -#define IFLNK 0xA000 /* S_IFLNK - symbolic link */ - -/* extended mode bits (on-disk inode di_mode) */ -#define INLINEEA 0x00040000 /* inline EA area free */ - -/* from jfs_imap.h */ - -#define EXTSPERIAG 128 /* number of disk inode extent per iag */ -#define SMAPSZ 4 /* number of words per summary map */ -#define MAXAG 128 /* maximum number of allocation groups */ - -/* - * inode allocation map: - * - * inode allocation map consists of - * . the inode map control page and - * . inode allocation group pages (per 4096 inodes) - * which are addressed by standard JFS xtree. - */ -/* - * inode allocation group page (per 4096 inodes of an AG) - */ -typedef struct { - s64 agstart; /* 8: starting block of ag */ - s32 iagnum; /* 4: inode allocation group number */ - s32 inofreefwd; /* 4: ag inode free list forward */ - s32 inofreeback; /* 4: ag inode free list back */ - s32 extfreefwd; /* 4: ag inode extent free list forward */ - s32 extfreeback; /* 4: ag inode extent free list back */ - s32 iagfree; /* 4: iag free list */ - - /* summary map: 1 bit per inode extent */ - s32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes; - * note: this indicates free and backed - * inodes, if the extent is not backed the - * value will be 1. if the extent is - * backed but all inodes are being used the - * value will be 1. if the extent is - * backed but at least one of the inodes is - * free the value will be 0. - */ - s32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */ - s32 nfreeinos; /* 4: number of free inodes */ - s32 nfreeexts; /* 4: number of free extents */ - /* (72) */ - u8 pad[1976]; /* 1976: pad to 2048 bytes */ - /* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */ - u32 wmap[EXTSPERIAG]; /* 512: working allocation map */ - u32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */ - pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */ -} iag_t; /* (4096) */ - -#endif /* _JFS_H_ */ diff --git a/src/filo/fs/shared.h b/src/filo/fs/shared.h deleted file mode 100644 index 9f2090b3..00000000 --- a/src/filo/fs/shared.h +++ /dev/null @@ -1 +0,0 @@ -/* Sorry, nothing is shared here ;) Just for GRUB compatibility. */ diff --git a/src/filo/fs/vfs.c b/src/filo/fs/vfs.c deleted file mode 100644 index 9131bf21..00000000 --- a/src/filo/fs/vfs.c +++ /dev/null @@ -1,193 +0,0 @@ -/* Interface between GRUB's fs drivers and application code */ -#include - -#include "filesys.h" -#include - -#define DEBUG_THIS DEBUG_VFS -#include - -int filepos; -int filemax; -grub_error_t errnum; -void (*disk_read_hook) (int, int, int); -void (*disk_read_func) (int, int, int); -char FSYS_BUF[FSYS_BUFLEN]; -int fsmax; - -struct fsys_entry { - char *name; - int (*mount_func) (void); - int (*read_func) (char *buf, int len); - int (*dir_func) (char *dirname); - void (*close_func) (void); - int (*embed_func) (int *start_sector, int needed_sectors); -}; - -struct fsys_entry fsys_table[] = { -# ifdef FSYS_FAT - {"fat", fat_mount, fat_read, fat_dir, 0, 0}, -# endif -# ifdef FSYS_EXT2FS - {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0}, -# endif -# ifdef FSYS_MINIX - {"minix", minix_mount, minix_read, minix_dir, 0, 0}, -# endif -# ifdef FSYS_REISERFS - {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, - reiserfs_embed}, -# endif -# ifdef FSYS_JFS - {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed}, -# endif -# ifdef FSYS_XFS - {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0}, -# endif -# ifdef FSYS_ISO9660 - {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0}, -# endif -}; - -/* NULLFS is used to read images from raw device */ -static int nullfs_dir(char *name) -{ - uint64_t dev_size; - - if (name) { - debug("can't have a named file\n"); - return 0; - } - - dev_size = (uint64_t) part_length << 9; - /* GRUB code doesn't like 2GB or bigger files */ - if (dev_size > 0x7fffffff) - dev_size = 0x7fffffff; - filemax = dev_size; - return 1; -} - -static int nullfs_read(char *buf, int len) -{ - if (devread(filepos>>9, filepos&0x1ff, len, buf)) { - filepos += len; - return len; - } else - return 0; -} - -static struct fsys_entry nullfs = - {"nullfs", 0, nullfs_read, nullfs_dir, 0, 0}; - -static struct fsys_entry *fsys; - -int mount_fs(void) -{ - int i; - - for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) { - if (fsys_table[i].mount_func()) { - fsys = &fsys_table[i]; - printf("Mounted %s\n", fsys->name); - return 1; - } - } - fsys = 0; - printf("Unknown filesystem type\n"); - return 0; -} - -int file_open(const char *filename) -{ - - char dev[32]; -// char *dev=0; - const char *path; - int len; - int retval = 0; - int reopen; - - path = strchr(filename, ':'); - if (path) { - len = path - filename; - path++; - //dev = malloc(len + 1); - memcpy(dev, filename, len); - dev[len] = '\0'; - } else { - /* No colon is given. Is this device or filename? */ - if (filename[0] == '/') { - /* Anything starts with '/' must be a filename */ - // dev = 0; - dev[0]=0; - - path = filename; - } else { - memcpy(dev, filename, 32); -// dev = strdup(filename); - path = 0; - } - } - debug("dev=%s, path=%s\n", dev, path); - - if (dev && dev[0]) { - if (!devopen(dev, &reopen)) { - fsys = 0; - goto out; - } - if (!reopen) - fsys = 0; - } - - if (path) { - if (!fsys || fsys==&nullfs) { - if (!mount_fs()) - goto out; - } - using_devsize = 0; - if (!path[0]) { - printf("No filename is given\n"); - goto out; - } - } else - fsys = &nullfs; - - filepos = 0; - errnum = 0; - if (!fsys->dir_func((char *) path)) { - printf("errnum=%d\n",errnum); -// printf("File not found\n"); - goto out; - } - retval = 1; -out: -// if (dev) -// free(dev); - return retval; -} - -int file_read(void *buf, unsigned long len) -{ - if (filepos < 0 || filepos > filemax) - filepos = filemax; - if (len < 0 || len > filemax-filepos) - len = filemax - filepos; - errnum = 0; - return fsys->read_func(buf, len); -} - -int file_seek(unsigned long offset) -{ - filepos = offset; - return filepos; -} - -unsigned long file_size(void) -{ - return filemax; -} - -void file_close(void) -{ -} - diff --git a/src/filo/fs/xfs.h b/src/filo/fs/xfs.h deleted file mode 100644 index 6a2f8fe0..00000000 --- a/src/filo/fs/xfs.h +++ /dev/null @@ -1,546 +0,0 @@ -/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#ifndef _BITS_TYPES_H -typedef signed char __int8_t; -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#endif - -typedef __uint64_t xfs_ino_t; -typedef __uint32_t xfs_agino_t; -typedef __int64_t xfs_daddr_t; -typedef __int64_t xfs_off_t; -typedef __uint8_t uuid_t[16]; - - -/* those are from xfs_types.h */ - -typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */ -typedef __uint32_t xfs_extlen_t; /* extent length in blocks */ -typedef __uint32_t xfs_agnumber_t; /* allocation group number */ -typedef __int32_t xfs_extnum_t; /* # of extents in a file */ -typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */ -typedef __int64_t xfs_fsize_t; /* bytes in a file */ - -typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ -typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */ - -/* - * Disk based types: - */ -typedef __uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */ -typedef __uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */ -typedef __uint64_t xfs_drtbno_t; /* extent (block) in realtime area */ -typedef __uint64_t xfs_dfiloff_t; /* block number in a file */ - -typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ -typedef __uint64_t xfs_fileoff_t; /* block number in a file */ -typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */ - - -/* those are from xfs_sb.h */ - -#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/ -#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ -#define XFS_SB_VERSION_NUMBITS 0x000f - -typedef struct xfs_sb -{ - __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ - __uint32_t sb_blocksize; /* logical block size, bytes */ - xfs_drfsbno_t sb_dblocks; /* number of data blocks */ - xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */ - xfs_drtbno_t sb_rextents; /* number of realtime extents */ - uuid_t sb_uuid; /* file system unique id */ - xfs_dfsbno_t sb_logstart; /* starting block of log if internal */ - xfs_ino_t sb_rootino; /* root inode number */ - xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ - xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ - xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ - xfs_agblock_t sb_agblocks; /* size of an allocation group */ - xfs_agnumber_t sb_agcount; /* number of allocation groups */ - xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ - xfs_extlen_t sb_logblocks; /* number of log blocks */ - __uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ - __uint16_t sb_sectsize; /* volume sector size, bytes */ - __uint16_t sb_inodesize; /* inode size, bytes */ - __uint16_t sb_inopblock; /* inodes per block */ - char sb_fname[12]; /* file system name */ - __uint8_t sb_blocklog; /* log2 of sb_blocksize */ - __uint8_t sb_sectlog; /* log2 of sb_sectsize */ - __uint8_t sb_inodelog; /* log2 of sb_inodesize */ - __uint8_t sb_inopblog; /* log2 of sb_inopblock */ - __uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ - __uint8_t sb_rextslog; /* log2 of sb_rextents */ - __uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ - __uint8_t sb_imax_pct; /* max % of fs for inode space */ - /* statistics */ - /* - * These fields must remain contiguous. If you really - * want to change their layout, make sure you fix the - * code in xfs_trans_apply_sb_deltas(). - */ - __uint64_t sb_icount; /* allocated inodes */ - __uint64_t sb_ifree; /* free inodes */ - __uint64_t sb_fdblocks; /* free data blocks */ - __uint64_t sb_frextents; /* free realtime extents */ - /* - * End contiguous fields. - */ - xfs_ino_t sb_uquotino; /* user quota inode */ - xfs_ino_t sb_gquotino; /* group quota inode */ - __uint16_t sb_qflags; /* quota flags */ - __uint8_t sb_flags; /* misc. flags */ - __uint8_t sb_shared_vn; /* shared version number */ - xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ - __uint32_t sb_unit; /* stripe or raid unit */ - __uint32_t sb_width; /* stripe or raid width */ - __uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ - __uint8_t sb_dummy[7]; /* padding */ -} xfs_sb_t; - - -/* those are from xfs_btree.h */ - -/* - * Long form header: bmap btrees. - */ -typedef struct xfs_btree_lblock -{ - __uint32_t bb_magic; /* magic number for block type */ - __uint16_t bb_level; /* 0 is a leaf */ - __uint16_t bb_numrecs; /* current # of data records */ - xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */ - xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */ -} xfs_btree_lblock_t; - -/* - * Combined header and structure, used by common code. - */ -typedef struct xfs_btree_hdr -{ - __uint32_t bb_magic; /* magic number for block type */ - __uint16_t bb_level; /* 0 is a leaf */ - __uint16_t bb_numrecs; /* current # of data records */ -} xfs_btree_hdr_t; - -typedef struct xfs_btree_block -{ - xfs_btree_hdr_t bb_h; /* header */ - union { - struct { - xfs_agblock_t bb_leftsib; - xfs_agblock_t bb_rightsib; - } s; /* short form pointers */ - struct { - xfs_dfsbno_t bb_leftsib; - xfs_dfsbno_t bb_rightsib; - } l; /* long form pointers */ - } bb_u; /* rest */ -} xfs_btree_block_t; - -/* those are from xfs_bmap_btree.h */ - -/* - * Bmap root header, on-disk form only. - */ -typedef struct xfs_bmdr_block -{ - __uint16_t bb_level; /* 0 is a leaf */ - __uint16_t bb_numrecs; /* current # of data records */ -} xfs_bmdr_block_t; - -/* - * Bmap btree record and extent descriptor. - * For 32-bit kernels, - * l0:31 is an extent flag (value 1 indicates non-normal). - * l0:0-30 and l1:9-31 are startoff. - * l1:0-8, l2:0-31, and l3:21-31 are startblock. - * l3:0-20 are blockcount. - * For 64-bit kernels, - * l0:63 is an extent flag (value 1 indicates non-normal). - * l0:9-62 are startoff. - * l0:0-8 and l1:21-63 are startblock. - * l1:0-20 are blockcount. - */ - -#define BMBT_USE_64 1 - -typedef struct xfs_bmbt_rec_32 -{ - __uint32_t l0, l1, l2, l3; -} xfs_bmbt_rec_32_t; -typedef struct xfs_bmbt_rec_64 -{ - __uint64_t l0, l1; -} xfs_bmbt_rec_64_t; - -#if BMBT_USE_64 -typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ -typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; -#else /* !BMBT_USE_64 */ -typedef __uint32_t xfs_bmbt_rec_base_t; /* use this for casts */ -typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; -#endif /* BMBT_USE_64 */ - -/* - * Key structure for non-leaf levels of the tree. - */ -typedef struct xfs_bmbt_key -{ - xfs_dfiloff_t br_startoff; /* starting file offset */ -} xfs_bmbt_key_t, xfs_bmdr_key_t; - -typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */ - /* btree block header type */ -typedef struct xfs_btree_lblock xfs_bmbt_block_t; - - -/* those are from xfs_dir2.h */ -/* - * Directory version 2. - * There are 4 possible formats: - * shortform - * single block - data with embedded leaf at the end - * multiple data blocks, single leaf+freeindex block - * data blocks, node&leaf blocks (btree), freeindex blocks - * - * The shortform format is in xfs_dir2_sf.h. - * The single block format is in xfs_dir2_block.h. - * The data block format is in xfs_dir2_data.h. - * The leaf and freeindex block formats are in xfs_dir2_leaf.h. - * Node blocks are the same as the other version, in xfs_da_btree.h. - */ - -/* - * Byte offset in data block and shortform entry. - */ -typedef __uint16_t xfs_dir2_data_off_t; - -/* - * Byte offset in a directory. - */ -typedef xfs_off_t xfs_dir2_off_t; - -/* those are from xfs_da_btree.h */ -/*======================================================================== - * Directory Structure when greater than XFS_LBSIZE(mp) bytes. - *========================================================================*/ - -/* - * This structure is common to both leaf nodes and non-leaf nodes in the Btree. - * - * Is is used to manage a doubly linked list of all blocks at the same - * level in the Btree, and to identify which type of block this is. - */ -#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ -#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ - -typedef struct xfs_da_blkinfo { - xfs_dablk_t forw; /* previous block in list */ - xfs_dablk_t back; /* following block in list */ - __uint16_t magic; /* validity check on block */ - __uint16_t pad; /* unused */ -} xfs_da_blkinfo_t; - -/* - * This is the structure of the root and intermediate nodes in the Btree. - * The leaf nodes are defined above. - * - * Entries are not packed. - * - * Since we have duplicate keys, use a binary search but always follow - * all match in the block, not just the first match found. - */ - -typedef struct xfs_da_intnode { - struct xfs_da_node_hdr { /* constant-structure header block */ - xfs_da_blkinfo_t info; /* block type, links, etc. */ - __uint16_t count; /* count of active entries */ - __uint16_t level; /* level above leaves (leaf == 0) */ - } hdr; - struct xfs_da_node_entry { - xfs_dahash_t hashval; /* hash value for this descendant */ - xfs_dablk_t before; /* Btree block before this key */ - } btree[1]; /* variable sized array of keys */ -} xfs_da_intnode_t; - - -/* those are from xfs_dir2_data.h */ -/* - * Directory format 2, data block structures. - */ - -/* - * Constants. - */ -#define XFS_DIR2_DATA_FREE_TAG 0xffff -#define XFS_DIR2_DATA_FD_COUNT 3 - -/* - * Structures. - */ - -/* - * Describe a free area in the data block. - * The freespace will be formatted as a xfs_dir2_data_unused_t. - */ -typedef struct xfs_dir2_data_free { - xfs_dir2_data_off_t offset; /* start of freespace */ - xfs_dir2_data_off_t length; /* length of freespace */ -} xfs_dir2_data_free_t; - -/* - * Header for the data blocks. - * Always at the beginning of a directory-sized block. - * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. - */ -typedef struct xfs_dir2_data_hdr { - __uint32_t magic; /* XFS_DIR2_DATA_MAGIC */ - /* or XFS_DIR2_BLOCK_MAGIC */ - xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; -} xfs_dir2_data_hdr_t; - -/* - * Active entry in a data block. Aligned to 8 bytes. - * Tag appears as the last 2 bytes. - */ -typedef struct xfs_dir2_data_entry { - xfs_ino_t inumber; /* inode number */ - __uint8_t namelen; /* name length */ - __uint8_t name[1]; /* name bytes, no null */ - /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ -} xfs_dir2_data_entry_t; - -/* - * Unused entry in a data block. Aligned to 8 bytes. - * Tag appears as the last 2 bytes. - */ -typedef struct xfs_dir2_data_unused { - __uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */ - xfs_dir2_data_off_t length; /* total free length */ - /* variable offset */ - xfs_dir2_data_off_t tag; /* starting offset of us */ -} xfs_dir2_data_unused_t; - -typedef union { - xfs_dir2_data_entry_t entry; - xfs_dir2_data_unused_t unused; -} xfs_dir2_data_union_t; - - -/* those are from xfs_dir2_leaf.h */ -/* - * Directory version 2, leaf block structures. - */ - -/* - * Leaf block header. - */ -typedef struct xfs_dir2_leaf_hdr { - xfs_da_blkinfo_t info; /* header for da routines */ - __uint16_t count; /* count of entries */ - __uint16_t stale; /* count of stale entries */ -} xfs_dir2_leaf_hdr_t; - - -/* those are from xfs_dir2_block.h */ -/* - * xfs_dir2_block.h - * Directory version 2, single block format structures - */ - -/* - * The single block format is as follows: - * xfs_dir2_data_hdr_t structure - * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures - * xfs_dir2_leaf_entry_t structures - * xfs_dir2_block_tail_t structure - */ - -#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */ - -typedef struct xfs_dir2_block_tail { - __uint32_t count; /* count of leaf entries */ - __uint32_t stale; /* count of stale lf entries */ -} xfs_dir2_block_tail_t; - - -/* those are from xfs_dir2_sf.h */ - -/* - * Directory layout when stored internal to an inode. - * - * Small directories are packed as tightly as possible so as to - * fit into the literal area of the inode. - */ - -/* - * Inode number stored as 8 8-bit values. - */ -typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; - -/* - * Inode number stored as 4 8-bit values. - * Works a lot of the time, when all the inode numbers in a directory - * fit in 32 bits. - */ -typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; - -typedef union { - xfs_dir2_ino8_t i8; - xfs_dir2_ino4_t i4; -} xfs_dir2_inou_t; - -/* - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. - * Only need 16 bits, this is the byte offset into the single block form. - */ -typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t; - -/* - * The parent directory has a dedicated field, and the self-pointer must - * be calculated on the fly. - * - * Entries are packed toward the top as tightly as possible. The header - * and the elements must be bcopy()'d out into a work area to get correct - * alignment for the inode number fields. - */ -typedef struct xfs_dir2_sf_hdr { - __uint8_t count; /* count of entries */ - __uint8_t i8count; /* count of 8-byte inode #s */ - xfs_dir2_inou_t parent; /* parent dir inode number */ -} xfs_dir2_sf_hdr_t; - -typedef struct xfs_dir2_sf_entry { - __uint8_t namelen; /* actual name length */ - xfs_dir2_sf_off_t offset; /* saved offset */ - __uint8_t name[1]; /* name, variable size */ - xfs_dir2_inou_t inumber; /* inode number, var. offset */ -} xfs_dir2_sf_entry_t; - -typedef struct xfs_dir2_sf { - xfs_dir2_sf_hdr_t hdr; /* shortform header */ - xfs_dir2_sf_entry_t list[1]; /* shortform entries */ -} xfs_dir2_sf_t; - -/* those are from xfs_dinode.h */ - -#define XFS_DINODE_VERSION_1 1 -#define XFS_DINODE_VERSION_2 2 -#define XFS_DINODE_MAGIC 0x494e /* 'IN' */ - -/* - * Disk inode structure. - * This is just the header; the inode is expanded to fill a variable size - * with the last field expanding. It is split into the core and "other" - * because we only need the core part in the in-core inode. - */ -typedef struct xfs_timestamp { - __int32_t t_sec; /* timestamp seconds */ - __int32_t t_nsec; /* timestamp nanoseconds */ -} xfs_timestamp_t; - -/* - * Note: Coordinate changes to this structure with the XFS_DI_* #defines - * below and the offsets table in xfs_ialloc_log_di(). - */ -typedef struct xfs_dinode_core -{ - __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ - __uint16_t di_mode; /* mode and type of file */ - __int8_t di_version; /* inode version */ - __int8_t di_format; /* format of di_c data */ - __uint16_t di_onlink; /* old number of links to file */ - __uint32_t di_uid; /* owner's user id */ - __uint32_t di_gid; /* owner's group id */ - __uint32_t di_nlink; /* number of links to file */ - __uint16_t di_projid; /* owner's project id */ - __uint8_t di_pad[10]; /* unused, zeroed space */ - xfs_timestamp_t di_atime; /* time last accessed */ - xfs_timestamp_t di_mtime; /* time last modified */ - xfs_timestamp_t di_ctime; /* time created/inode modified */ - xfs_fsize_t di_size; /* number of bytes in file */ - xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */ - xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ - xfs_extnum_t di_nextents; /* number of extents in data fork */ - xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ - __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ - __int8_t di_aformat; /* format of attr fork's data */ - __uint32_t di_dmevmask; /* DMIG event mask */ - __uint16_t di_dmstate; /* DMIG state info */ - __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ - __uint32_t di_gen; /* generation number */ -} xfs_dinode_core_t; - -typedef struct xfs_dinode -{ - xfs_dinode_core_t di_core; - xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ - union { - xfs_bmdr_block_t di_bmbt; /* btree root block */ - xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ - xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ - char di_c[1]; /* local contents */ - } di_u; -} xfs_dinode_t; - -/* - * Values for di_format - */ -typedef enum xfs_dinode_fmt -{ - XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */ - XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */ - /* LNK: di_symlink */ - XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */ - XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */ - XFS_DINODE_FMT_UUID /* MNT: di_uuid */ -} xfs_dinode_fmt_t; - -/* - * File types (mode field) - */ -#define IFMT 0170000 /* type of file */ -#define IFDIR 0040000 /* directory */ -#define IFREG 0100000 /* regular */ -#define IFLNK 0120000 /* symbolic link */ diff --git a/src/filo/i386/context.c b/src/filo/i386/context.c deleted file mode 100644 index 54a15e35..00000000 --- a/src/filo/i386/context.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * context switching - * 2003-10 by SONE Takeshi - */ -#include - -#include "segment.h" -#include "context.h" - -#define MAIN_STACK_SIZE 16384 -#define IMAGE_STACK_SIZE 4096 - -static void start_main(void); /* forward decl. */ -void __exit_context(void); /* assembly routine */ - -/* - * Main context structure - * It is placed at the bottom of our stack, and loaded by assembly routine - * to start us up. - */ -struct context main_ctx __attribute__((section (".initctx"))) = { - .gdt_base = (uint32_t) gdt, - .gdt_limit = GDT_LIMIT, - .cs = FLAT_CS, - .ds = FLAT_DS, - .es = FLAT_DS, - .fs = FLAT_DS, - .gs = FLAT_DS, - .ss = FLAT_DS, - .esp = (uint32_t) ESP_LOC(&main_ctx), - .eip = (uint32_t) start_main, - .return_addr = (uint32_t) __exit_context, -}; - -/* This is used by assembly routine to load/store the context which - * it is to switch/switched. */ -struct context *__context = &main_ctx; - -#if 0 -/* Stack for loaded ELF image */ -static uint8_t image_stack[IMAGE_STACK_SIZE]; -#endif - -/* Pointer to startup context (physical address) */ -unsigned long __boot_ctx; - -/* - * Main starter - * This is the C function that runs first. - */ -static void start_main(void) -{ - int retval; - extern int filo(void); - - /* Save startup context, so we can refer to it later. - * We have to keep it in physical address since we will relocate. */ - __boot_ctx = virt_to_phys(__context); - - /* Start the real fun */ - retval = filo(); - - /* Pass return value to startup context. Bootloader may see it. */ - boot_ctx->eax = retval; - - /* Returning from here should jump to __exit_context */ - __context = boot_ctx; -} - -/* Setup a new context using the given stack. - */ -struct context * -init_context(uint8_t *stack, uint32_t stack_size, int num_params) -{ - struct context *ctx; - - ctx = (struct context *) - (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t))); - memset(ctx, 0, sizeof(*ctx)); - - /* Fill in reasonable default for flat memory model */ - ctx->gdt_base = virt_to_phys(gdt); - ctx->gdt_limit = GDT_LIMIT; - ctx->cs = FLAT_CS; - ctx->ds = FLAT_DS; - ctx->es = FLAT_DS; - ctx->fs = FLAT_DS; - ctx->gs = FLAT_DS; - ctx->ss = FLAT_DS; - ctx->esp = virt_to_phys(ESP_LOC(ctx)); - ctx->return_addr = virt_to_phys(__exit_context); - - return ctx; -} - -/* Switch to another context. */ -struct context *switch_to(struct context *ctx) -{ - struct context *save, *ret; - - save = __context; - __context = ctx; - asm ("pushl %cs; call __switch_context"); - ret = __context; - __context = save; - return ret; -} - -#if 0 -//We will use elf_start in Etherboot -/* Start ELF Boot image */ -uint32_t start_elf(uint32_t entry_point, uint32_t param) -{ - struct context *ctx; - - ctx = init_context(image_stack, sizeof image_stack, 1); - ctx->eip = entry_point; - ctx->param[0] = param; - ctx->eax = 0xe1fb007; - ctx->ebx = param; - - ctx = switch_to(ctx); - return ctx->eax; -} -#endif diff --git a/src/filo/i386/context.h b/src/filo/i386/context.h deleted file mode 100644 index b8731795..00000000 --- a/src/filo/i386/context.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef i386_CONTEXT_H -#define i386_CONTEXT_H - -#include - -struct context { - /* Stack Segment, placed here because of the alignment issue... */ - uint16_t ss; - /* Used with sgdt/lgdt */ - uint16_t gdt_limit; - uint32_t gdt_base; - /* General registers, accessed with pushal/popal */ - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; /* points just below eax */ - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; -#define ESP_LOC(ctx) (&(ctx)->gs) - /* Segment registers */ - uint32_t gs; - uint32_t fs; - uint32_t es; - uint32_t ds; - /* Flags */ - uint32_t eflags; - /* Code segment:offset */ - uint32_t eip; - uint32_t cs; - /* Optional stack contents */ - uint32_t return_addr; - uint32_t param[0]; -}; - -/* Create a new context in the given stack */ -struct context * -init_context(uint8_t *stack, uint32_t stack_size, int num_param); - -/* Switch context */ -struct context *switch_to(struct context *); - -/* Holds physical address of boot context */ -extern unsigned long __boot_ctx; - -/* This can always be safely used to refer to the boot context */ -#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx)) - -#endif /* i386_CONTEXT_H */ diff --git a/src/filo/i386/linux_load.c b/src/filo/i386/linux_load.c deleted file mode 100644 index 42e3edfc..00000000 --- a/src/filo/i386/linux_load.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Linux/i386 loader - * Supports bzImage, zImage and Image format. - * - * Based on work by Steve Gehlbach. - * Portions are taken from mkelfImage. - * - * 2003-09 by SONE Takeshi - */ -#include - -#include - -#include -#include - -#include "context.h" -#include "segment.h" - -#define DEBUG_THIS DEBUG_LINUXLOAD -#include - -#define LINUX_PARAM_LOC 0x90000 -#define COMMAND_LINE_LOC 0x91000 -#define GDT_LOC 0x92000 -#define STACK_LOC 0x93000 - -/* The header of Linux/i386 kernel */ -struct linux_header { - uint8_t reserved1[0x1f1]; /* 0x000 */ - uint8_t setup_sects; /* 0x1f1 */ - uint16_t root_flags; /* 0x1f2 */ - uint8_t reserved2[6]; /* 0x1f4 */ - uint16_t vid_mode; /* 0x1fa */ - uint16_t root_dev; /* 0x1fc */ - uint16_t boot_sector_magic; /* 0x1fe */ - /* 2.00+ */ - uint8_t reserved3[2]; /* 0x200 */ - uint8_t header_magic[4]; /* 0x202 */ - uint16_t protocol_version; /* 0x206 */ - uint32_t realmode_swtch; /* 0x208 */ - uint16_t start_sys; /* 0x20c */ - uint16_t kver_addr; /* 0x20e */ - uint8_t type_of_loader; /* 0x210 */ - uint8_t loadflags; /* 0x211 */ - uint16_t setup_move_size; /* 0x212 */ - uint32_t code32_start; /* 0x214 */ - uint32_t ramdisk_image; /* 0x218 */ - uint32_t ramdisk_size; /* 0x21c */ - uint8_t reserved4[4]; /* 0x220 */ - /* 2.01+ */ - uint16_t heap_end_ptr; /* 0x224 */ - uint8_t reserved5[2]; /* 0x226 */ - /* 2.02+ */ - uint32_t cmd_line_ptr; /* 0x228 */ - /* 2.03+ */ - uint32_t initrd_addr_max; /* 0x22c */ -} __attribute__ ((packed)); - - -/* Paramters passed to 32-bit part of Linux - * This is another view of the structure above.. */ -struct linux_params { - uint8_t orig_x; /* 0x00 */ - uint8_t orig_y; /* 0x01 */ - uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ - uint16_t orig_video_page; /* 0x04 */ - uint8_t orig_video_mode; /* 0x06 */ - uint8_t orig_video_cols; /* 0x07 */ - uint16_t unused2; /* 0x08 */ - uint16_t orig_video_ega_bx; /* 0x0a */ - uint16_t unused3; /* 0x0c */ - uint8_t orig_video_lines; /* 0x0e */ - uint8_t orig_video_isVGA; /* 0x0f */ - uint16_t orig_video_points; /* 0x10 */ - - /* VESA graphic mode -- linear frame buffer */ - uint16_t lfb_width; /* 0x12 */ - uint16_t lfb_height; /* 0x14 */ - uint16_t lfb_depth; /* 0x16 */ - uint32_t lfb_base; /* 0x18 */ - uint32_t lfb_size; /* 0x1c */ - uint16_t cl_magic; /* 0x20 */ -#define CL_MAGIC_VALUE 0xA33F - uint16_t cl_offset; /* 0x22 */ - uint16_t lfb_linelength; /* 0x24 */ - uint8_t red_size; /* 0x26 */ - uint8_t red_pos; /* 0x27 */ - uint8_t green_size; /* 0x28 */ - uint8_t green_pos; /* 0x29 */ - uint8_t blue_size; /* 0x2a */ - uint8_t blue_pos; /* 0x2b */ - uint8_t rsvd_size; /* 0x2c */ - uint8_t rsvd_pos; /* 0x2d */ - uint16_t vesapm_seg; /* 0x2e */ - uint16_t vesapm_off; /* 0x30 */ - uint16_t pages; /* 0x32 */ - uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ - - //struct apm_bios_info apm_bios_info; /* 0x40 */ - uint8_t apm_bios_info[0x40]; - //struct drive_info_struct drive_info; /* 0x80 */ - uint8_t drive_info[0x20]; - //struct sys_desc_table sys_desc_table; /* 0xa0 */ - uint8_t sys_desc_table[0x140]; - uint32_t alt_mem_k; /* 0x1e0 */ - uint8_t reserved5[4]; /* 0x1e4 */ - uint8_t e820_map_nr; /* 0x1e8 */ - uint8_t reserved6[9]; /* 0x1e9 */ - uint16_t mount_root_rdonly; /* 0x1f2 */ - uint8_t reserved7[4]; /* 0x1f4 */ - uint16_t ramdisk_flags; /* 0x1f8 */ -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 - uint8_t reserved8[2]; /* 0x1fa */ - uint16_t orig_root_dev; /* 0x1fc */ - uint8_t reserved9[1]; /* 0x1fe */ - uint8_t aux_device_info; /* 0x1ff */ - uint8_t reserved10[2]; /* 0x200 */ - uint8_t param_block_signature[4]; /* 0x202 */ - uint16_t param_block_version; /* 0x206 */ - uint8_t reserved11[8]; /* 0x208 */ - uint8_t loader_type; /* 0x210 */ -#define LOADER_TYPE_LOADLIN 1 -#define LOADER_TYPE_BOOTSECT_LOADER 2 -#define LOADER_TYPE_SYSLINUX 3 -#define LOADER_TYPE_ETHERBOOT 4 -#define LOADER_TYPE_KERNEL 5 - uint8_t loader_flags; /* 0x211 */ - uint8_t reserved12[2]; /* 0x212 */ - uint32_t kernel_start; /* 0x214 */ - uint32_t initrd_start; /* 0x218 */ - uint32_t initrd_size; /* 0x21c */ - uint8_t reserved12_5[8]; /* 0x220 */ - uint32_t cmd_line_ptr; /* 0x228 */ - uint8_t reserved13[164]; /* 0x22c */ - struct e820entry e820_map[E820MAX]; /* 0x2d0 */ - uint8_t reserved16[688]; /* 0x550 */ -#define COMMAND_LINE_SIZE 256 - /* Command line is copied here by 32-bit i386/kernel/head.S. - * So I will follow the boot protocol, rather than putting it - * directly here. --ts1 */ - uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ - uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ -}; - -uint64_t forced_memsize; - -/* Load the first part the file and check if it's Linux */ -static uint32_t load_linux_header(struct linux_header *hdr) -{ - int load_high; - uint32_t kern_addr; - - if (file_read(hdr, sizeof *hdr) != sizeof *hdr) { - debug("Can't read Linux header\n"); - return 0; - } - if (hdr->boot_sector_magic != 0xaa55) { - debug("Not a Linux kernel image\n"); - return 0; - } - - /* Linux is found. Print some information */ - if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { - /* This may be floppy disk image or something. - * Perform a simple (incomplete) sanity check. */ - if (hdr->setup_sects >= 16 - || file_size() - (hdr->setup_sects<<9) >= 512<<10) { - debug("This looks like a bootdisk image but not like Linux...\n"); - return 0; - } - - debugx("Possible very old Linux"); - /* This kernel does not even have a protocol version. - * Force the value. */ - hdr->protocol_version = 0; /* pre-2.00 */ - } else - printf("Found Linux"); - if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { - char kver[256]; - file_seek(hdr->kver_addr + 0x200); - if (file_read(kver, sizeof kver) != 0) { - kver[255] = 0; - printf(" version %s", kver); - } - } - debug(" (protocol %#x)", hdr->protocol_version); - load_high = 0; - if (hdr->protocol_version >= 0x200) { - debug(" (loadflags %#x)", hdr->loadflags); - load_high = hdr->loadflags & 1; - } - if (load_high) { - printf(" bzImage"); - kern_addr = 0x100000; - } else { - printf(" zImage or Image"); - kern_addr = 0x1000; - } - printf(".\n"); - - return kern_addr; -} - -/* Set up parameters for 32-bit kernel */ -static void -init_linux_params(struct linux_params *params, struct linux_header *hdr) -{ - debug("Setting up paramters at %#lx\n", virt_to_phys(params)); - memset(params, 0, sizeof *params); - - /* Copy some useful values from header */ - params->mount_root_rdonly = hdr->root_flags; - params->orig_root_dev = hdr->root_dev; - - /* Video parameters. - * This assumes we have VGA in standard 80x25 text mode, - * just like our vga.c does. - * Cursor position is filled later to allow some more printf's. */ - params->orig_video_mode = 3; - params->orig_video_cols = 80; - params->orig_video_lines = 25; - params->orig_video_isVGA = 1; - params->orig_video_points = 16; - - params->loader_type = 0xff; /* Unregistered Linux loader */ -} - -/* Memory map */ -static void -set_memory_size(struct linux_params *params, struct sys_info *info) -{ - uint32_t i; - uint32_t ramtop = 0; - struct e820entry *linux_map; - struct e820entry *filo_map; - - linux_map = params->e820_map; - - filo_map = meminfo.map; - for (i = 0; i < meminfo.map_count; i++, linux_map++, filo_map++) { - if (i < E820MAX) { - /* Convert to BIOS e820 style */ - linux_map->addr = filo_map->addr; - linux_map->size = filo_map->size; - linux_map->type = filo_map->type; -// debug("%016Lx - %016Lx\n", linux_map->addr,linux_map->addr + linux_map->size); - params->e820_map_nr = i+1; - } - - } - ramtop = meminfo.memsize; - debug("ramtop=%#xk\n", ramtop); - /* Size of memory above 1MB in KB */ - params->alt_mem_k = ramtop; - /* old style, 64MB max */ - if (ramtop >= (64<<10)) - params->ext_mem_k = (63<<10); - else - params->ext_mem_k = params->alt_mem_k; - - debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); -} - -/* - * Parse command line - * Some parameters, like initrd=, are not passed to kernel, - * we are responsible to process them. - * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. - */ -static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) -{ - const char *start, *sep, *end, *val; - char name[64]; - int len; - int k_len; - int to_kern; - char *initrd = 0; - int toolong = 0; - - forced_memsize = 0; - - if (!orig_cmdline) { - *kern_cmdline = 0; - return 0; - } - - k_len = 0; - debug("original command line: \"%s\"\n", orig_cmdline); - debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); - - start = orig_cmdline; - while (*start == ' ') - start++; - while (*start) { - end = strchr(start, ' '); - if (!end) - end = start + strlen(start); - sep = strchr(start, '='); - if (!sep || sep > end) - sep = end; - len = sep - start; - if (len >= sizeof(name)) - len = sizeof(name) - 1; - memcpy(name, start, len); - name[len] = 0; - - if (*sep == '=') { - val = sep + 1; - len = end - val; - } else { - val = 0; - len = 0; - } - - /* Only initrd= and mem= are handled here. vga= is not, - * which I believe is a paramter to the realmode part of Linux, - * which we don't execute. */ - if (strcmp(name, "initrd") == 0) { - if (!val) - printf("Missing filename to initrd parameter\n"); - else { - initrd = allot(len + 1); - memcpy(initrd, val, len); - initrd[len] = 0; - debug("initrd=%s\n", initrd); - } - /* Don't pass this to kernel */ - to_kern = 0; - } else if (strcmp(name, "mem") == 0) { - if (!val) - printf("Missing value for mem parameter\n"); - else { - forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); - if (forced_memsize == 0) - printf("Invalid mem option, ignored\n"); - if (val != end) { - printf("Garbage after mem=, ignored\n"); - forced_memsize = 0; - } -// debug("mem=%Lu\n", forced_memsize); - } - /* mem= is for both loader and kernel */ - to_kern = 1; - } else - to_kern = 1; - - if (to_kern) { - /* Copy to kernel command line buffer */ - if (k_len != 0) - kern_cmdline[k_len++] = ' '; /* put separator */ - len = end - start; - if (k_len + len >= COMMAND_LINE_SIZE) { - len = COMMAND_LINE_SIZE - k_len - 1; - if (!toolong) { - printf("Kernel command line is too long; truncated to " - "%d bytes\n", COMMAND_LINE_SIZE-1); - toolong = 1; - } - } - memcpy(kern_cmdline + k_len, start, len); - k_len += len; - } - - start = end; - while (*start == ' ') - start++; - } - kern_cmdline[k_len] = 0; - debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); - - return initrd; -} - -/* Set command line location */ -static void set_command_line_loc(struct linux_params *params, - struct linux_header *hdr) -{ - if (hdr->protocol_version >= 0x202) { - /* new style */ - params->cmd_line_ptr = COMMAND_LINE_LOC; - } else { - /* old style */ - params->cl_magic = CL_MAGIC_VALUE; - params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; - } -} - -/* Load 32-bit part of kernel */ -static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) -{ - uint32_t kern_offset, kern_size; - - if (hdr->setup_sects == 0) - hdr->setup_sects = 4; - kern_offset = (hdr->setup_sects + 1) * 512; - file_seek(kern_offset); - kern_size = file_size() - kern_offset; - debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); - - if (using_devsize) { - printf("Attempt to load up to end of device as kernel; " - "specify the image size\n"); - return 0; - } - - printf("Loading kernel... "); - if (file_read(phys_to_virt(kern_addr), kern_size) != kern_size) { - printf("Can't read kernel\n"); - return 0; - } - printf("ok\n"); - - return kern_size; -} - -static int load_initrd(struct linux_header *hdr, struct sys_info *info, - uint32_t kern_end, struct linux_params *params, const char *initrd_file) -{ - uint32_t max; - uint32_t start, end, size; - uint64_t forced; - extern char _virt_start[], _end[]; - - if (!file_open(initrd_file)) { - printf("Can't open initrd: %s\n", initrd_file); - return -1; - } - if (using_devsize) { - printf("Attempt to load up to end of device as initrd; " - "specify the image size\n"); - return -1; - } - size = file_size(); - - - /* Find out the kernel's restriction on how high the initrd can be - * placed */ - if (hdr->protocol_version >= 0x203) - max = hdr->initrd_addr_max; - else - max = 0x38000000; /* Hardcoded value for older kernels */ - - /* FILO itself is at the top of RAM. (relocated) - * So, try putting initrd just below us. */ - end = virt_to_phys(_virt_start); - if (end > max) - end = max; - - /* If "mem=" option is given, we have to put the initrd within - * the specified range. */ - if (forced_memsize) { - forced = forced_memsize; - if (forced > max) - forced = max; - /* If the "mem=" is lower, it's easy */ - if (forced <= end) - end = forced; - else { - /* Otherwise, see if we can put it above us */ - if (virt_to_phys(_end) + size <= forced) - end = forced; /* Ok */ - } - } - - start = end - size; - start &= ~0xfff; /* page align */ - end = start + size; - - debug("start=%#x end=%#x\n", start, end); - - if (start < kern_end) { - printf("Initrd is too big\n"); - return -1; - } - - printf("Loading initrd... "); - if (file_read(phys_to_virt(start), size) != size) { - printf("Can't read initrd\n"); - return -1; - } - printf("ok\n"); - - params->initrd_start = start; - params->initrd_size = size; - - return 0; -} - -static void hardware_setup(void) -{ - /* Disable nmi */ - outb(0x80, 0x70); - - /* Make sure any coprocessor is properly reset.. */ - outb(0, 0xf0); - outb(0, 0xf1); - - /* we're getting screwed again and again by this problem of the 8259. - * so we're going to leave this lying around for inclusion into - * crt0.S on an as-needed basis. - * - * well, that went ok, I hope. Now we have to reprogram the interrupts :-( - * we put them right after the intel-reserved hardware interrupts, at - * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really - * messed this up with the original PC, and they haven't been able to - * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, - * which is used for the internal hardware interrupts as well. We just - * have to reprogram the 8259's, and it isn't fun. - */ - - outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ - outb(0x11, 0xA0); /* and to 8259A-2 */ - - outb(0x20, 0x21); /* start of hardware int's (0x20) */ - outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ - - outb(0x04, 0x21); /* 8259-1 is master */ - outb(0x02, 0xA1); /* 8259-2 is slave */ - - outb(0x01, 0x21); /* 8086 mode for both */ - outb(0x01, 0xA1); - - outb(0xFF, 0xA1); /* mask off all interrupts for now */ - outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ -} - -/* Start Linux */ -static int start_linux(uint32_t kern_addr, struct linux_params *params) -{ - struct segment_desc *linux_gdt; - struct context *ctx; -#if 0 - extern int cursor_x, cursor_y; -#endif - - ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); - - /* Linux expects GDT being in low memory */ - linux_gdt = phys_to_virt(GDT_LOC); - memset(linux_gdt, 0, 13*sizeof(struct segment_desc)); - /* Normal kernel code/data segments */ - linux_gdt[2] = gdt[FLAT_CODE]; - linux_gdt[3] = gdt[FLAT_DATA]; - /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible - * segments (2 and 3), so it SHOULD not be a problem. - * However, some distro kernels (eg. RH9) with backported threading - * patch use 12 and 13 also when booting... */ - linux_gdt[12] = gdt[FLAT_CODE]; - linux_gdt[13] = gdt[FLAT_DATA]; - ctx->gdt_base = GDT_LOC; - ctx->gdt_limit = 14*8-1; - ctx->cs = 0x10; - ctx->ds = 0x18; - ctx->es = 0x18; - ctx->fs = 0x18; - ctx->gs = 0x18; - ctx->ss = 0x18; - - /* Parameter location */ - ctx->esi = virt_to_phys(params); - - /* Entry point */ - ctx->eip = kern_addr; - - debug("eip=%#x\n", kern_addr); - printf("Jumping to entry point...\n"); - -#ifdef VGA_CONSOLE - /* Update VGA cursor position. - * This must be here because the printf changes the value! */ -#if 0 - params->orig_x = cursor_x; - params->orig_y = cursor_y; -#endif -#endif - - /* Go... */ - ctx = switch_to(ctx); - - /* It's impossible but... */ - printf("Returned with eax=%#x\n", ctx->eax); - - return ctx->eax; -} - -int linux_load(struct sys_info *info, const char *file, const char *cmdline) -{ - struct linux_header hdr; - struct linux_params *params; - uint32_t kern_addr, kern_size; - char *initrd_file = 0; - - if (!file_open(file)) - return -1; - - kern_addr = load_linux_header(&hdr); - if (kern_addr == 0) - return LOADER_NOT_SUPPORT; - - params = phys_to_virt(LINUX_PARAM_LOC); - init_linux_params(params, &hdr); - set_memory_size(params, info); - initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); - set_command_line_loc(params, &hdr); - - kern_size = load_linux_kernel(&hdr, kern_addr); - if (kern_size == 0) { - if (initrd_file) - forget(initrd_file); - return -1; - } - - if (initrd_file) { - if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file) - != 0) { - forget(initrd_file); - return -1; - } - forget(initrd_file); - } - - hardware_setup(); - - start_linux(kern_addr, params); - return 0; -} diff --git a/src/filo/i386/multiboot.c b/src/filo/i386/multiboot.c deleted file mode 100644 index e4a49569..00000000 --- a/src/filo/i386/multiboot.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Support for Multiboot */ -#include - -#include -#include -#include - -#define DEBUG_THIS DEBUG_MULTIBOOT -#include - -/* Multiboot header, gives information to loader */ - -#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 -#define MULTIBOOT_HEADER_FLAGS 0x00000003 - -struct mbheader { - unsigned int magic, flags, checksum; -}; -const struct mbheader multiboot_header - __attribute__((section (".hdr"))) = -{ - MULTIBOOT_HEADER_MAGIC, - MULTIBOOT_HEADER_FLAGS, - -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) -}; - -/* Multiboot information structure, provided by loader to us */ - -struct multiboot_mmap { - unsigned entry_size; - unsigned base_lo, base_hi; - unsigned size_lo, size_hi; - unsigned type; -}; - -struct multiboot_info { - unsigned flags; -#define MULTIBOOT_MEM_VALID 0x01 -#define MULTIBOOT_BOOT_DEV_VALID 0x02 -#define MULTIBOOT_CMDLINE_VALID 0x04 -#define MULTIBOOT_MODS_VALID 0x08 -#define MULTIBOOT_AOUT_SYMS_VALID 0x10 -#define MULTIBOOT_ELF_SYMS_VALID 0x20 -#define MULTIBOOT_MMAP_VALID 0x40 - unsigned mem_lower; - unsigned mem_upper; - unsigned char boot_device[4]; - unsigned command_line; - unsigned mods_count; - unsigned mods_addr; - unsigned syms_num; - unsigned syms_size; - unsigned syms_addr; - unsigned syms_shndx; - unsigned mmap_length; - unsigned mmap_addr; -}; - -void collect_multiboot_info(struct sys_info *info) -{ - struct multiboot_info *mbinfo; - struct multiboot_mmap *mbmem; - unsigned mbcount, mbaddr; - int i; - struct memrange *mmap; - int mmap_count; - - if (info->boot_type != 0x2BADB002) - return; - - debug("Using Multiboot information at %#lx\n", info->boot_data); - - mbinfo = phys_to_virt(info->boot_data); - - if (mbinfo->flags & MULTIBOOT_MMAP_VALID) { - /* convert mmap records */ - mbmem = phys_to_virt(mbinfo->mmap_addr); - mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4); - mmap = malloc(mbcount * sizeof *mmap); - mmap_count = 0; - mbaddr = mbinfo->mmap_addr; - for (i = 0; i < mbcount; i++) { - mbmem = phys_to_virt(mbaddr); - debug("%08x%08x %08x%08x (%d)\n", - mbmem->base_hi, - mbmem->base_lo, - mbmem->size_hi, - mbmem->size_lo, - mbmem->type); - if (mbmem->type == 1) { /* Only normal RAM */ - mmap[mmap_count].base = mbmem->base_lo - + (((unsigned long long) mbmem->base_hi) << 32); - mmap[mmap_count].size = mbmem->size_lo - + (((unsigned long long) mbmem->size_hi) << 32); - mmap_count++; - } - mbaddr += mbmem->entry_size + 4; - if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length) - break; - } - /* simple sanity check - there should be at least 2 RAM segments - * (base 640k and extended) */ - if (mmap_count >= 2) - goto got_it; - - printf("Multiboot mmap is broken\n"); - free(mmap); - /* fall back to mem_lower/mem_upper */ - } - - if (mbinfo->flags & MULTIBOOT_MEM_VALID) { - /* use mem_lower and mem_upper */ - mmap_count = 2; - mmap = malloc(2 * sizeof(*mmap)); - mmap[0].base = 0; - mmap[0].size = mbinfo->mem_lower << 10; - mmap[1].base = 1 << 20; /* 1MB */ - mmap[1].size = mbinfo->mem_upper << 10; - goto got_it; - } - - printf("Can't get memory information from Multiboot\n"); - return; - -got_it: - info->memrange = mmap; - info->n_memranges = mmap_count; - return; -} diff --git a/src/filo/i386/segment.c b/src/filo/i386/segment.c deleted file mode 100644 index 6e370d8b..00000000 --- a/src/filo/i386/segment.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Segmentation of the i386 architecture. - * - * 2003-07 by SONE Takeshi - */ -#include - -//#include -#include -#include "segment.h" - -#define DEBUG_THIS DEBUG_SEGMENT -#include - -/* i386 lgdt argument */ -struct gdtarg { - unsigned short limit; - unsigned int base; -} __attribute__((packed)); - -/* GDT, the global descriptor table */ -struct segment_desc gdt[NUM_SEG] = { - /* 0x00: null segment */ - {0, 0, 0, 0, 0, 0}, - /* 0x08: flat code segment */ - {0xffff, 0, 0, 0x9f, 0xcf, 0}, - /* 0x10: flat data segment */ - {0xffff, 0, 0, 0x93, 0xcf, 0}, - /* 0x18: code segment for relocated execution */ - {0xffff, 0, 0, 0x9f, 0xcf, 0}, - /* 0x20: data segment for relocated execution */ - {0xffff, 0, 0, 0x93, 0xcf, 0}, -}; - -/* Copy GDT to new location and reload it */ -void move_gdt(unsigned long newgdt) -{ - struct gdtarg gdtarg; - - debug("Moving GDT to %#lx...", newgdt); - memcpy(phys_to_virt(newgdt), gdt, sizeof gdt); - gdtarg.base = newgdt; - gdtarg.limit = GDT_LIMIT; - debug("reloading GDT..."); - __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); - debug("reloading CS for fun..."); - __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS)); - debug("ok\n"); -} diff --git a/src/filo/i386/segment.h b/src/filo/i386/segment.h deleted file mode 100644 index 97eb574e..00000000 --- a/src/filo/i386/segment.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Segment indexes. Must match the gdt definition in segment.c. */ -enum { - NULL_SEG, - FLAT_CODE, - FLAT_DATA, - RELOC_CODE, - RELOC_DATA, - NUM_SEG, -}; - -/* Values for segment selector register */ -#define FLAT_CS (FLAT_CODE << 3) -#define FLAT_DS (FLAT_DATA << 3) -#define RELOC_CS (RELOC_CODE << 3) -#define RELOC_DS (RELOC_DATA << 3) - -/* i386 segment descriptor */ -struct segment_desc { - unsigned short limit_0; - unsigned short base_0; - unsigned char base_16; - unsigned char types; - unsigned char flags; - unsigned char base_24; -}; - -extern struct segment_desc gdt[NUM_SEG]; - -#define GDT_LIMIT ((NUM_SEG << 3) - 1) diff --git a/src/filo/i386/switch.S b/src/filo/i386/switch.S deleted file mode 100644 index 76ac75bf..00000000 --- a/src/filo/i386/switch.S +++ /dev/null @@ -1,116 +0,0 @@ - .globl entry, __switch_context, __exit_context, halt - - .text - .align 4 - -/* - * Entry point - * We start execution from here. - * It is assumed that CPU is in 32-bit protected mode and - * all segments are 4GB and base zero (flat model). - */ -entry: - /* Save boot context and switch to our main context. - * Main context is statically defined in C. - */ - pushl %cs - call __switch_context - - /* We get here when the main context switches back to - * the boot context. - * Return to previous bootloader. - */ - ret - -/* - * Switch execution context - * This saves registers, segments, and GDT in the stack, then - * switches the stack, and restores everything from the new stack. - * This function takes no argument. New stack pointer is - * taken from global variable __context, and old stack pointer - * is also saved to __context. This way we can just jump to - * this routine to get back to the original context. - * - * Call this routine with lcall or pushl %cs; call. - */ -__switch_context: - /* Save everything in current stack */ - pushfl /* 56 */ - pushl %ds /* 52 */ - pushl %es /* 48 */ - pushl %fs /* 44 */ - pushl %gs /* 40 */ - pushal /* 8 */ - subl $8, %esp - movw %ss, (%esp) /* 0 */ - sgdt 2(%esp) /* 2 */ - -#if 0 - /* Swap %cs and %eip on the stack, so lret will work */ - movl 60(%esp), %eax - xchgl %eax, 64(%esp) - movl %eax, 60(%esp) -#endif - - /* At this point we don't know if we are on flat segment - * or relocated. So compute the address offset from %eip. - * Assuming CS.base==DS.base==SS.base. - */ - call 1f -1: popl %ebx - subl $1b, %ebx - - /* Interrupts are not allowed... */ - cli - - /* Current context pointer is our stack pointer */ - movl %esp, %esi - - /* Normalize the ctx pointer */ - subl %ebx, %esi - - /* Swap it with new value */ - xchgl %esi, __context(%ebx) - - /* Adjust new ctx pointer for current address offset */ - addl %ebx, %esi - - /* Load new %ss and %esp to temporary */ - movzwl (%esi), %edx - movl 20(%esi), %eax - - /* Load new GDT */ - lgdt 2(%esi) - - /* Load new stack segment with new GDT */ - movl %edx, %ss - - /* Set new stack pointer, but we have to adjust it because - * pushal saves %esp value before pushal, and we want the value - * after pushal. - */ - leal -32(%eax), %esp - - /* Load the rest from new stack */ - popal - popl %gs - popl %fs - popl %es - popl %ds - popfl - - /* Finally, load new %cs and %eip */ - lret - -__exit_context: - /* Get back to the original context */ - pushl %cs - call __switch_context - - /* We get here if the other context attempt to switch to this - * dead context. This should not happen. */ - -halt: - cli - hlt - jmp halt diff --git a/src/filo/i386/sys_info.c b/src/filo/i386/sys_info.c deleted file mode 100644 index fa8c190f..00000000 --- a/src/filo/i386/sys_info.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include "context.h" -#define DEBUG_THIS DEBUG_SYS_INFO -#include - -void collect_multiboot_info(struct sys_info *); - -void collect_sys_info(struct sys_info *info) -{ - - /* Pick up paramters given by bootloader to us */ - info->boot_type = boot_ctx->eax; - info->boot_data = boot_ctx->ebx; - info->boot_arg = boot_ctx->param[0]; - debug("boot eax = %#lx\n", info->boot_type); - debug("boot ebx = %#lx\n", info->boot_data); - debug("boot arg = %#lx\n", info->boot_arg); - - collect_elfboot_info(info); - collect_linuxbios_info(info); -#ifdef MULTIBOOT_IMAGE - collect_multiboot_info(info); -#endif - -#if 0 - debug("RAM %Ld MB\n", (meminfo.memsize + 512*1024) >> 20); -#endif -} diff --git a/src/filo/main/console_x.c b/src/filo/main/console_x.c deleted file mode 100644 index fd04a939..00000000 --- a/src/filo/main/console_x.c +++ /dev/null @@ -1,74 +0,0 @@ - -#include "etherboot.h" - -#include - -int getline(char *buf, int max) -{ - int cur, ch, nonspace_seen; - - cur = 0; - while (buf[cur]) { - putchar(buf[cur]); - cur++; - } - for (;;) { - ch = getchar(); - switch (ch) { - /* end of line */ - case '\r': - case '\n': - putchar('\n'); - goto out; - /* backspace */ - case '\b': - case '\x7f': - if (cur > 0) { - cur--; - putchar('\b'); - putchar(' '); - putchar('\b'); - } - break; - /* word erase */ - case 'W' & 0x1f: /* ^W */ - nonspace_seen = 0; - while (cur) { - if (buf[cur-1] != ' ') - nonspace_seen = 1; - putchar('\b'); - putchar(' '); - putchar('\b'); - cur--; - if (nonspace_seen && cur < max-1 && cur > 0 && buf[cur-1]==' ') - break; - } - break; - /* line erase */ - case 'U' & 0x1f: /* ^U */ - while (cur) { - putchar('\b'); - putchar(' '); - putchar('\b'); - cur--; - } - cur = 0; - break; - default: - if (ch < 0x20) - break; /* ignore control char */ - if (ch >= 0x7f) - break; - if (cur + 1 < max) { - putchar(ch); /* echo back */ - buf[cur] = ch; - cur++; - } - } - } -out: - if (cur >= max) - cur = max - 1; - buf[cur] = '\0'; - return cur; -} diff --git a/src/filo/main/elfload.c b/src/filo/main/elfload.c deleted file mode 100644 index 53114ffb..00000000 --- a/src/filo/main/elfload.c +++ /dev/null @@ -1,398 +0,0 @@ -/* ELF Boot loader - * As we have seek, this implementation can be straightforward. - * 2003-07 by SONE Takeshi - */ -#include -#include -#include -#include -#include -#include - -#include -#define DEBUG_THIS DEBUG_ELFBOOT -#include - -#if 1 -//Use that in Etherboot -extern int elf_start(unsigned long __unused_i386, unsigned long entry, unsigned long param); -#define start_elf(x,y) elf_start(0, x, y) -#else -// original in filo -extern unsigned int start_elf(unsigned long entry_point, unsigned long param); -#endif - -extern char _virt_start[], _end[]; - -static char *image_name, *image_version; - -static int check_mem_ranges(struct sys_info *info, - Elf_phdr *phdr, int phnum) -{ - int i, j; - unsigned long start, end; - unsigned long prog_start, prog_end; -#if 0 - struct memrange *mem; -#else - struct e820entry *mem; -#endif - - prog_start = virt_to_phys(&_virt_start); - prog_end = virt_to_phys(&_end); - - for (i = 0; i < phnum; i++) { - if (phdr[i].p_type != PT_LOAD) - continue; - start = phdr[i].p_paddr; - end = start + phdr[i].p_memsz; - if (start < prog_start && end > prog_start) - goto conflict; - if (start < prog_end && end > prog_end) - goto conflict; -#if 0 - for (j = 0; j < info->n_memranges; j++) { - mem = &info->memrange[j]; - if (mem->base <= start && mem->base + mem->size >= end) - break; - } - if (j >= info->n_memranges) - goto badseg; -#else -#define LB_MEM_RAM 1 - for (j = 0; j < meminfo.map_count; j++) { - mem = &meminfo.map[j]; - if (mem->type!=LB_MEM_RAM) continue; - if (mem->addr <= start && mem->addr + mem->size >= end) - break; - } - if (j >= meminfo.map_count) - goto badseg; -#endif - } - return 1; - -conflict: - printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end); - -badseg: - printf("Segment %d [%#lx-%#lx] doesn't fit into memory\n", i, start, end-1); - return 0; -} - -static unsigned long process_image_notes(Elf_phdr *phdr, int phnum, - unsigned short *sum_ptr) -{ - int i; - char *buf = NULL; - int retval = 0; - unsigned long addr, end; - Elf_Nhdr *nhdr; - const char *name; - void *desc; - - for (i = 0; i < phnum; i++) { - if (phdr[i].p_type != PT_NOTE) - continue; - buf = allot(phdr[i].p_filesz); - file_seek(phdr[i].p_offset); - if (file_read(buf, phdr[i].p_filesz) != phdr[i].p_filesz) { - printf("Can't read note segment\n"); - goto out; - } - addr = (unsigned long) buf; - end = addr + phdr[i].p_filesz; - while (addr < end) { - nhdr = (Elf_Nhdr *) addr; - addr += sizeof(Elf_Nhdr); - name = (const char *) addr; - addr += (nhdr->n_namesz+3) & ~3; - desc = (void *) addr; - addr += (nhdr->n_descsz+3) & ~3; - - if (nhdr->n_namesz==sizeof(ELF_NOTE_BOOT) - && memcmp(name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT))==0) { - if (nhdr->n_type == EIN_PROGRAM_NAME) { - image_name = calloc(1, nhdr->n_descsz + 1); - memcpy(image_name, desc, nhdr->n_descsz); - } - if (nhdr->n_type == EIN_PROGRAM_VERSION) { - image_version = calloc(1, nhdr->n_descsz + 1); - memcpy(image_version, desc, nhdr->n_descsz); - } - if (nhdr->n_type == EIN_PROGRAM_CHECKSUM) { - *sum_ptr = *(unsigned short *) desc; - debug("Image checksum: %04x\n", *sum_ptr); - /* Where in the file */ - retval = phdr[i].p_offset - + (unsigned long) desc - (unsigned long) buf; - } - } - } - } -out: - if (buf) - forget(buf); - return retval; -} - -static int load_segments(Elf_phdr *phdr, int phnum, - unsigned long checksum_offset) -{ - unsigned long bytes; - unsigned int start_time, time; - int i; - int j; - - bytes = 0; - start_time = currticks(); -#if 0 - for (j = 0; j < phnum; j++) { - if (phdr[j].p_type != PT_LOAD) - continue; - debug("0 segment %d addr:%#x file:%#x mem:%#x, phdr%#x\n", - j, phdr[j].p_paddr, phdr[j].p_filesz, phdr[j].p_memsz, virt_to_phys(&phdr[j])); - } -#endif - - for (i = 0; i < phnum; i++) { - if (phdr[i].p_type != PT_LOAD) - continue; - debug("segment %d addr:%#x file:%#x mem:%#x phdr:%#x ", - i, phdr[i].p_paddr, phdr[i].p_filesz, phdr[i].p_memsz, virt_to_phys(&phdr[i])); - file_seek(phdr[i].p_offset); - debug("loading... "); - if (file_read(phys_to_virt(phdr[i].p_paddr), phdr[i].p_filesz) - != phdr[i].p_filesz) { - printf("Can't read program segment %d\n", i); - return 0; - } - bytes += phdr[i].p_filesz; - debug("clearing... "); - memset(phys_to_virt(phdr[i].p_paddr + phdr[i].p_filesz), 0, - phdr[i].p_memsz - phdr[i].p_filesz); - if (phdr[i].p_offset <= checksum_offset - && phdr[i].p_offset + phdr[i].p_filesz >= checksum_offset+2) { - debug("clearing checksum... "); - memset(phys_to_virt(phdr[i].p_paddr + checksum_offset - - phdr[i].p_offset), 0, 2); - } - debug("ok\n"); - - } - time = (currticks() - start_time)*1000/18; - printf("Loaded %d bytes in %dms (%dKB/s)\n", bytes, time, - time? bytes/time : 0); - return 1; -} - -static int verify_image(Elf_ehdr *ehdr, Elf_phdr *phdr, int phnum, - unsigned short image_sum) -{ - unsigned short sum, part_sum; - unsigned long offset; - int i; - - sum = 0; - offset = 0; - - part_sum = ipchksum(ehdr, sizeof *ehdr); - sum = add_ipchksums(offset, sum, part_sum); - offset += sizeof *ehdr; - - part_sum = ipchksum(phdr, phnum * sizeof(*phdr)); - sum = add_ipchksums(offset, sum, part_sum); - offset += phnum * sizeof(*phdr); - - for (i = 0; i < phnum; i++) { - if (phdr[i].p_type != PT_LOAD) - continue; - part_sum = ipchksum(phys_to_virt(phdr[i].p_paddr), phdr[i].p_memsz); - sum = add_ipchksums(offset, sum, part_sum); - offset += phdr[i].p_memsz; - } - - if (sum != image_sum) { - printf("Verify FAILED (image:%04x vs computed:%04x)\n", - image_sum, sum); - return 0; - } - return 1; -} - -static inline unsigned const padded(unsigned s) -{ - return (s + 3) & ~3; -} - -static Elf_Bhdr *add_boot_note(Elf_Bhdr *bhdr, const char *name, - unsigned type, const char *desc, unsigned descsz) -{ - Elf_Nhdr nhdr; - unsigned ent_size, new_size, pad; - char *addr; - - if (!bhdr) - return NULL; - - nhdr.n_namesz = name? strlen(name)+1 : 0; - nhdr.n_descsz = descsz; - nhdr.n_type = type; - ent_size = sizeof(nhdr) + padded(nhdr.n_namesz) + padded(nhdr.n_descsz); - if (bhdr->b_size + ent_size > 0xffff) { - printf("Boot notes too big\n"); - forget(bhdr); - return NULL; - } - if (bhdr->b_size + ent_size > bhdr->b_checksum) { - do { - new_size = bhdr->b_checksum * 2; - } while (new_size < bhdr->b_size + ent_size); - if (new_size > 0xffff) - new_size = 0xffff; - debug("expanding boot note size to %u\n", new_size); - bhdr = realloc(bhdr, new_size); - bhdr->b_checksum = new_size; - } - - addr = (char *) bhdr; - addr += bhdr->b_size; - memcpy(addr, &nhdr, sizeof(nhdr)); - addr += sizeof(nhdr); - - memcpy(addr, name, nhdr.n_namesz); - addr += nhdr.n_namesz; - pad = padded(nhdr.n_namesz) - nhdr.n_namesz; - memset(addr, 0, pad); - addr += pad; - - memcpy(addr, desc, nhdr.n_descsz); - addr += nhdr.n_descsz; - pad = padded(nhdr.n_descsz) - nhdr.n_descsz; - memset(addr, 0, pad); - addr += pad; - - bhdr->b_size += ent_size; - bhdr->b_records++; - return bhdr; -} - -static inline Elf_Bhdr *add_note_string(Elf_Bhdr *bhdr, const char *name, - unsigned type, const char *desc) -{ - return add_boot_note(bhdr, name, type, desc, strlen(desc) + 1); -} - -static Elf_Bhdr *build_boot_notes(struct sys_info *info, const char *cmdline) -{ - Elf_Bhdr *bhdr; - - bhdr = allot(256); - bhdr->b_signature = ELF_BHDR_MAGIC; - bhdr->b_size = sizeof *bhdr; - bhdr->b_checksum = 256; /* XXX cache the current buffer size here */ - bhdr->b_records = 0; - - if (info->firmware) - bhdr = add_note_string(bhdr, NULL, EBN_FIRMWARE_TYPE, info->firmware); - bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_NAME, program_name); - bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_VERSION, program_version); - if (cmdline) - bhdr = add_note_string(bhdr, NULL, EBN_COMMAND_LINE, cmdline); - if (!bhdr) - return bhdr; - bhdr->b_checksum = 0; - bhdr->b_checksum = ipchksum(bhdr, bhdr->b_size); - return bhdr; -} - -int elf_load(struct sys_info *info, const char *filename, const char *cmdline) -{ - Elf_ehdr ehdr; - Elf_phdr *phdr = NULL; - unsigned long phdr_size; - unsigned long checksum_offset; - unsigned short checksum; - Elf_Bhdr *boot_notes = NULL; - int retval = -1; - int image_retval; - - image_name = image_version = 0; - - if (!file_open(filename)) - goto out; - - if (file_read(&ehdr, sizeof ehdr) != sizeof ehdr) { - debug("Can't read ELF header\n"); - retval = LOADER_NOT_SUPPORT; - goto out; - } - - if (ehdr.e_ident[EI_MAG0] != ELFMAG0 - || ehdr.e_ident[EI_MAG1] != ELFMAG1 - || ehdr.e_ident[EI_MAG2] != ELFMAG2 - || ehdr.e_ident[EI_MAG3] != ELFMAG3 - || ehdr.e_ident[EI_CLASS] != ARCH_ELF_CLASS - || ehdr.e_ident[EI_DATA] != ARCH_ELF_DATA - || ehdr.e_ident[EI_VERSION] != EV_CURRENT - || ehdr.e_type != ET_EXEC - || !ARCH_ELF_MACHINE_OK(ehdr.e_machine) - || ehdr.e_version != EV_CURRENT - || ehdr.e_phentsize != sizeof(Elf_phdr)) { - debug("Not a bootable ELF image\n"); - retval = LOADER_NOT_SUPPORT; - goto out; - } - - phdr_size = ehdr.e_phnum * sizeof *phdr; - phdr = allot(phdr_size);//hack LYH otherwise some one clear the last entry - file_seek(ehdr.e_phoff); - if (file_read(phdr, phdr_size) != phdr_size) { - printf("Can't read program header\n"); - goto out; - } - - if (!check_mem_ranges(info, phdr, ehdr.e_phnum)) - goto out; - - checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum); - - printf("Loading %s", image_name ? image_name : "image"); - if (image_version) - printf(" version %s", image_version); - printf("...\n"); - - if (!load_segments(phdr, ehdr.e_phnum, checksum_offset)) - goto out; - - if (checksum_offset) { - if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum)) - goto out; - } - - boot_notes = build_boot_notes(info, cmdline); - - debug("current time: %x\n", currticks()); - - debug("entry point is %#x\n", ehdr.e_entry); - printf("Jumping to entry point...\n"); - - image_retval = start_elf(ehdr.e_entry, virt_to_phys(boot_notes)); -#if 0 - console_init(); -#endif - - printf("Image returned with return value %#x\n", image_retval); - retval = 0; - -out: - if (phdr) - forget(phdr); - if (boot_notes) - forget(boot_notes); - if (image_name) - forget(image_name); - if (image_version) - forget(image_version); - return retval; -} diff --git a/src/filo/main/elfnote.c b/src/filo/main/elfnote.c deleted file mode 100644 index 2100ec95..00000000 --- a/src/filo/main/elfnote.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Support for ELF Boot Proposal as a boot image */ - -#include -#include -#include -#include - -#include "version.h" -#define DEBUG_THIS DEBUG_ELFNOTE -#include - -/* ELF image notes provide information to the loader who boots us */ - -/* This compiles and generates correct PT_NOTE segment for me. - * If it doesn't, use assembly version below. */ - -struct elf_image_note { - Elf_Nhdr hdr0; - char name0[sizeof(ELF_NOTE_BOOT)]; - char prog_name[sizeof(PROGRAM_NAME)]; - - Elf_Nhdr hdr1; - char name1[sizeof(ELF_NOTE_BOOT)]; - char version[sizeof(PROGRAM_VERSION)]; - - Elf_Nhdr hdr2; - char name2[sizeof(ELF_NOTE_BOOT)]; - unsigned short checksum; -}; - -const struct elf_image_note elf_image_notes - __attribute__ ((section (".note.ELFBoot"))) = -{ - .hdr0 = { - .n_namesz = sizeof(ELF_NOTE_BOOT), - .n_descsz = sizeof(PROGRAM_NAME), - .n_type = EIN_PROGRAM_NAME, - }, - .name0 = ELF_NOTE_BOOT, - .prog_name = PROGRAM_NAME, - - .hdr1 = { - .n_namesz = sizeof(ELF_NOTE_BOOT), - .n_descsz = sizeof(PROGRAM_VERSION), - .n_type = EIN_PROGRAM_VERSION, - }, - .name1 = ELF_NOTE_BOOT, - .version = PROGRAM_VERSION, - - .hdr2 = { - .n_namesz = sizeof(ELF_NOTE_BOOT), - .n_descsz = sizeof(unsigned short), - .n_type = EIN_PROGRAM_CHECKSUM, - }, - .name2 = ELF_NOTE_BOOT, - .checksum = 0, /* to be computed by external tool */ -}; - -/* This is refered by other files */ -const char *program_name = elf_image_notes.prog_name; -const char *program_version = elf_image_notes.version; - -#if 0 - - /* This tells the linker to make a PT_NOTE segment. - * If the section is named just ".note", it will be - * mixed up with useless .version notes generated by GCC. - */ - .section ".note.ELFBoot", "a" - - .align 4 - .int 2f - 1f - .int 4f - 3f - .int EIN_PROGRAM_NAME -1: .asciz "ELFBoot" -2: .align 4 -3: .asciz PROGRAM_NAME -4: - - .align 4 - .int 2f - 1f - .int 4f - 3f - .int EIN_PROGRAM_VERSION -1: .asciz "ELFBoot" -2: .align 4 -3: .asciz PROGRAM_VERSION -4: - - .align 4 - .int 2f - 1f - .int 4f - 3f - .int EIN_PROGRAM_CHECKSUM -1: .asciz "ELFBoot" -2: .align 4 -3: .short 0 -4: -#endif - -/* Collect information from the ELF bootloader - * Note that we have to copy them to our own memory, - * otherwise they might be overwritten afterward. */ -void collect_elfboot_info(struct sys_info *info) -{ - Elf_Bhdr *hdr = 0; - char *addr, *end; - Elf_Nhdr *nhdr; - char *name, *desc; - - if (info->boot_type == ELF_BHDR_MAGIC) - hdr = phys_to_virt(info->boot_data); - else - hdr = phys_to_virt(info->boot_arg); - - if (hdr->b_signature != ELF_BHDR_MAGIC) - return; - - if (ipchksum(hdr, hdr->b_size) != 0) { - printf("Broken ELF boot notes\n"); - return; - } - - addr = (char *) (hdr + 1); - end = addr + hdr->b_size; - while (addr < end) { - nhdr = (Elf_Nhdr *) addr; - addr += sizeof(Elf_Nhdr); - name = addr; - addr += (nhdr->n_namesz + 3) & ~3; - desc = addr; - addr += (nhdr->n_descsz + 3) & ~3; - - if (nhdr->n_namesz == 0) { - /* Standard notes */ - switch (nhdr->n_type) { - case EBN_FIRMWARE_TYPE: - info->firmware = strdup(desc); - break; - case EBN_BOOTLOADER_NAME: - debug("Bootloader: %s\n", desc); - break; - case EBN_BOOTLOADER_VERSION: - debug("Version: %s\n", desc); - break; - case EBN_COMMAND_LINE: - info->command_line = strdup(desc); - break; - case EBN_LOADED_IMAGE: - debug("Image name: %s\n", desc); - break; - } - } - } -} diff --git a/src/filo/main/filo_x.c b/src/filo/main/filo_x.c deleted file mode 100644 index 6569c413..00000000 --- a/src/filo/main/filo_x.c +++ /dev/null @@ -1,129 +0,0 @@ -#include - -#include -#include -#include - -#define ENTER '\r' -#define ESCAPE '\x1b' - -#ifndef AUTOBOOT_FILE -#define autoboot() ((void) 0) /* nop */ -#endif - -#ifndef AUTOBOOT_DELAY -#define autoboot_delay() 0 /* success */ -#endif - -struct sys_info sys_info; - -static void init(void) -{ - collect_sys_info(&sys_info); - - printf("%s version %s\n", program_name, program_version); - -} - -static void boot(const char *line) -{ - char file[256], *param; - - /* Split filename and parameter */ - memcpy(file, line,256); -// file = strdup(line); - param = strchr(file, ' '); - if (param) { - *param = '\0'; - param++; - } - if (elf_load(&sys_info, file, param) == LOADER_NOT_SUPPORT){ - if (linux_load(&sys_info, file, param) == LOADER_NOT_SUPPORT) - printf("Unsupported image format\n"); - } -// free(file); -} - -#ifdef AUTOBOOT_FILE -#if AUTOBOOT_DELAY - -static inline int autoboot_delay(void) -{ - unsigned int timeout; - int sec, tmp; - int key; - - key = 0; - - printf("Press for default boot, or for boot prompt... "); - for (sec = AUTOBOOT_DELAY; sec>0 && key==0; sec--) { - printf("%d", sec); - timeout = currticks() + TICKS_PER_SEC; - while (currticks() < timeout) { - if (iskey()) { - key = getchar(); - if (key==ENTER || key==ESCAPE) - break; - } - } - for (tmp = sec; tmp; tmp /= 10) - printf("\b \b"); - } - if (key == 0) { - printf("timed out\n"); - return 0; /* success */ - } else { - putchar('\n'); - if (key == ESCAPE) - return -1; /* canceled */ - else - return 0; /* default accepted */ - } -} -#endif /* AUTOBOOT_DELAY */ - -static void autoboot(void) -{ - /* If Escape key is pressed already, skip autoboot */ - if (iskey() && getchar()==ESCAPE) - return; - - if (autoboot_delay()==0) { - printf("boot: %s\n", AUTOBOOT_FILE); - boot(AUTOBOOT_FILE); - } -} -#endif /* AUTOBOOT_FILE */ - -/* The main routine */ -int filo(void) -{ - char line[256]; - - /* Initialize */ - - init(); - - /* Try default image */ - autoboot(); - - /* The above didn't work, ask user */ - while (iskey()) - getchar(); -#ifdef AUTOBOOT_FILE - strncpy(line, AUTOBOOT_FILE, sizeof(line)-1); - line[sizeof(line)-1] = '\0'; -#else - line[0] = '\0'; -#endif - for (;;) { - printf("boot: "); - getline(line, sizeof line); -// BY LYH add "quit" to exit filo - if (strcmp(line,"quit")==0) break; -// if (memcmp(line,"quit",4)==0) break; - if (line[0]) - boot(line); - } - return 0; -} diff --git a/src/filo/main/lib.c b/src/filo/main/lib.c deleted file mode 100644 index 6e5020c7..00000000 --- a/src/filo/main/lib.c +++ /dev/null @@ -1,56 +0,0 @@ - -#include -#include - -char *strdup(const char *s) -{ - size_t sz = strlen(s) + 1; - char *d = allot(sz); - memcpy(d, s, sz); - return d; -} - -int isspace(int c) -{ - switch (c) { - case ' ': case '\f': case '\n': - case '\r': case '\t': case '\v': - return 1; - default: - return 0; - } -} - -unsigned int get_le32(const unsigned char *p) -{ - return ((unsigned int) p[0] << 0) - | ((unsigned int) p[1] << 8) - | ((unsigned int) p[2] << 16) - | ((unsigned int) p[3] << 24); -} - -unsigned int get_le16(const unsigned char *p) -{ - return ((unsigned int) p[0] << 0) - | ((unsigned int) p[1] << 8); -} -#if (DEBUG_ALL || DEBUG_ELFBOOT || DEBUG_ELFNOTE || DEBUG_LINUXBIOS || \ - DEBUG_MALLOC || DEBUG_MULTIBOOT || DEBUG_SEGMENT || DEBUG_SYS_INFO ||\ - DEBUG_TIMER || DEBUG_BLOCKDEV || DEBUG_PCI || DEBUG_LINUXLOAD ||\ - DEBUG_IDE || DEBUG_ELTORITO) - -// It is needed by debug for filo -void hexdump(const void *p, unsigned int len) -{ - int i; - const unsigned char *q = p; - - for (i = 0; i < len; i++) { - if (i%16==0) - printf("%04x: ", i); - printf("%02x%c", q[i], i%16==15 ? '\n' : i%8==7 ? '-' : ' '); - } - if (i%16 != 0) - putchar('\n'); -} -#endif diff --git a/src/filo/main/linuxbios_x.c b/src/filo/main/linuxbios_x.c deleted file mode 100644 index 37f9e3f1..00000000 --- a/src/filo/main/linuxbios_x.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Adapted from Etherboot 5.1.8 */ -#include -#define DEBUG_THIS DEBUG_LINUXBIOS -#include - -#if 0 - -#define for_each_lbrec(head, rec) \ - for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ - (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ - (rec->size >= 1) && \ - ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \ - rec = (struct lb_record *)(((char *)rec) + rec->size)) - -static void convert_memmap(struct lb_memory *lbmem, struct sys_info *info) -{ - int lbcount; - int i; - - lbcount = lbmem->size / sizeof(struct lb_memory_range); - info->memrange = malloc(lbcount * sizeof(struct memrange)); - info->n_memranges = 0; - for (i = 0; i < lbcount; i++) { - debug("%#016Lx %#016Lx %d\n", - lbmem->map[i].start, lbmem->map[i].size, - (int) lbmem->map[i].type); - if (lbmem->map[i].type != LB_MEM_RAM) - continue; - info->memrange[info->n_memranges].base = lbmem->map[i].start; - info->memrange[info->n_memranges].size = lbmem->map[i].size; - info->n_memranges++; - } -} -static int read_lbtable(struct lb_header *head, struct sys_info *info) -{ - int retval = 0; - - /* Read linuxbios tables... */ - struct lb_record *rec; - - for_each_lbrec(head, rec) { - switch(rec->tag) { - case LB_TAG_MEMORY: - convert_memmap((struct lb_memory *) rec, info); - retval = 1; - break; - }; - } - return retval; -} -#endif -#if 0 -//Use func in Etherboot -static unsigned long count_lb_records(void *start, unsigned long length) -{ - struct lb_record *rec; - void *end; - unsigned long count; - count = 0; - end = ((char *)start) + length; - for(rec = start; ((void *)rec < end) && - ((signed long)rec->size <= (end - (void *)rec)); - rec = (void *)(((char *)rec) + rec->size)) { - count++; - } - return count; -} -static int find_lb_table(void *start, void *end, struct lb_header **result) -{ - unsigned char *ptr; - /* For now be stupid.... */ - for(ptr = start; (void *)ptr < end; ptr += 16) { - struct lb_header *head = (struct lb_header *)ptr; - if ( (head->signature[0] != 'L') || - (head->signature[1] != 'B') || - (head->signature[2] != 'I') || - (head->signature[3] != 'O')) { - continue; - } - if (head->header_bytes != sizeof(*head)) - continue; - debug("Found canidate at: %p\n", head); - if (ipchksum((uint16_t *)head, sizeof(*head)) != 0) - continue; - debug("header checksum o.k.\n"); - if (ipchksum((uint16_t *)(ptr + sizeof(*head)), head->table_bytes) != - head->table_checksum) { - continue; - } - debug("table checksum o.k.\n"); - if (count_lb_records(ptr + sizeof(*head), head->table_bytes) != - head->table_entries) { - continue; - } - debug("record count o.k.\n"); - *result = head; - return 1; - }; - return 0; -} -#endif -void collect_linuxbios_info(struct sys_info *info) -{ -#if 0 - struct lb_header *lb_table; - int found; - debug("Searching for LinuxBIOS tables...\n"); - found = 0; - if (!found) { - found = find_lb_table(phys_to_virt(0x00000), phys_to_virt(0x01000), &lb_table); - } - if (!found) { - found = find_lb_table(phys_to_virt(0xf0000), phys_to_virt(0x100000), &lb_table); - } - if (!found) - return; - - debug("Found LinuxBIOS table at: %p\n", lb_table); -#endif - info->firmware = "LinuxBIOS"; -#if 0 - read_lbtable(lb_table, info); -#endif -} diff --git a/src/filo/main/malloc_x.c b/src/filo/main/malloc_x.c deleted file mode 100644 index 99b309aa..00000000 --- a/src/filo/main/malloc_x.c +++ /dev/null @@ -1,45 +0,0 @@ -#include - -#include - -void *calloc(size_t nmemb, size_t size) -{ - size_t alloc_size = nmemb * size; - void *mem; - - if (alloc_size < nmemb || alloc_size < size) { - printf("calloc overflow: %u, %u\n", nmemb, size); - return 0; - } - - mem = allot(alloc_size); - memset(mem, 0, alloc_size); - - return mem; -} - -void *realloc(void *mem, size_t size) -{ - size_t copy_size; - void *new_mem; - size_t *mark, addr; - - if (mem == 0) - return allot(size); - if (size == 0) { - forget(mem); - return 0; - } - - addr = virt_to_phys(mem); - mark = phys_to_virt(addr - sizeof(size_t)); - copy_size = *mark; - - if (size < copy_size) - copy_size = size; - /* XXX should optimze this */ - new_mem = allot(size); - memcpy(new_mem, mem, copy_size); - forget(mem); - return new_mem; -} diff --git a/src/filo/main/pci_x.c b/src/filo/main/pci_x.c deleted file mode 100644 index 0c88dff7..00000000 --- a/src/filo/main/pci_x.c +++ /dev/null @@ -1,124 +0,0 @@ -#ifdef CONFIG_PCI - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - */ - -#include -#include -#include - -#define DEBUG_THIS DEBUG_PCI - -#include - -struct pci_device *dev_list; -int n_devs; - -static void pci_scan_bus(void) -{ - - unsigned int first_bus, first_devfn; - unsigned int devfn, bus, buses; - - uint32_t class; - uint16_t vendor, dev_id; - uint8_t hdr_type; - - - first_bus = 0; - first_devfn = 0; - - buses=256; - for (bus = first_bus; bus < buses; ++bus) { - for (devfn = first_devfn; devfn < 0xff; ++devfn) { - -#if 1 - if (PCI_FUNC(devfn) == 0) - pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); - else if (!(hdr_type & 0x80)) /* not a multi-function device */ - continue; -#endif - - pcibios_read_config_word(bus,devfn, PCI_VENDOR_ID, &vendor); - if (vendor==0xffff || vendor==0) - continue; - - if (dev_list) { - dev_list[n_devs].bus = bus; - dev_list[n_devs].devfn = devfn; - dev_list[n_devs].vendor = vendor; - - pcibios_read_config_word(bus,devfn, PCI_DEVICE_ID, &dev_id); - dev_list[n_devs].dev_id = dev_id; - - pcibios_read_config_dword(bus,devfn, PCI_CLASS_REVISION, &class); - dev_list[n_devs].class = class; - - } - n_devs++; - } - first_devfn = 0; - } - first_bus = 0; - -} -#define DEBUG 0 - -void pci_init(void) -{ - /* Count devices */ - dev_list = 0; - n_devs = 0; - debug("Scanning PCI: "); - pci_scan_bus(); - debug("found %d devices\n", n_devs); - - /* Make the list */ - dev_list = allot(n_devs * sizeof(struct pci_device)); - n_devs = 0; - pci_scan_bus(); -#if DEBUG - { - int i; - for (i = 0; i < n_devs; i++) { - printf("%02x:%02x.%x %04x:%04x %04x %02x\n", - dev_list[i].bus, - PCI_SLOT(dev_list[i].devfn), - PCI_FUNC(dev_list[i].devfn), - dev_list[i].vendor, - dev_list[i].dev_id,((dev_list[i].class)>>16), - ((dev_list[i].class)>>8 & 0xff)); - } - } -#endif -} - -struct pci_device *pci_find_device_2(int vendor, int device, int devclass, int devclass2, int prog_if, int index) -{ - int i; - - for (i=0; i>16) || devclass2==((dev_list[i].class)>>16)) - if (prog_if < 0 || prog_if==((dev_list[i].class)>>8 & 0xff)) { - if (index == 0) - return &dev_list[i]; - index--; - } - } - - return NULL; -} - - -struct pci_device *pci_find_device(int vendor, int device, int devclass, int prog_if, int index) -{ - return pci_find_device_2(vendor, device, devclass, devclass, prog_if, index); -} - -#endif diff --git a/src/filo/main/printf_x.c b/src/filo/main/printf_x.c deleted file mode 100644 index 517e2dd2..00000000 --- a/src/filo/main/printf_x.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Adapted from LinuxBIOS */ - -/* - * - * linux/lib/vsprintf.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - */ - -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ -/* - * Wirzenius wrote this portably, Torvalds fucked it up :-) - */ - -#include "etherboot.h" -#include -#include - -/* haha, don't need ctype.c */ -#define isdigit(c) ((c) >= '0' && (c) <= '9') -#define is_digit isdigit -#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) -#define islower(c) ((c) >= 'a' && (c) <= 'z') -#define toupper(c) __toupper(c) - -static inline unsigned char __toupper(unsigned char c) -{ - if (islower(c)) - c -= 'a'-'A'; - return c; -} - - -unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) -{ - unsigned long long result = 0,value; - - if (!base) { - base = 10; - if (*cp == '0') { - base = 8; - cp++; - if ((*cp == 'x') && isxdigit(cp[1])) { - cp++; - base = 16; - } - } - } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { - result = result*base + value; - cp++; - } - if (endp) - *endp = (char *)cp; - return result; -} - -long long simple_strtoll(const char *cp,char **endp,unsigned int base) -{ - if(*cp=='-') - return -simple_strtoull(cp+1,endp,base); - return simple_strtoull(cp,endp,base); -} - -unsigned long long strtoull_with_suffix(const char *cp,char **endp,unsigned int base) -{ - unsigned long long result; - - if (!endp) { - printf("%s must be called with endp\n", __FUNCTION__); - return 0; - } - result = simple_strtoull(cp, endp, base); - switch (toupper(**endp)) { - case 'K': - result <<= 10; - ++*endp; - break; - case 'M': - result <<= 20; - ++*endp; - break; - case 'G': - result <<= 30; - ++*endp; - break; - } - return result; -} - -#if 0 -// it can be used to substitute the vsprintf.c in etherboot. And it has better -// support in numeric output suppot -//When you want to debug filo, you need to enable it and disable vsprintf.c -// to get output from filo -// BY LYH - -static int skip_atoi(const char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -#define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -static int number(int (*tx_byte)(int byte), long num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[66]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - int count = 0; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - tx_byte(' '), count++; - if (sign) - tx_byte(sign), count++; - if (type & SPECIAL) { - if (base==8) - tx_byte('0'), count++; - else if (base==16) { - tx_byte('0'), count++; - tx_byte(digits[33]), count++; - } - } - if (!(type & LEFT)) - while (size-- > 0) - tx_byte(c), count++; - while (i < precision--) - tx_byte('0'), count++; - while (i-- > 0) - tx_byte(tmp[i]), count++; - while (size-- > 0) - tx_byte(' '), count++; - return count; -} - - -int vtxprintf(int (*tx_byte)(int byte), const char *fmt, va_list args) -{ - int len; - unsigned long num; - int i, base; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - - int count; - - for (count=0; *fmt ; ++fmt) { - if (*fmt != '%') { - tx_byte(*fmt), count++; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - tx_byte(' '), count++; - tx_byte((unsigned char) va_arg(args, int)), count++; - while (--field_width > 0) - tx_byte(' '), count++; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = ""; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - tx_byte(' '), count++; - for (i = 0; i < len; ++i) - tx_byte(*s++), count++; - while (len < field_width--) - tx_byte(' '), count++; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - count += number(tx_byte, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = count; - } else { - int * ip = va_arg(args, int *); - *ip = count; - } - continue; - - case '%': - tx_byte('%'), count++; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - tx_byte('%'), count++; - if (*fmt) - tx_byte(*fmt), count++; - else - --fmt; - continue; - } - if (qualifier == 'L') - num = va_arg(args, unsigned long long); - else if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (qualifier == 'h') { - num = (unsigned short) va_arg(args, int); - if (flags & SIGN) - num = (short) num; - } else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - count += number(tx_byte, num, base, field_width, precision, flags); - } - return count; -} - -/* FIXME this global makes vsprintf non-reentrant - */ -static char *str_buf; -static int str_tx_byte(int byte) -{ - *str_buf = byte; - str_buf++; - return byte; -} - -int vsprintf(char * buf, const char *fmt, va_list args) -{ - int i; - str_buf = buf; - i = vtxprintf(str_tx_byte, fmt, args); - /* maeder/Ispiri -- The null termination was missing a deference */ - /* and was just zeroing out the pointer instead */ - *str_buf = '\0'; - return i; -} - -int sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - -void printf(const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = vtxprintf(putchar, fmt, args); - va_end(args); - return i; -} -#endif diff --git a/src/filo/usb/debug_x.c b/src/filo/usb/debug_x.c deleted file mode 100644 index 95a80b0a..00000000 --- a/src/filo/usb/debug_x.c +++ /dev/null @@ -1,433 +0,0 @@ -#ifdef USB_DISK -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - -#include "usb.h" -#include "uhci.h" -#include "debug_x.h" - -//#include - - -void dump_link( link_pointer_t *link, char *prefix) -{ - DPRINTF("%saddr: %08x\n", prefix, MEM_ADDR(link->link) ); - DPRINTF("%s raw addr: %04x\n", prefix, (link->link) <<4 ); - DPRINTF("%sterminate: %x\n", prefix, link->terminate); - DPRINTF("%squeue: %x\n", prefix, link->queue); - DPRINTF("%sdepth: %x\n", prefix, link->depth); -} - -void dump_frame_list( link_pointer_t *addr, char *prefix) -{ - int i; - - DPRINTF("%sFRAMELIST:\n",prefix); - - for(i=0;i<10; i++) { - dump_link(addr+i, prefix); - if(addr[i].queue) - dump_queue_head( MEM_ADDR(addr[i].link), ""); - else - dump_td( MEM_ADDR(addr[i].link), ""); - } -} - -void dump_hex(uchar *data, int len, char *prefix) -{ - int i=0; - - while(ipacket_type) { - case SETUP_TOKEN: - DPRINTF("%stype: SETUP\n", prefix); - break; - case OUT_TOKEN: - DPRINTF("%stype: OUT\n", prefix); - break; - case IN_TOKEN: - DPRINTF("%stype: IN\n", prefix); - break; - default: - DPRINTF("%stype: INVALID (%02x)\n", prefix, td->packet_type); - break; - } - - DPRINTF("%sretries: %x\n", prefix, td->retrys); - - if(td->isochronous) { - DPRINTF("%sisochronous\n", prefix); - } - - if(td->interrupt) { - DPRINTF("%sIOC\n", prefix); - } - - if(td->lowspeed) { - DPRINTF("%slowspeed\n", prefix); - } - - if(td->detect_short) { - DPRINTF("%sDETECT_SHORT\n", prefix); - } - - DPRINTF("%sactive: %04x\n", prefix, td->active); - DPRINTF("%sdevice_addr: %02x\n", prefix, td->device_addr); - DPRINTF("%sendpoint: %1x\n", prefix, td->endpoint); - DPRINTF("%sdata_toggle: %1x\n", prefix, td->data_toggle); - DPRINTF("%smax_transfer: %x\n", prefix, td->max_transfer); - DPRINTF("%sactual: %x\n", prefix, td->actual); - DPRINTF("%slink:\n", prefix); - - if(td->stall) { - DPRINTF("%sSTALL\n", prefix); - } - - if(td->bitstuff) { - DPRINTF("%sBITSTUFF ERROR\n", prefix); - } - - if(td->crc) { - DPRINTF("%sCRC ERROR\n", prefix); - } - - if(td->nak) { - DPRINTF("%sNAK ERROR\n", prefix); - } - - if(td->babble) { - DPRINTF("%sBABBLE ERROR\n", prefix); - } - - if(td->buffer_error) { - DPRINTF("%sBUFFER ERROR\n", prefix); - } - - if(MEM_ADDR(td->link.link) == td) { - DPRINTF("link loops back to me!\n"); - return; - } - - dump_link(&(td->link), newpre); - if(!td->link.terminate) { - if(td->link.queue) - dump_queue_head(MEM_ADDR(td->link.link), prefix ); - else - dump_td(MEM_ADDR(td->link.link), prefix); - } -} - -void dump_queue_head( queue_head_t *qh, char *prefix) -{ - char newpre[64]; - - newpre[0] = '\t'; - strcpy(newpre+1, prefix); - - DPRINTF("%sQUEUE HEAD(%x):\n", prefix, qh); - DPRINTF("%sdepth:\n", prefix); - dump_link( &(qh->depth), newpre); - - if(!qh->depth.terminate) { - if(qh->depth.queue) { - dump_queue_head(MEM_ADDR(qh->depth.link), newpre); - } - else { - dump_td( MEM_ADDR(qh->depth.link), newpre); - } - } - - - DPRINTF("%sbredth:\n", prefix); - dump_link( &(qh->bredth), newpre); - if(!qh->bredth.terminate) { - if(qh->bredth.queue) { - dump_queue_head(MEM_ADDR(qh->bredth.link), newpre); - } - else { - dump_td( MEM_ADDR(qh->bredth.link), newpre); - } - } -} - -void dump_transaction( transaction_t *trans, char *prefix) -{ - char newpre[64]; - - newpre[0] = '\t'; - strcpy(newpre+1, prefix); - - - DPRINTF("%s TRANSACTION(%x):\n", prefix, trans); - dump_queue_head( trans->qh, newpre); - - DPRINTF("%s TDs:\n", prefix); - dump_td( trans->td_list, newpre); - - DPRINTF("\n"); - if(trans->next) - dump_transaction(trans->next, prefix); -} - -void dump_usbdev( usbdev_t *dev, char *prefix) -{ - char newpre[64]; - int i; - - newpre[0] = '\t'; - strcpy(newpre+1, prefix); - - DPRINTF("%saddress: %x\n", prefix, dev->address); - DPRINTF("%sclass: %x\n", prefix, dev->class); - DPRINTF("%ssubclass: %x\n", prefix, dev->subclass); - DPRINTF("%sbulk_in: %x\n", prefix, dev->bulk_in); - DPRINTF("%sbulk_out: %x\n", prefix, dev->bulk_out); - DPRINTF("%sinterrupt: %x\n", prefix, dev->interrupt); - - DPRINTF("%sep toggle:\n", prefix); - for(i=0;itoggle[i]); - } - - DPRINTF("%sep max_packet:\n", prefix); - for(i=0;imax_packet[i]); - } -} - -void dump_all_usbdev(char *prefix) -{ - int i; - - for(i=0;ibLength); - DPRINTF("%stype: %02x\n", prefix, des->type); - DPRINTF("%sbcdVersion: %1x%1x\n", prefix, des->bcdVersion[1], des->bcdVersion[0]); - DPRINTF("%sClass: %02x\n",prefix, des->Class); - DPRINTF("%sSubClass: %02x\n",prefix, des->SubClass); - DPRINTF("%sprotocol: %02x\n",prefix, des->protocol); - DPRINTF("%smax_packet: %x\n",prefix, des->max_packet); - DPRINTF("%sidVendor: %04x\n", prefix, des->idVendor); - DPRINTF("%sidProduct: %04x\n", prefix, des->idProduct); - DPRINTF("%sbcdDeviceVersion: %1x%1x\n", prefix, des->bcdDevice[1], des->bcdDevice[0]); - DPRINTF("%siManufacturor: %02x\n", prefix, des->iManufacturor); - DPRINTF("%siProduct: %02x\n", prefix, des->iProduct); - DPRINTF("%siSerial: %02x\n", prefix, des->iSerial); - DPRINTF("%sbNumConfig: %02x\n", prefix, des->bNumConfig); - -} - -void dump_interface_descriptor( interface_descriptor_t *iface, char *prefix) -{ - - DPRINTF("%sbLength: %02x\n", prefix, iface->bLength); - DPRINTF("%stype: %02x\n", prefix, iface->type); - DPRINTF("%sbInterfaceNumber: %02x\n", prefix, iface->bInterfaceNumber); - DPRINTF("%sbAlternateSetting: %02x\n", prefix, iface->bAlternateSetting); - DPRINTF("%sbNumEndpoints: %02x\n", prefix, iface->bNumEndpoints); - DPRINTF("%sbInterfaceClass: %02x\n", prefix, iface->bInterfaceClass); - DPRINTF("%sbInterfaceSubClass: %02x\n", prefix, iface->bInterfaceSubClass); - DPRINTF("%sbInterfaceProtocol: %02x\n", prefix, iface->bInterfaceProtocol); - DPRINTF("%siInterface: %02x\n", prefix, iface->iInterface); -} - -void dump_endpoint_descriptor( endpoint_descriptor_t *ep, char *prefix) -{ - - DPRINTF("%sbLength: %02x\n", prefix, ep->bLength); - DPRINTF("%stype: %02x\n", prefix, ep->type); - DPRINTF("%sbEndpointAddress: %02x\n", prefix, ep->bEndpointAddress); - DPRINTF("%sbmAttributes: %02x\n", prefix, ep->bmAttributes); - DPRINTF("%swMaxPacketSize: %02x\n", prefix, ep->wMaxPacketSize); - DPRINTF("%sbInterval: %02x\n", prefix, ep->bInterval); -} - -void dump_config_descriptor( uchar *des, char *prefix) // YES uchar * -{ - config_descriptor_t *config; - interface_descriptor_t *iface; - endpoint_descriptor_t *ep; - char newpre[64]; - int i; - - memset(newpre,0,sizeof(newpre)); - newpre[0] = '\t'; - strcpy(newpre+1, prefix); - - config = (config_descriptor_t *) des; - iface = (interface_descriptor_t *) (des + config->bLength); - ep = (endpoint_descriptor_t *) (des + config->bLength + iface->bLength); - - // now, the config itself - DPRINTF("%sbLength: %02x\n", prefix, config->bLength); - DPRINTF("%stype: %02x\n", prefix, config->type); - DPRINTF("%swTotalLength: %04x\n", prefix, config->wTotalLength); - DPRINTF("%sbNumInterfaces: %02x\n", prefix, config->bNumInterfaces); - DPRINTF("%sbConfigurationValue: %02x\n", prefix, config->bConfigurationValue); - DPRINTF("%siConfiguration: %02x\n", prefix, config->iConfiguration); - DPRINTF("%sbmAttributes: %02x\n", prefix, config->bmAttributes); - - DPRINTF("%sbMaxPower: %02x\n", prefix, config->bMaxPower); - - DPRINTF("\n%sInterface(%x):\n", prefix, iface); - dump_interface_descriptor(iface, newpre); - - newpre[1] = '\t'; - strcpy(newpre+2, prefix); - - for(i=0; ibNumEndpoints; i++) { - DPRINTF("\n%sEndpoint (%x):\n", newpre+1, ep+i); - dump_endpoint_descriptor( ep+i, newpre); - } -} - -// Some control message bmRequestType defines -#define CTRL_DEVICE 0 -#define CONTROL_INTERFACE 1 -#define CONTROL_ENDPOINT 2 -#define CONTROL_OTHER 3 -#define CONTROL_RECIPIENT_MASK 0x1f - -#define CONTROL_TYPE_STD 0 -#define CONTROL_TYPE_CLASS 0x20 -#define CONTROL_CLASS_VENDOR 0x40 -#define CONTROL_CLASS_MASK 0x60 - -#define CONTROL_OUT 0 -#define CONTROL_IN 0x80 -#define CONTROL_DIR_MASK 0x80 - -// bRequest values -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 -#define SET_FEATURE 3 -#define SET_ADDRESS 5 - -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 - -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 - -#define GET_INTERFACE 10 -#define SET_INTERFACE 11 - -#define SYNC_FRAME 12 - -// descriptor types -#define DEVICE_DESC 1 -#define CONFIGURATION_DESC 2 -#define STRING_DESC 3 -#define INTERFACE_DESC 4 -#define ENDPOINT_DESC 5 -#define OTHERSPEED_DESC 7 -#define POWER_DESC 8 - -// features -#define FEATURE_HALT 0 -void dump_ctrlmsg( ctrl_msg_t *msg, char *prefix) -{ - DPRINTF("%sbmRequestType: %02x\n", prefix, msg->bmRequestType); - DPRINTF("%sbRequest: %02x\n", prefix, msg->bRequest); - DPRINTF("%swValue: %04x\n", prefix, msg->wValue); - DPRINTF("%swIndex: %04x\n", prefix, msg->wIndex); - DPRINTF("%swLength: %04x\n", prefix, msg->wLength); -} - -#endif diff --git a/src/filo/usb/debug_x.h b/src/filo/usb/debug_x.h deleted file mode 100644 index 109daae0..00000000 --- a/src/filo/usb/debug_x.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DEBUG_X_H -#define _DEBUG_X_H - -void dump_hex(uchar *data, int len, char *prefix); -void dump_link( link_pointer_t *link, char *prefix); -void dump_td( td_t *td, char *prefix); -void dump_queue_head( queue_head_t *qh, char *prefix); -void dump_transaction( transaction_t *trans, char *prefix); -void dump_usbdev( usbdev_t *dev, char *prefix); -void dump_uhci(uint32_t port); -//void dump_all_usbdev(char *prefix); -void dump_device_descriptor( device_descriptor_t *des, char *prefix); -void dump_interface_descriptor( interface_descriptor_t *iface, char *prefix); -void dump_endpoint_descriptor( endpoint_descriptor_t *ep, char *prefix); -void dump_config_descriptor( uchar *des, char *prefix); -void dump_ctrlmsg( ctrl_msg_t *msg, char *prefix); - -#endif diff --git a/src/filo/usb/ohci.c b/src/filo/usb/ohci.c deleted file mode 100644 index 5c84c637..00000000 --- a/src/filo/usb/ohci.c +++ /dev/null @@ -1,1437 +0,0 @@ -#ifdef USB_DISK - -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - -#define DEBUG_TD 0 -#define DEBUG_ED 0 - - -#include "usb.h" -#include "ohci.h" - - -extern int usec_offset; - -ohci_regs_t *ohci_regs; - -// It will clear the enable bit -void ohc_clear_stat(uchar dev) -{ - uint32_t value; - ohci_regs = (ohci_regs_t *)hc_base[dev]; - - value = readl(&ohci_regs->cmdstatus); - writel(value, &ohci_regs->cmdstatus); -} - -void clear_oport_stat(uint32_t port) -{ - uint32_t value; - - value = readl(port); - writel(value, port); -} - -void oport_suspend( uint32_t port) -{ - writel( RH_PS_PSS, port); - -} -void oport_wakeup( uint32_t port) -{ - writel( RH_PS_POCI, port); - -} -#if 0 -void oport_resume( uint32_t port) -{ - uint32_t value; - - value = readl(port); - value |= 0x40; - writel(value, port); - udelay(20000+usec_offset); - value &= ~0x40; - writel(value, port); - - do { - value = readl(port); - } while(value & 0x40); -} -#endif -void oport_enable( uint32_t port) -{ - uint32_t value; - - value = readl(port); - - if((value & RH_PS_CCS)) { // if connected - writel( RH_PS_PES, port); - udelay(10); - writel( RH_PS_PESC, port); // Clear Change bit - } - -} - - - -void oport_disable( uint32_t port) -{ - writel( RH_PS_CCS, port); -} - -void oport_reset(uint32_t port) -{ - - uint32_t value; - - writel( RH_PS_PRS, port); - do { - value = readl( port ); - } while (!(value & RH_PS_PRSC) ); - writel(RH_PS_PRSC, port); //Clear Change bit - -} - -void oport_reset_long(uint32_t port) -{ - oport_reset(port); -} - -#if 0 - -int ohc_stop(uchar dev) -{ - unsigned short tmp; - uint32_t ctl; - - ohci_regs = hc_base[dev]; - - ctl = readl( &ohci_regs->control); - ctl &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); - writel (ctl, &ohci_regs->control); - - return(0); -} -#endif - - -#define MAX_OHCI_TD 32 - -ohci_td_t *_ohci_td; -uint8_t _ohci_td_tag[MAX_OHCI_TD]; //1: used, 0:unused - -void init_ohci_td(){ - _ohci_td = allot2(sizeof(ohci_td_t)*MAX_OHCI_TD, 0x1f); // 32 byte aligna - if(_ohci_td==0) { - printf("init_ohci_td: NOMEM\n"); - } - memset(_ohci_td_tag, 0, sizeof(_ohci_td_tag)); -} - -ohci_td_t *td_alloc(ohci_t *ohci, int memflag){ - int i; - ohci_td_t *td; - for(i = 0; i< MAX_OHCI_TD; i++ ) { - if(_ohci_td_tag[i]==1) continue; - td = &_ohci_td[i]; - memset(td, 0, sizeof(ohci_td_t)); - td->td_dma = (void *)virt_to_phys(td); - _ohci_td_tag[i] = 1; - return td; - } - printf("td_alloc: no free slot\n"); - return 0; -} - -int td_free(ohci_t *ohci, ohci_td_t *td) { - int i; - for(i = 0; i< MAX_OHCI_TD; i++ ) { - if(_ohci_td_tag[i]==0) continue; - if(&_ohci_td[i] == td ) { - _ohci_td_tag[i] = 0; - return 1; - } - } - return 0; -} - - -struct ohci_td * -dma_to_td (struct ohci * hc, void *td_dma) -{ - int i; - ohci_td_t *td; - for(i = 0; i< MAX_OHCI_TD; i++ ) { - if(_ohci_td_tag[i]==0) continue; - td = &_ohci_td[i]; - if(td->td_dma == td_dma ) { - return td; - } - } - printf("dma_to_td: can not find td\n"); - return 0; - -} - -ohci_t _ohci_x[MAX_CONTROLLERS]; - -void ohci_init(void) -{ - init_ohci_td(); -} - -static int ohci_get_current_frame_number (struct usbdev *usb_dev) -{ - ohci_t * ohci = &_ohci_x[usb_dev->controller]; - - return le16_to_cpu (ohci->hcca->frame_no); -} - - - -static u32 roothub_a (struct ohci *hc) - { return readl (&hc->regs->roothub.a); } -static inline u32 roothub_b (struct ohci *hc) - { return readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci *hc) - { return readl (&hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci *hc, int i) - { return readl (&hc->regs->roothub.portstatus[i]);} - - -#if DEBUG_USB==1 - -#define OHCI_VERBOSE_DEBUG - -# define dbg(...) \ - do { printf(__VA_ARGS__); printf("\n"); } while (0) - -static void urb_print (struct urb * urb, char * str, int small) -{ - unsigned int pipe= urb->pipe; - - if (!urb->dev ) { - dbg("%s URB: no dev", str); - return; - } - -#ifndef OHCI_VERBOSE_DEBUG - if (urb->status != 0) -#endif - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", - str, - ohci_get_current_frame_number (urb->dev), - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? 'O': 'I', - usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): - (usb_pipecontrol (pipe)? "CTRL": "BULK"), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - urb->status, urb->status); -#ifdef OHCI_VERBOSE_DEBUG -// if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printf ("ohci.c: cmd(8):"); - for (i = 0; i < 8 ; i++) - printf (" %02x", ((u8 *) urb->setup_packet) [i]); - printf ("\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - printf("ohci.c: data(%d/%d):", - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout (pipe)? - urb->transfer_buffer_length: urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printf (" %02x", ((u8 *) urb->transfer_buffer) [i]); - printf ("%s stat:%d\n", i < len? "...": "", urb->status); - } -// } -#endif -} - -/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds (ohci_t * ohci, char * str) { - int i, j; - u32 * ed_p; - for (i= 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printf ("ohci.c: %s branch int %2d(%2x):", str, i, i); -#if 0 - while (*ed_p != 0 && j--) { - ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); - printk (" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } -#endif - printf ("\n"); - } -} -static void ohci_dump_intr_mask (char *label, u32 mask) -{ - dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} -static void maybe_print_eds (char *label, u32 value) -{ - if (value) - dbg ("%s %08x", label, value); -} -static char *hcfs2string (int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} -// dump control and status registers -static void ohci_dump_status (ohci_t *controller) -{ - struct ohci_regs *regs = controller->regs; - u32 temp; - - temp = readl (®s->revision) & 0xff; - if (temp != 0x10) - dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); - - temp = readl (®s->control); - dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string (temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = readl (®s->cmdstatus); - dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); - ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); - // intrdisable always same as intrenable - // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); - - maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); - - maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); - maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); - - maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); - maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); - - maybe_print_eds ("donehead", readl (®s->donehead)); -} - -static void ohci_dump_roothub (ohci_t *controller, int verbose) -{ - u32 temp, ndp, i; - - temp = roothub_a (controller); - if (temp == ~(u32)0) - return; - ndp = (temp & RH_A_NDP); - - if (verbose) { - dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b (controller); - dbg ("roothub.b: %08x PPCM=%04x DR=%04x", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status (controller); - dbg ("roothub.status: %08x%s%s%s%s%s%s", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", - i, - temp, - (temp & RH_PS_PRSC) ? " PRSC" : "", - (temp & RH_PS_OCIC) ? " OCIC" : "", - (temp & RH_PS_PSSC) ? " PSSC" : "", - (temp & RH_PS_PESC) ? " PESC" : "", - (temp & RH_PS_CSC) ? " CSC" : "", - - (temp & RH_PS_LSDA) ? " LSDA" : "", - (temp & RH_PS_PPS) ? " PPS" : "", - (temp & RH_PS_PRS) ? " PRS" : "", - (temp & RH_PS_POCI) ? " POCI" : "", - (temp & RH_PS_PSS) ? " PSS" : "", - - (temp & RH_PS_PES) ? " PES" : "", - (temp & RH_PS_CCS) ? " CCS" : "" - ); - } -} - -static void ohci_dump (ohci_t *controller, int verbose) -{ - dbg ("OHCI controller usb-%x state", controller->regs); - - // dumps some of the state we know about - ohci_dump_status (controller); - if (verbose) - ep_print_int_eds (controller, "hcca"); - dbg ("hcca frame #%04x", controller->hcca->frame_no); - ohci_dump_roothub (controller, 1); -} -void ohci_dump_x(uchar controller) -{ - ohci_t *ohci; - ohci = &_ohci_x[controller]; - ohci_dump (ohci, 1); -} -#endif - -/* link an ed into one of the HC chains */ - -/* ED is only enqueued and dequeued by HCD - So ep_link may only to be called two times for every device (function) -- ed, one for controled and one for bulked - one ohci may have several controled and bulked. -*/ - -int ep_link (ohci_t * ohci, ed_t * edi) -{ - volatile ed_t * ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case PIPE_CONTROL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { -// debug("ep_link control 21 ed->dma = %x\n", (uint32_t)ed->dma); - writel ((uint32_t)ed->dma, &ohci->regs->ed_controlhead); - } else { -// debug("ep_link control 22 ed->dma = %x\n", (uint32_t)ed->dma); - ohci->ed_controltail->hwNextED = cpu_to_le32 ((uint32_t)ed->dma); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail) { - /* enable control ed list */ - ohci->hc_control |= OHCI_CTRL_CLE; //5 - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = edi; - break; - - case PIPE_BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - // debug("ep_link control 31 ed->dma = %x\n", (uint32_t)ed->dma); - writel ((uint32_t)ed->dma, &ohci->regs->ed_bulkhead); - } else { - // debug("ep_link control 32 ed->dma = %x\n", (uint32_t)ed->dma); - ohci->ed_bulktail->hwNextED = cpu_to_le32 ((uint32_t)ed->dma); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail) { - /* enable bulk ed list */ - ohci->hc_control |= OHCI_CTRL_BLE; //5 - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = edi; - break; - } - return 0; -} -/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, - * but the USB stack is a little bit stateless so we do it at every transaction - * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK - * in all other cases the state is left unchanged - * the ed info fields are setted anyway even though most of them should not change */ - -ed_t * ep_add_ed ( - usbdev_t * usb_dev, - unsigned int pipe, - int interval, - int load, - int mem_flags -) -{ - ohci_t * ohci = &_ohci_x[usb_dev->controller]; - ohci_td_t * td; - ed_t * ed; - unsigned long flags; - int i; - - /* We use preallocate ed in ohci struct - numbering rule ??? - */ - i = (usb_pipeendpoint (pipe) << 1) |(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe)); - ed = (ed_t *)&ohci->ed[i]; - -// debug("ep_add_ed: usb_dev port=%x, controller = %d ohci=%x ohci->ed=%x ed=%x ed->dma=%x\n", usb_dev->port,usb_dev->controller, ohci, ohci->ed, ed, ed->dma); - - if (ed->state == ED_NEW) { - ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ - /* dummy td; end of td list for ed */ - td = td_alloc (ohci, 0); - - ed->hwTailP = cpu_to_le32 ((uint32_t)td->td_dma); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype (pipe); - ohci->ed_cnt++; // we will be used to calcaulate next pipe - -// debug("ep_add_ed 1 td=%x dma=%x ed->dma=%x ed->hwHeadP=%x ed->hwTailP=%x\n", td, td->td_dma, ed->dma, ed->hwHeadP, ed->hwTailP); - - } - - ohci->dev[usb_pipedevice (pipe)] = usb_dev; // marked the ed to this dev - - ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) - | usb_pipeendpoint (pipe) << 7 - | (usb_pipeisoc (pipe)? 0x8000: 0) - | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) - | usb_pipeslow (pipe) << 13 - | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); - -// debug("ep_add_ed: pipe=%x ed_num=%d ed->dma=%x ed->hwInfo=%x ed->hwHeadP=%x ed->hwTailP=%x\n", pipe, i, ed->dma, ed->hwINFO, ed->hwHeadP, ed->hwTailP); - - return ed; -} - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -void -td_fill (ohci_t * ohci, unsigned int info, - void *data, int len, - struct urb * urb, int index) // *data should dma address of buffer -{ - ohci_td_t * td, * td_pt; - urb_priv_t * urb_priv = urb->hcpriv; - - if (index >= urb_priv->length) { - printf("internal OHCI error: TD index > length"); - return; - } - - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = dma_to_td (ohci, - (void *)(le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf)); - -// debug("td_fill 2 td = %x, dma=%x , ed->hwHeadP=%x, ed->hwTailP=%x \n", td, td->td_dma, urb_priv->ed->hwHeadP, urb_priv->ed->hwTailP ); - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->urb = urb; - td->data_dma = data; - if (!len) - data = 0; - - - td->hwINFO = cpu_to_le32 (info); - td->hwCBP = cpu_to_le32 ((uint32_t)data); - if (data) - td->hwBE = cpu_to_le32 ((uint32_t)data + len - 1); - else - td->hwBE = 0; - td->hwNextTD = cpu_to_le32 ((uint32_t)td_pt->td_dma); - - /* append to queue */ - td->ed->hwTailP = td->hwNextTD; - // debug("td_fill 4 td->td_dma=%x, td->hwINFO=%x\n", td->td_dma, td->hwINFO ); - // debug("td_fill 5 ed->dma=%x, ed->hwHeadP=%x, ed->hwTailP=%x \n", urb_priv->ed->dma, urb_priv->ed->hwHeadP, urb_priv->ed->hwTailP ); -} - -/* prepare all TDs of a transfer */ - -void td_submit_urb (struct urb * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - ohci_t * ohci = (ohci_t *) &_ohci_x[urb->dev->controller]; - void * data; - int data_len = urb->transfer_buffer_length; - int cnt = 0; - u32 info = 0; - unsigned int toggle = 0; - void *setup_buffer; - - /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ - if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1); - } - - urb_priv->td_cnt = 0; - - if (data_len) { - data = (void *)virt_to_phys(urb->transfer_buffer); - } else - data = 0; - switch (usb_pipetype (urb->pipe)) { - case PIPE_BULK: - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; - while(data_len > 4096) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); - cnt++; -#if 0 - /* If the transfer size is multiple of the pipe mtu, - * we may need an extra TD to create a empty frame - * Note : another way to check this condition is - * to test if(urb_priv->length > cnt) - Jean II */ - if ((urb->transfer_flags & USB_ZERO_PACKET) && - usb_pipeout (urb->pipe) && - (urb->transfer_buffer_length != 0) && - ((urb->transfer_buffer_length % maxps) == 0)) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt); - cnt++; - } -#endif - -// debug("td_submit_urb 2 -- set OHCI_BLF\n"); - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ - break; - - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - setup_buffer = (void *)virt_to_phys(urb->setup_packet); -// debug("td_sumbit_urb 11 setup_buffer = %x\n", setup_buffer); - td_fill (ohci, info, setup_buffer , 8, urb, cnt++); - if (data_len > 0) { - info = usb_pipeout (urb->pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, urb, cnt++); - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, urb, cnt++); -// debug("td_sumbit_urb 11 data = %x\n", data); - -// debug("td_submit_urb 2 -- set OHCI_CLF\n"); - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ - break; - - } - if (urb_priv->length != cnt) { - debug("TD LENGTH %d != CNT %d", urb_priv->length, cnt); - } -} - -/* free HCD-private data associated with this URB */ - -void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv) -{ - int i; - int last = urb_priv->length - 1; - int len; - struct ohci_td *td; - - if (last >= 0) { -#if 0 - /* ISOC, BULK, INTR data buffer starts at td 0 - * CTRL setup starts at td 0 */ - td = urb_priv->td [0]; - - len = td->urb->transfer_buffer_length; - - /* unmap CTRL URB setup */ - if (usb_pipecontrol (td->urb->pipe)) { -// it should be freed in usb_control_msg_x -// forget2((void *)phys_to_virt((uint32_t)td->data_dma)); // 8 bytes - - /* CTRL data buffer starts at td 1 if len > 0 */ - if (len && last > 0) - td = urb_priv->td [1]; - } - - /* unmap data buffer */ - if (len && td->data_dma) { -// Don't need -// forget2((void *)phys_to_virt((uint32_t)td->data_dma)); - } -#endif - - for (i = 0; i <= last; i++) { - td = urb_priv->td [i]; - if (td) - td_free (hc, td); - } - } -#if URB_PRE_ALLOCATE!=1 - forget2((void *)urb_priv); -#endif -} - -/* get a transfer request */ - -int ohci_submit_urb (struct urb * urb) -{ - ohci_t * ohci; - ed_t * ed; - urb_priv_t * urb_priv; - unsigned int pipe = urb->pipe; - int i, size = 0; - int mem_flags = 0; - - if (!urb->dev) - return -ENODEV; - - if (urb->hcpriv) /* urb already in use */ - return -EINVAL; - - - ohci = (ohci_t *) &_ohci_x[urb->dev->controller]; -// printf("ohci_submit_urb: urb->dev port=%x, controller = %d ohci=%x ohci->ed=%x ohci->hcca=%x\n", urb->dev->port,urb->dev->controller, ohci, ohci->ed, ohci->hcca); - -#if DEBUG_USB==1 -// urb_print (urb, "SUB", usb_pipein (pipe)); -#endif - - -#if 0 - /* handle a request to the virtual root hub */ - if (usb_pipedevice (pipe) == ohci->rh.devnum) - return rh_submit_urb (urb); - - /* when controller's hung, permit only roothub cleanup attempts - * such as powering down ports */ - if (ohci->disabled) { - usb_dec_dev_use (urb->dev); - return -ESHUTDOWN; - } -#endif - - /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) { - return -ENOMEM; - } -// debug("ohci_submit_usb: ed->dma=%x\n", ed->dma); - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (urb->transfer_buffer_length - 1) / 4096 + 1; -#if 0 - /* If the transfer size is multiple of the pipe mtu, - * we may need an extra TD to create a empty frame - * Jean II */ - if ((urb->transfer_flags & USB_ZERO_PACKET) && - usb_pipeout (pipe) && - (urb->transfer_buffer_length != 0) && - ((urb->transfer_buffer_length % maxps) == 0)) - size++; -#endif - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (urb->transfer_buffer_length == 0)? 2: - (urb->transfer_buffer_length - 1) / 4096 + 3; - break; - } - - /* allocate the private part of the URB */ -#if URB_PRE_ALLOCATE!=1 - urb_priv = allot2 (sizeof (urb_priv_t) + size * sizeof (ohci_td_t *), 0xff); - if (urb_priv == 0) { - printf("ohci_submit_usb: urb_priv allocated no mem\n"); - return -ENOMEM; - } -#else - urb_priv = ohci->urb_priv; -#endif - memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (ohci_td_t *)); - - /* fill the private part of the URB */ - urb_priv->length = size; - urb_priv->ed = ed; - - /* allocate the TDs (updating hash chains) */ - for (i = 0; i < size; i++) { - urb_priv->td[i] = td_alloc (ohci, 0); - if (!urb_priv->td[i]) { - urb_priv->length = i; - urb_free_priv (ohci, urb_priv); - return -ENOMEM; - } - } - - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_free_priv (ohci, urb_priv); - return -EINVAL; - } - - urb->actual_length = 0; - urb->hcpriv = urb_priv; - urb->status = USB_ST_URB_PENDING; - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) { - ep_link (ohci, ed); - } - - /* fill the TDs and link it to the ed */ - td_submit_urb (urb); - -#if 0 - /* drive timeouts by SF (messy, but works) */ - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -#endif - - return 0; -} -/* calculate the transfer length and update the urb */ - -void dl_transfer_length(ohci_td_t * td) -{ - u32 tdINFO, tdBE, tdCBP; - struct urb * urb = td->urb; - urb_priv_t * urb_priv = urb->hcpriv; - - tdINFO = le32_to_cpup (&td->hwINFO); - tdBE = le32_to_cpup (&td->hwBE); - tdCBP = le32_to_cpup (&td->hwCBP); - - - if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && - ((td->index == 0) || (td->index == urb_priv->length - 1)))) { - if (tdBE != 0) { - if (td->hwCBP == 0) - urb->actual_length += tdBE - (uint32_t)td->data_dma + 1; - else - urb->actual_length += tdCBP - (uint32_t)td->data_dma; - } - - } - -// debug("td->td_dma=%x, urb->actual_length=%d\n", td->td_dma, urb->actual_length); -} - -/*-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -ohci_td_t * dl_reverse_done_list (ohci_t * ohci) -{ - u32 td_list_hc; - ohci_td_t * td_rev = NULL; - ohci_td_t * td_list = NULL; - urb_priv_t * urb_priv = NULL; - uint32_t value; - u32 td_list_hc2; - int timeout = 1000000; //1 second -// unsigned long flags; -// Here need to process across the frame tds - td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; - td_list_hc2 = readl(&ohci->regs->donehead); -// debug("ohci->hcca->done_head = %x ohci->hcca=%x ohci=%x ohci->regs->donehead=%x\n", td_list_hc, ohci->hcca, ohci, td_list_hc2); - - td_list = dma_to_td (ohci, (void *)td_list_hc); - urb_priv = (urb_priv_t *) td_list->urb->hcpriv; - - while(/*(td_list_hc2!=0) || */(td_list->index < urb_priv->length-1) && (timeout>0)) { // wait another update for donehead - // To handle 1. ohci->hcca->donehead !=0 and regs->donehead!=0 - // 2. ohci->hcca->donehead !=0 and regs->donehead ==0 but regs-->donehead will be filled - - ohci->hcca->done_head = 0; - - value = readl(&ohci->regs->intrstatus); - value &= readl(&ohci->regs->intrenable); - - // We need to clear that the bit, otherwise We will not get next return. - if(value & OHCI_INTR_WDH) { - writel(value, &ohci->regs->intrstatus); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -// debug("OHCI_INTR_WDH cleared intrstatus=%x value=%x \n", readl(&ohci->regs->intrstatus), value); - } - while(timeout>0) { // wait for next DONEHEAD_WRITEBACK - value = readl(&ohci->regs->intrstatus); - if(!(value & OHCI_INTR_WDH)) { - udelay(1); - timeout--; - continue; - } else { - break; - } - } - - td_list_hc2 = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; - // merge td_list_hc the tail of td_list_hc2 - - if(td_list_hc2!=0) { - - while (td_list_hc2) { - td_list = dma_to_td (ohci, (void *)td_list_hc2); - td_list_hc2 = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; - } - - td_list->hwNextTD = td_list_hc; - - td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; - - td_list = dma_to_td (ohci, (void *)td_list_hc); - } else { - printf("."); - } - - } - - ohci->hcca->done_head = 0; - - value = readl(&ohci->regs->intrstatus); -// debug("OHCI_INTR_WDH value=%x \n", value); - value &= readl(&ohci->regs->intrenable); - -// We need to clear that the bit, otherwise We will not get next return. -// if(value & OHCI_INTR_WDH) { - writel(value, &ohci->regs->intrstatus); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ -// debug("OHCI_INTR_WDH cleared intrstatus=%x value=%x \n", readl(&ohci->regs->intrstatus), value); -// } - -#if 0 - if (value & OHCI_INTR_SO) { - debug("USB Schedule overrun"); - writel (OHCI_INTR_SO, &ohci->regs->intrenable); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ - } -#endif - - - while (td_list_hc) { -// debug("td_list_hc = %x\n", td_list_hc); - td_list = dma_to_td (ohci, (void *)td_list_hc); - - if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { - urb_priv = (urb_priv_t *) td_list->urb->hcpriv; - debug(" USB-error/status: %x : %x\n", - TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list); - if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) { - if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { - td_list->ed->hwHeadP = - (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | - (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); - urb_priv->td_cnt += urb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); - } - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; - } - return td_list; -} -/*-------------------------------------------------------------------------*/ -/* td done list */ - -void dl_done_list (ohci_t * ohci, ohci_td_t * td_list) -{ - ohci_td_t * td_list_next = NULL; - ed_t * ed; - // int cc = 0; - struct urb * urb; - urb_priv_t * urb_priv; - u32 tdINFO; //, edHeadP, edTailP; - -// unsigned long flags; - - while (td_list) { - td_list_next = td_list->next_dl_td; - - urb = td_list->urb; - urb_priv = urb->hcpriv; - tdINFO = le32_to_cpup (&td_list->hwINFO); - - ed = td_list->ed; - - dl_transfer_length(td_list); -#if 0 - /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (cc == TD_CC_STALL) - usb_endpoint_halt(urb->dev, - usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - - if (!(urb->transfer_flags & USB_DISABLE_SPD) - && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - if (++(urb_priv->td_cnt) == urb_priv->length) { - if ((ed->state & (ED_OPER | ED_UNLINK)) - && (urb_priv->state != URB_DEL)) { - urb->status = cc_to_error[cc]; - ohci_return_urb (ohci, urb); - } - else { - dl_del_urb (urb); - } - } - - if (ed->state != ED_NEW) { - edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0; - edTailP = le32_to_cpup (&ed->hwTailP); - - /* unlink eds if they are not busy */ - if ((edHeadP == edTailP) && (ed->state == ED_OPER)) - ep_unlink (ohci, ed); - } -#endif - - td_list = td_list_next; - } -} - -void ohci_wait_urb_done(struct urb *urb, int timeout) { // timeout usually ==10000 --> 10milisecond - //here need to according the urb or ed type judge the BLF and CLF, We may need one time out in it - // Or need to check intrstatus and see if the hcca->done_head has been filled. - // We need to clear that the bit, otherwise We will get next return. - uint32_t pipe = urb->pipe; - uint32_t value; - usbdev_t *usb_dev = urb->dev; - ohci_t *ohci = &_ohci_x[usb_dev->controller]; - uint32_t type; - while(timeout>0) { -#if 1 - value = readl(&ohci->regs->intrstatus); - if(!(value & OHCI_INTR_WDH)) { - udelay(1); - timeout--; - continue; - } else { - break; - } -#endif - } -#if 1 - while (timeout>0) { - type = usb_pipetype (pipe); - if(type ==PIPE_BULK) { - if( (readl(&ohci->regs->cmdstatus) & OHCI_BLF) == 0) break; - } else if(type == PIPE_CONTROL) { - if( (readl(&ohci->regs->cmdstatus) & OHCI_CLF) == 0) break; - } - udelay(1); // - timeout--; - } -#endif - - -} -void ohci_urb_complete(struct urb *urb) { - - ohci_t *ohci = &_ohci_x[urb->dev->controller]; - // it will clear the done list. and urb's actual_length is updated - dl_done_list (ohci, dl_reverse_done_list (ohci)); - -#if DEBUG_USB==1 - urb_print (urb, "RET", usb_pipein (urb->pipe)); -#endif - - urb_free_priv(ohci, urb->hcpriv); // free the priv and td list - -} -/*-------------------------------------------------------------------*/ -// it will 1. call usb_bulk_msg_x -// 2. call dl_list and find the data return -int ohci_bulk_transfer( uchar devnum, uchar ep, unsigned int data_len, uchar *data) { - int actual_length; - uint32_t t = devnum; - uint32_t pipe = ((ep&0x80)? 0x80:0)|(t<<8)|(3<<30); - t = ep; - pipe |=(t&0xf)<<15; - - usb_bulk_msg_x(&usb_device[devnum], pipe, data, data_len, &actual_length, 10000, ohci_urb_complete); - - return actual_length; - - -} -// it will 1. Call usb_control_msg_x -// 2. call dl_done_list to get the data returned ----> should be packed in one usb_complete_t function -// and assigned that to urb - -int ohci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short -wLength, void *data){ - - uint32_t t = devnum; - uint32_t pipe = ((request_type&0x80)? 0x80:0)|(t<<8)|(2<<30); - return usb_control_msg_x(&usb_device[devnum], pipe, request, request_type, wValue, wIndex, data, wLength, 10000, ohci_urb_complete); - -} - -int ohc_reset(uchar controller) -{ - - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - debug("Resetting OHCI\n"); - ohci_regs = (ohci_regs_t *)hc_base[controller]; - ohci_t *ohci = &_ohci_x[controller]; - -#ifndef __hppa__ - /* PA-RISC doesn't have SMM, but PDC might leave IR set */ - if (readl (&ohci_regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ - writel (OHCI_OCR, &ohci_regs->cmdstatus); /* request ownership */ - debug("USB HC TakeOver from SMM"); - while (readl (&ohci_regs->control) & OHCI_CTRL_IR) { - mdelay (10); - if (--smm_timeout == 0) { - printf("USB HC TakeOver failed!"); - return -1; - } - } - } -#endif - - debug("USB HC reset_hc usb-%08x: ctrl = 0x%x ;", - hc_base[controller], - readl (&ohci_regs->control)); - - /* Reset USB (needed by some controllers) */ - writel (0, &ohci_regs->control); - - /* Force a state change from USBRESET to USBOPERATIONAL for ALi */ - (void) readl (&ohci_regs->control); /* PCI posting */ - writel (ohci->hc_control = OHCI_USB_OPER, &ohci_regs->control); - - /* HC Reset requires max 10 ms delay */ - writel (OHCI_HCR, &ohci_regs->cmdstatus); - while ((readl (&ohci_regs->cmdstatus) & OHCI_HCR) != 0) { - if (--timeout == 0) { - printf("USB HC reset timed out!"); - return -1; - } - udelay (1); - } - return 0; -} - - -int ohc_start(uchar controller) { - // unsigned short tmp; - u32 mask; - unsigned int fminterval; - int delaytime; - ohci_regs = (ohci_regs_t *)hc_base[controller]; - ohci_t *ohci = &_ohci_x[controller]; - - debug("Starting OHCI\n"); - - writel (0, &ohci_regs->ed_controlhead); - writel (0, &ohci_regs->ed_bulkhead); - - writel ((uint32_t)ohci->hcca_dma, &ohci_regs->hcca); /* a reset clears this */ //3 - - fminterval = 0x2edf; //6 - writel ((fminterval * 9) / 10, &ohci_regs->periodicstart); // Don't worry, we can disable periodic in contol or let the ED list null - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci_regs->fminterval); - writel (0x628, &ohci_regs->lsthresh); - - /* start controller operations */ - - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - writel (ohci->hc_control, &ohci_regs->control); // PIE and IE is disabled - // DO we need to enable that but leave all ISO ED and INT ED list null??? - - mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; - writel (mask, &ohci->regs->intrenable); - writel (mask, &ohci->regs->intrstatus); - - /* required for AMD-756 and some Mac platforms */ - writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); - - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ - - // POTPGT delay is bits 24-31, in 2 ms units. - delaytime = ((roothub_a (ohci) >> 23) & 0x1fe)*5/2; // for apacer 256 usb 2.0 + NEC 2.0 chip -// delaytime = ((roothub_a (ohci) >> 23) & 0x1fe); - - mdelay (delaytime); - -// printf("delaytime: %d\n", delaytime); - - return(0); -} - - -int ohc_init(struct pci_device *dev) -{ - uint16_t word; - uint32_t dword; - ohci_t *ohci; - ed_t * ed; - int i,j, NDP; - int size; - - pci_read_config_dword(dev, 0x10, &dword); // it will be 4k range - hc_base[num_controllers] = (uint32_t)phys_to_virt(dword); - ohci = &_ohci_x[num_controllers]; - debug("ohc_init num_controllers=%d ohci=%x\n", num_controllers, (uint32_t)ohci); - memset(ohci, 0, sizeof(ohci_t)); - ohci->regs = (ohci_regs_t *)hc_base[num_controllers]; - ohci_regs = ohci->regs; - - ohci->hcca = allot2(sizeof (struct ohci_hcca), 0xff); //1 - if (!ohci->hcca) { - printf("ohc_init: hcca allocated no MEM\n"); - return -ENOMEM; - } - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - ohci->hcca_dma = (void *)virt_to_phys(ohci->hcca); - - //init ed; - ohci->ed = allot2(sizeof(ed_t)*NUM_EDS,0xf); - if(ohci->ed==0) { - printf("ohci_init: ed allocate no MEM\n"); - } -// debug("ohci->ed = %x\n", ohci->ed); - for(i=0; ied[i]; - ed->dma = (void *)virt_to_phys(ed); -// debug("i=%d, ed dma = %x\n", i, (uint32_t)ed->dma); - ed->state = ED_NEW; - } - -// init urb and urb_priv - ohci->urb = (struct urb *)allot2(sizeof(struct urb),0xff); - if (!ohci->urb) { - printf("ohci_init: urb allocate failed"); - } - memset(ohci->urb, 0, sizeof(urb_t)); - - - /* allocate the private part of the URB */ - size = 4; - ohci->urb_priv = allot2 (sizeof (urb_priv_t) + size * sizeof (ohci_td_t *), 0xff); - if (ohci->urb_priv == 0) { - printf("ohci_init: urb_priv allocated no mem\n"); - } - memset (ohci->urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (ohci_td_t *)); - - // set master - pci_read_config_word(dev, 0x04, &word); - word |= 0x04; - pci_write_config_word(dev, 0x04, word); - - - DPRINTF("Found OHCI at %08x\n", hc_base[num_controllers]); - ohc_reset(num_controllers); - - /* Here should or move to ohc_start - 1. Init HCCA - 2. Init ED and TD ---> in submit_urb - 3. Assign HCCA to ohci_regs->hcca ---> in ohc_init - 4. Set Intr to ohci_regs->intrenable ---> disable that in ohc_init - 5. enable all queue in ohci_regs->control ---> in ep_link and it is called by submit_urb - 6. set peridicstart to 0.9 of frameinterval ---> ohc_start - */ - -// writel( 0, &ohci_regs->intrenable); // no interrupts! //4 -// writel( 0xffffffff, &ohci_regs->intrdisable); - - NDP = readl(&ohci->regs->roothub.a) & 0xff; - for(j=0;jregs->roothub.portstatus[j]); - } - - /* FIXME this is a second HC reset; why?? */ - writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ - mdelay (10); - - ohc_start(num_controllers); - - num_controllers++; - -#if DEBUG_USB==1 -// ohci_dump (ohci, 1); -#endif - -// debug("ohci->ed = %x\n", ohci->ed); - return(0); -} -int poll_o_root_hub(uint32_t port, uchar controller) -{ - uint32_t value; - int addr=0; - int i; - static uint32_t do_over=0; - uint8_t what; - ohci_t *ohci; - - value = readl(port); - - debug("poll_o_root_hub1 v=%08x port = %x, controller = %d\n", value, port, controller); - - if(value == 0xffffffff) return addr; // stupid port - - if((value & RH_PS_CSC) || do_over == port) { - debug("poll_o_root_hub2 v=%08x\t", value); - do_over=0; - if(value & RH_PS_CCS ) { // if port connected - debug("poll_o_root_hub21 v=%08x\t", value); - DPRINTF("Connection on port %04x\n", port); - - writel(value, port); - for(i=0; i<40; i++) { - udelay(10000+usec_offset); - value = readl(port); - if(value & RH_PS_CSC) { - writel(value, port); //Clear Change bit - i=0; - DPRINTF("BOUNCE!\n"); - } - } -// debug("poll_o_root_hub211 v=%08x\t", value); - - oport_wakeup(port); -// DPRINTF("Wakup %04x\n", port); - -// debug("poll_o_root_hub212 v=%08x\t", readl(port)); - oport_reset(port); -// debug("poll_o_root_hub213 v=%08x\t", readl(port)); - mdelay(10); - oport_enable(port); -// debug("poll_o_root_hub214 v=%08x\t", readl(port)); - - if(!(value & RH_PS_CCS)) { - DPRINTF("Device went away!\n"); - return(-1); - } - - addr = configure_device( port, controller, value & RH_PS_LSDA); - -#if DEBUG_USB==1 - // some one clear enable bit??? why??? It costs me one week to find it out. - ohci = &_ohci_x[controller]; - ohci_dump (ohci, 1); -#endif - -#if 1 -// usb_control_msg(addr, 0x21, 0xff, 0, 0, 0, NULL);// reset device -// mdelay(10); - usb_control_msg(addr, 0xa1, 0xfe, 0, 0, 1, &what); // get MAX L // get MAX LUN -#endif - -// debug("poll_o_root_hub215 v=%08x addr = %d\n", readl(port), addr); - - if(addr<0) { - oport_disable(port); - udelay(20000); -// oport_reset(port); - oport_reset_long(port); - oport_suspend(port); - do_over=port; - ohc_clear_stat(controller); - - } - } else { -// debug("poll_o_root_hub22 v=%08x\t", readl(port)); - oport_suspend(port); - oport_disable(port); - DPRINTF("Port %04x disconnected\n", port); - // wave hands, deconfigure devices on this port! - } - } - - return(addr); -} - - - - -#endif diff --git a/src/filo/usb/ohci.h b/src/filo/usb/ohci.h deleted file mode 100644 index 0c9c6ad5..00000000 --- a/src/filo/usb/ohci.h +++ /dev/null @@ -1,316 +0,0 @@ -#ifdef USB_DISK - -#ifndef _OHCI_H -#define _OHCI_H - -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -// for OHCI - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -struct ed { - u32 hwINFO; - u32 hwTailP; - u32 hwHeadP; - u32 hwNextED; - - struct ed * ed_prev; - u8 int_period; // No use just for aligned - u8 int_branch; // No use just for aligned - u8 int_load; // No uae just for aligned - u8 int_interval; // No use just for aligned - u8 state; - u8 type; - u16 last_iso; // no use just for aligned - struct ed * ed_rm_list; // No use just for aligned - - void * dma; - - u32 unused[3]; -}; -// __attribute((aligned(16))); -typedef struct ed ed_t; - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -struct ohci_td { - u32 hwINFO; - u32 hwCBP; /* Current Buffer Pointer */ - u32 hwNextTD; /* Next TD Pointer */ - u32 hwBE; /* Memory Buffer End Pointer */ - u16 hwPSW[MAXPSW]; - u8 unused; - u8 index; - struct ed * ed; - struct ohci_td * next_dl_td; - struct urb * urb; //defined in usb.h - void * td_dma; - void * data_dma; - u32 unused2[2]; -}; -//__attribute((aligned(32))); /* normally 16, iso needs 32 */ -typedef struct ohci_td ohci_td_t; - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - u32 int_table[NUM_INTS]; /* Interrupt ED table */ - u16 frame_no; /* current frame number */ - u16 pad1; /* set to 0 on each frame_no change */ - u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute((aligned(256))); - - -#define MAX_ROOT_PORTS 15 - -struct ohci_regs { - /* control and status registers */ - u32 revision; - u32 control; - u32 cmdstatus; - u32 intrstatus; - u32 intrenable; - u32 intrdisable; - /* memory pointers */ - u32 hcca; - u32 ed_periodcurrent; - u32 ed_controlhead; - u32 ed_controlcurrent; - u32 ed_bulkhead; - u32 ed_bulkcurrent; - u32 donehead; - /* frame counters */ - u32 fminterval; - u32 fmremaining; - u32 fmnumber; - u32 periodicstart; - u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - u32 a; - u32 b; - u32 status; - u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute((aligned(32))); -typedef struct ohci_regs ohci_regs_t; - - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) -//| OHCI_CTRL_IE | OHCI_CTRL_PLE - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -typedef struct -{ - ed_t * ed; - u16 length; // number of tds associated with this request - u16 td_cnt; // number of tds already serviced - int state; -#if 0 - wait_queue_head_t * wait; -#endif - ohci_td_t * td[0]; // list pointer to all corresponding TDs associated with this request - -} urb_priv_t; - -#define NUM_EDS 32 /* num of preallocated endpoint descriptors */ - -typedef struct ohci { - struct ohci_hcca *hcca; /* hcca */ - void * hcca_dma; - - ohci_regs_t * regs; /* OHCI controller's memory */ - - ed_t * ed_bulktail; /* last endpoint of bulk list */ - ed_t * ed_controltail; /* last endpoint of control list */ - - int intrstatus; - u32 hc_control; /* copy of the hc control reg */ - - uint32_t ed_cnt; - ed_t *ed; // Allocate that from ed_buffer in ohc_init - usbdev_t *dev[NUM_EDS]; - urb_t *urb; // one ohci one urb - urb_priv_t *urb_priv; - struct usb_ctrlrequest *dr; -} ohci_t; - - -extern ohci_t _ohci_x[MAX_CONTROLLERS]; - -#define usb_to_ohci(usb_dev) (&_ohci_x[(usb_dev)->controller]) - -extern ohci_regs_t *ohci_regs; - -void clear_oport_stat(uint32_t port); -int ohc_init(struct pci_device *dev); -int poll_o_root_hub(uint32_t port, uchar controller); - -int ohci_bulk_transfer( uchar devnum, uchar ep, unsigned int data_len, uchar *data); -int ohci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short - wLength, void *data); -void ohci_wait_urb_done(struct urb *urb, int timeout); - -void ohci_init(void); -int ohc_init(struct pci_device *dev); -int ohci_submit_urb (struct urb * urb); -#endif - -#endif diff --git a/src/filo/usb/scsi.h b/src/filo/usb/scsi.h deleted file mode 100644 index 7c119a48..00000000 --- a/src/filo/usb/scsi.h +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * This header file contains public constants and structures used by - * the scsi code for linux. - */ - -#ifndef _SCSI_SCSI_H -#define _SCSI_SCSI_H 1 - -//#include - -/* - * SCSI opcodes - */ - -#define TEST_UNIT_READY 0x00 -#define REZERO_UNIT 0x01 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define READ_BLOCK_LIMITS 0x05 -#define REASSIGN_BLOCKS 0x07 -#define READ_6 0x08 -#define WRITE_6 0x0a -#define SEEK_6 0x0b -#define READ_REVERSE 0x0f -#define WRITE_FILEMARKS 0x10 -#define SPACE 0x11 -#define INQUIRY 0x12 -#define RECOVER_BUFFERED_DATA 0x14 -#define MODE_SELECT 0x15 -#define RESERVE 0x16 -#define RELEASE 0x17 -#define COPY 0x18 -#define ERASE 0x19 -#define MODE_SENSE 0x1a -#define START_STOP 0x1b -#define RECEIVE_DIAGNOSTIC 0x1c -#define SEND_DIAGNOSTIC 0x1d -#define ALLOW_MEDIUM_REMOVAL 0x1e - -#define SET_WINDOW 0x24 -#define READ_CAPACITY 0x25 -#define READ_10 0x28 -#define WRITE_10 0x2a -#define SEEK_10 0x2b -#define WRITE_VERIFY 0x2e -#define VERIFY 0x2f -#define SEARCH_HIGH 0x30 -#define SEARCH_EQUAL 0x31 -#define SEARCH_LOW 0x32 -#define SET_LIMITS 0x33 -#define PRE_FETCH 0x34 -#define READ_POSITION 0x34 -#define SYNCHRONIZE_CACHE 0x35 -#define LOCK_UNLOCK_CACHE 0x36 -#define READ_DEFECT_DATA 0x37 -#define MEDIUM_SCAN 0x38 -#define COMPARE 0x39 -#define COPY_VERIFY 0x3a -#define WRITE_BUFFER 0x3b -#define READ_BUFFER 0x3c -#define UPDATE_BLOCK 0x3d -#define READ_LONG 0x3e -#define WRITE_LONG 0x3f -#define CHANGE_DEFINITION 0x40 -#define WRITE_SAME 0x41 -#define READ_TOC 0x43 -#define LOG_SELECT 0x4c -#define LOG_SENSE 0x4d -#define MODE_SELECT_10 0x55 -#define RESERVE_10 0x56 -#define RELEASE_10 0x57 -#define MODE_SENSE_10 0x5a -#define PERSISTENT_RESERVE_IN 0x5e -#define PERSISTENT_RESERVE_OUT 0x5f -#define MOVE_MEDIUM 0xa5 -#define READ_12 0xa8 -#define WRITE_12 0xaa -#define WRITE_VERIFY_12 0xae -#define SEARCH_HIGH_12 0xb0 -#define SEARCH_EQUAL_12 0xb1 -#define SEARCH_LOW_12 0xb2 -#define READ_ELEMENT_STATUS 0xb8 -#define SEND_VOLUME_TAG 0xb6 -#define WRITE_LONG_2 0xea - -/* - * Status codes - */ - -#define GOOD 0x00 -#define CHECK_CONDITION 0x01 -#define CONDITION_GOOD 0x02 -#define BUSY 0x04 -#define INTERMEDIATE_GOOD 0x08 -#define INTERMEDIATE_C_GOOD 0x0a -#define RESERVATION_CONFLICT 0x0c -#define COMMAND_TERMINATED 0x11 -#define QUEUE_FULL 0x14 - -#define STATUS_MASK 0x3e - -/* - * SENSE KEYS - */ - -#define NO_SENSE 0x00 -#define RECOVERED_ERROR 0x01 -#define NOT_READY 0x02 -#define MEDIUM_ERROR 0x03 -#define HARDWARE_ERROR 0x04 -#define ILLEGAL_REQUEST 0x05 -#define UNIT_ATTENTION 0x06 -#define DATA_PROTECT 0x07 -#define BLANK_CHECK 0x08 -#define COPY_ABORTED 0x0a -#define ABORTED_COMMAND 0x0b -#define VOLUME_OVERFLOW 0x0d -#define MISCOMPARE 0x0e - - -/* - * DEVICE TYPES - */ - -#define TYPE_DISK 0x00 -#define TYPE_TAPE 0x01 -#define TYPE_PROCESSOR 0x03 /* HP scanners use this */ -#define TYPE_WORM 0x04 /* Treated as ROM by our system */ -#define TYPE_ROM 0x05 -#define TYPE_SCANNER 0x06 -#define TYPE_MOD 0x07 /* Magneto-optical disk - - * - treated as TYPE_DISK */ -#define TYPE_MEDIUM_CHANGER 0x08 -#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ -#define TYPE_NO_LUN 0x7f - -/* - * standard mode-select header prepended to all mode-select commands - * - * moved here from cdrom.h -- kraxel - */ - -struct ccs_modesel_head - { - unsigned char _r1; /* reserved. */ - unsigned char medium; /* device-specific medium type. */ - unsigned char _r2; /* reserved. */ - unsigned char block_desc_length; /* block descriptor length. */ - unsigned char density; /* device-specific density code. */ - unsigned char number_blocks_hi; /* number of blocks in this block - desc. */ - unsigned char number_blocks_med; - unsigned char number_blocks_lo; - unsigned char _r3; - unsigned char block_length_hi; /* block length for blocks in this - desc. */ - unsigned char block_length_med; - unsigned char block_length_lo; - }; - -/* - * MESSAGE CODES - */ - -#define COMMAND_COMPLETE 0x00 -#define EXTENDED_MESSAGE 0x01 -#define EXTENDED_MODIFY_DATA_POINTER 0x00 -#define EXTENDED_SDTR 0x01 -#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */ -#define EXTENDED_WDTR 0x03 -#define SAVE_POINTERS 0x02 -#define RESTORE_POINTERS 0x03 -#define DISCONNECT 0x04 -#define INITIATOR_ERROR 0x05 -#define ABORT 0x06 -#define MESSAGE_REJECT 0x07 -#define NOP 0x08 -#define MSG_PARITY_ERROR 0x09 -#define LINKED_CMD_COMPLETE 0x0a -#define LINKED_FLG_CMD_COMPLETE 0x0b -#define BUS_DEVICE_RESET 0x0c - -#define INITIATE_RECOVERY 0x0f /* SCSI-II only */ -#define RELEASE_RECOVERY 0x10 /* SCSI-II only */ - -#define SIMPLE_QUEUE_TAG 0x20 -#define HEAD_OF_QUEUE_TAG 0x21 -#define ORDERED_QUEUE_TAG 0x22 - -/* - * Here are some scsi specific ioctl commands which are sometimes useful. - */ -/* These are a few other constants only used by scsi devices. */ - -#define SCSI_IOCTL_GET_IDLUN 0x5382 - -/* Used to turn on and off tagged queuing for scsi devices. */ - -#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 -#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 - -/* Used to obtain the host number of a device. */ -#define SCSI_IOCTL_PROBE_HOST 0x5385 - -/* Used to get the bus number for a device. */ -#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 - -#endif /* scsi/scsi.h */ diff --git a/src/filo/usb/scsi_cmds.c b/src/filo/usb/scsi_cmds.c deleted file mode 100644 index bd7b7fa8..00000000 --- a/src/filo/usb/scsi_cmds.c +++ /dev/null @@ -1,512 +0,0 @@ -#ifdef USB_DISK -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - - -#include "scsi.h" - - -#include "usb_scsi_low.h" - -#ifndef NULL -#define NULL (void *) 0x0 -#endif - -#include "scsi_cmds.h" - -devhandle sgh; - -typedef struct sense_data { - uchar code; - - uchar sense_key:4; - uchar res1:4; - - uchar additional_code; - uchar qualifier; - - uchar res2[3]; - - uchar length; -} __attribute__ ((packed)) sense_data_t; - -typedef struct fixed_sense_data { - uchar code:7; - uchar valid:1; - - uchar obs1; - - uchar sense_key:4; - uchar res1:1; - uchar ili:1; - uchar eom:1; - uchar mark:1; - - unsigned int info; - - uchar add_len; -} __attribute__ ((packed)) fixed_sense_data_t; - -typedef struct additional_fixed_data { - unsigned int info; - - uchar code; - uchar qualifier; - uchar fru; - - uchar specific[3]; -} __attribute__ ((packed)) additional_fixed_data_t; - - -void PrintSense(uchar *sense, int len) -{ - int i; - - DPRINTF( "sense data "); - for(i=0;i=0x72) { - sense_data_t *sd = (sense_data_t *) sense; - uchar *pos = sense+sizeof(sense_data_t); - uchar remaining = sd->length; - int dlen; - - DPRINTF("code = %02x, key = %1x, additional = %02x, qual = %02x\n", sd->code, sd->sense_key, sd->additional_code, sd->qualifier); - - while(remaining) { - DPRINTF("type = %02x", pos[0]); - dlen = pos[1]; - pos+=2; - remaining -=2; - - for(i=0; iadd_len; - additional_fixed_data_t *afd; - - - DPRINTF("code = %02x key = %1x\n", fd->code, fd->sense_key); - if(fd->mark) { - DPRINTF("filemark "); - } - - if(fd->eom) { - DPRINTF(" End Of Media "); - } - - if(fd->ili) { - DPRINTF("Illegal instruction"); - } - - DPRINTF("\n"); - - if(fd->valid) { - DPRINTF( "(valid) "); - } - - DPRINTF( "Info: %08x\n", ntohl(fd->info)); - - afd = (additional_fixed_data_t *) (sense + 8); - -// while(remaining) { - if(remaining) { - DPRINTF("command info = %08x\n", ntohl(afd->info)); - DPRINTF("code = %02x, qual = %02x, fru = %02x\n", afd->code, afd->qualifier, afd->fru); - DPRINTF("sense key data = %02x:%02x:%02x\n\n", afd->specific[2], afd->specific[1], afd->specific[0]); - - afd++; - remaining -= sizeof(additional_fixed_data_t); - } - } - -} - -typedef struct query_response { - uchar type:5; - uchar qualifier:3; - - uchar reserved1:7; - uchar removable:1; - - uchar version; - - uchar ResponseDataFormat:4; // should == 2 - uchar HiSup:1; // report luns cmd supported - uchar NormACA:1; - uchar obsolete:1; - uchar aerc:1; - - uchar AdditionalLength; // length of vendor specific data (beyond 96 bytes) - - uchar reserved2:7; - uchar sccs:1; // have raid controller - - uchar addr16:1; // - uchar obsolete2:2; - uchar MChnger:1; // media changer - uchar MultiP:1; // multi port - uchar vs:1; // ??? - uchar EncServ:1; // enclosure service - uchar BQue:1; // basic command queueing - - uchar vs2:1; - uchar CmdQue:1; // full command queueing - uchar obsolete4:1; - uchar linked:1; - uchar sync:1; - uchar wbus16:1; // - uchar obsolete3:1; - uchar RelAddr:1; // treletive addressing - - char vendor[8]; - char product[16]; - char revision[4]; - char vendor_data[20]; - - uchar ius:1; - uchar qas:1; - uchar clocking:2; // - uchar reserved3:4; - - unsigned short version_desc[8]; - - char reserved4[21]; -} query_response_t; - -typedef struct ReadBlockCMD { - uchar cmd; - - uchar reladdr:1; - uchar reserved:2; - uchar fua:1; // force unit access flush to media - uchar dpo:1; // direct page out, do not cache - uchar reserved2:3; - - unsigned int block_address; - uchar reserved3; - - unsigned short block_count; - - uchar control; -} __attribute__ ((packed)) ReadBlockCMD_t ; - -int ll_read_block(devhandle sgd, char *buffer, int blocknum, int count) -{ - int ret; - ReadBlockCMD_t rb; - char sensedat[32]; - - memset(&rb,0,sizeof(rb)); - rb.cmd = READ_10; - rb.block_address = htonl(blocknum); - rb.block_count = htons(count); - - ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_FROM_DEV, buffer, count * 512, sensedat, sizeof(sensedat)); - - if(ret<0) { - DPRINTF("ERROR: ll_read_block( %x, %x, %x, %x) = %d\n", sgd, buffer, blocknum, count, ret); - PrintSense(sensedat, 32); - } - - return(ret); - -} - -int ll_write_block(devhandle sgd, char *buffer, int blocknum, int count) -{ - int ret; - ReadBlockCMD_t rb; - char sensedat[32]; - - memset(&rb,0,sizeof(rb)); - rb.cmd = WRITE_10; - rb.block_address = htonl(blocknum); - rb.block_count = htons(count); - - ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_TO_DEV, buffer, count * 512, sensedat, sizeof(sensedat)); - - return(ret); -} - -typedef struct ReadLongCMD { - uchar cmd; - - uchar reladdr:1; - uchar correct:1; - uchar reserved:5; - - unsigned int block_address; - uchar reserved3; - - unsigned short length; - - uchar control; -} __attribute__ ((packed)) ReadLongCMD_t ; - -int ll_read_long(devhandle sgd, char *buffer, int blocknum, int size) -{ - int ret; - ReadLongCMD_t rb; - char sensedat[32]; - - memset(&rb,0,sizeof(rb)); - rb.cmd = READ_LONG; - rb.block_address = htonl(blocknum); - rb.length = htons(size); - - ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_FROM_DEV, buffer, size, sensedat, sizeof(sensedat)); - return(ret); -} - -unsigned char ReadCapacityCMD[10] = { READ_CAPACITY, 0, 0,0,0,0, 0,0,0, 0}; - -struct ReadCapacityResponse { - unsigned int block_address; - unsigned int block_length; -}; - -int get_capacity(devhandle sgd, unsigned long *block_count, unsigned int *blk_len) -{ - int ret; - struct ReadCapacityResponse response; - char sensedat[32]; - - ret = scsi_command(sgd, ReadCapacityCMD, sizeof(ReadCapacityCMD), SG_DXFER_FROM_DEV, (uint8_t *)&response, sizeof(response), sensedat, sizeof(sensedat) ); - if(ret<0) { - DPRINTF("ERROR:get capacity: %d\n", ret); - PrintSense(sensedat,32); - } - - - *block_count = ntohl(response.block_address) +1; - *blk_len = ntohl(response.block_length); - - return(ret); -} - -#define INQ_REP_LEN 96 -unsigned char InquiryCMD[6] = { INQUIRY, 0, 0, 0, INQ_REP_LEN, 0}; - -int query(devhandle sgd, query_response_t *qr) -{ - int ret; - char sensedat[32]; - - ret = scsi_command(sgd, InquiryCMD, sizeof(InquiryCMD), SG_DXFER_FROM_DEV, (uint8_t *)qr, sizeof(query_response_t), sensedat, sizeof(sensedat) ); - - if(ret<0){ - DPRINTF("query: IOCTL"); - } - - return(ret); -} - -typedef struct lun_list { - unsigned int list_length; - unsigned int reserved; - unsigned long long lun[16]; -} lun_list_t; - -#define REPORT_LUNS 0xa0 -unsigned char ReportLunsCMD[12] = { REPORT_LUNS, 0, 2, 0, 0, 0, 0, 0, 0, 128, 0, 0 }; - -int ReportLUNS(devhandle sgd, lun_list_t *list) -{ - int ret; - char sensedat[32]; - - memset (list, 0, sizeof(lun_list_t)); - ret = scsi_command(sgd, ReportLunsCMD, sizeof(ReportLunsCMD), SG_DXFER_FROM_DEV, (uint8_t *)list, sizeof(lun_list_t), sensedat, sizeof(sensedat) ); - - if(ret<0) { - DPRINTF("Report Luns: IOCTL"); - } - - list->list_length = ntohl(list->list_length); - - return(ret); -} - -typedef struct command_descriptor { - uchar opcode; - uchar reserved; - unsigned short service_action; - uchar reserved2; - - uchar action_valid:1; - uchar reserved3:7; - - unsigned short cdb_len; -} __attribute__ ((packed)) command_descriptor_t; - -typedef struct report_opcodes_result { - unsigned long length; - - command_descriptor_t command[256]; -} __attribute__ ((packed)) report_opcode_result_t; - - -#define REPORT_OPCODES 0xa3 - -typedef struct report_opcodes_cmd { - uchar cmd; - uchar reserved[5]; - unsigned int reply_len; - uchar reserved2; - uchar control; -} __attribute__ ((packed)) ReportOpcodesCMD_t; - -//ReportOpcodesCMD_t ReportOpcodesCMD = { cmd : REPORT_OPCODES, reply_len: htonl(sizeof(report_opcode_result_t)) }; - -int ReportOpCodes(devhandle sgd, report_opcode_result_t *list) -{ - int ret; - char sensedat[32]; - ReportOpcodesCMD_t ReportOpcodesCMD; - - memset (list, 0, sizeof(report_opcode_result_t)); - ReportOpcodesCMD.cmd = REPORT_OPCODES; - ReportOpcodesCMD.reply_len = htonl( sizeof(report_opcode_result_t)); - - ret = scsi_command(sgd, (uint8_t *)&ReportOpcodesCMD, sizeof(ReportOpcodesCMD_t), SG_DXFER_FROM_DEV, (uint8_t *)list, sizeof(report_opcode_result_t), sensedat, sizeof(sensedat) ); - - if(ret<0) { - DPRINTF("Report Luns: IOCTL"); - } - - list->length = ntohl(list->length); - - return(ret); -} - - -#define READ_ATTRIBUTE 0x8c -#define VOLUME_LIST 2 -#define PARTITION_LIST 3 - -typedef struct read_attribute_cmd { - uchar cmd; - - uchar action:5; - uchar res:3; - - uchar restricted[3]; - - uchar volume; - uchar res2; - uchar partition; - - ushort attribute; - unsigned int reply_len; - uchar res3; - uchar control; -} __attribute__ ((packed)) ReadAttributeCMD_t; - -int CheckVolumes(devhandle sgd) -{ - int ret; - uchar reply[4]; - uchar sensedat[32]; - ReadAttributeCMD_t cmd; - - memset(&cmd,0,sizeof(cmd)); - - cmd.cmd=READ_ATTRIBUTE; - cmd.action = VOLUME_LIST; - cmd.reply_len = htonl(4); - - ret = scsi_command(sgd, (uint8_t *)&cmd, sizeof(cmd), SG_DXFER_FROM_DEV, reply, sizeof(reply), sensedat, sizeof(sensedat) ); - if(ret<0) { - DPRINTF("Report Volumes: IOCTL"); - return(-1); - } - - if(! reply[0] && !reply[1]) - return(0); - - return(reply[3]); -} - -int CheckPartitions(devhandle sgd) -{ - int ret; - uchar reply[4]; - uchar sensedat[32]; - ReadAttributeCMD_t cmd; - - memset(&cmd,0,sizeof(cmd)); - - cmd.cmd=READ_ATTRIBUTE; - cmd.action = PARTITION_LIST; - cmd.reply_len = htonl(4); - - ret = scsi_command(sgd, (uint8_t *)&cmd, sizeof(cmd), SG_DXFER_FROM_DEV, reply, sizeof(reply), sensedat, sizeof(sensedat) ); - if(ret<0) { - DPRINTF("Report PARTITIONVolumes: IOCTL"); - return(-1); - } - - if(! reply[0] && !reply[1]) - return(0); - - return(reply[3]); -} - -int UnitReady(devhandle sgd) -{ - uchar cmd[6]; - uchar sensedat[32]; - int ret; - - memset(cmd,0,sizeof(cmd)); - - ret = scsi_command(sgd, &cmd, sizeof(cmd), SG_DXFER_FROM_DEV, NULL, 0, sensedat, sizeof(sensedat) ); - if(ret<0) { - DPRINTF("UnitReady :"); - return(0); - } - - return(1); -} - - -#endif diff --git a/src/filo/usb/scsi_cmds.h b/src/filo/usb/scsi_cmds.h deleted file mode 100644 index 1c64a3bf..00000000 --- a/src/filo/usb/scsi_cmds.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _SCSI_CMDS_H -#define _SCSI_CMDS_H - -#define devhandle uint8_t - -#define uchar uint8_t -#define ushort uint16_t - -void PrintSense(uchar *sense, int len); -int ll_read_block(devhandle sgd, char *buffer, int blocknum, int count); - -int get_capacity(devhandle sgd, unsigned long *block_count, unsigned int *blk_len); -int UnitReady(uchar sgd); -#endif diff --git a/src/filo/usb/uhci.c b/src/filo/usb/uhci.c deleted file mode 100644 index 4ce4b499..00000000 --- a/src/filo/usb/uhci.c +++ /dev/null @@ -1,1143 +0,0 @@ -#ifdef USB_DISK - -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - - -#include "usb.h" -#include "uhci.h" -#include "debug_x.h" - -#define ALLOCATE 1 - -extern int usec_offset; - -int wait_head( queue_head_t *head, int count) -{ - td_t *td; - - - while(!head->depth.terminate) { - td = MEM_ADDR(head->depth.link); - if(!td->active) - return(-1); // queue failed - - if(count) - if(! --count) - return(0); // still active - - udelay(500); // give it some time - } - - return(1); // success -} - -queue_head_t *free_qh; -queue_head_t _queue_heads[MAX_QUEUEHEAD]; -queue_head_t *queue_heads = _queue_heads; - -queue_head_t *new_queue_head(void) -{ - queue_head_t *qh; - - if(!free_qh) - return(NULL); - - qh = free_qh; - free_qh = MEM_ADDR(qh->bredth.link); - - memset(qh,0,sizeof(queue_head_t)); - qh->bredth.terminate = qh->depth.terminate=1; - - return(qh); -} - -void free_queue_head( queue_head_t *qh) -{ - - qh->bredth.link = LINK_ADDR(free_qh); - if(!free_qh) - qh->bredth.terminate=1; - - qh->depth.terminate=1; - free_qh = qh; -} - -void init_qh(void) -{ - int i; - - for(i=0; ilink.link); -// DPRINTF("new_td: free_td_list = %p\n", free_td_list); - - memset(td, 0, sizeof(td_t)); - td->link.terminate=1; - -// DPRINTF("new_td: returning %p\n", td); - return(td); -} - -td_t *find_last_td(td_t *td) -{ - td_t *last; - - last = td; - - while(!last->link.terminate) - last = MEM_ADDR(last->link.link); - - return(last); -} - -void free_td( td_t *td) -{ - td_t *last_td; - - last_td = find_last_td(td); - - last_td->link.link = LINK_ADDR(free_td_list); - if(!free_td_list) - last_td->link.terminate=1; - else - last_td->link.terminate=0; - - free_td_list = td; - -} - -link_pointer_t *queue_end( queue_head_t *queue) -{ - link_pointer_t *link; - - link = &(queue->depth); - - while(!link->terminate) - link = MEM_ADDR(link->link); - - return(link); -} - -void add_td( queue_head_t *head, td_t *td) -{ - link_pointer_t *link; - - link = queue_end(head); - - link->link = LINK_ADDR(td); - link->terminate=0; -} - -transaction_t transactions[MAX_TRANSACTIONS]; -transaction_t *free_transactions; - -void init_transactions(void) -{ - int i; - - memset(transactions, 0, sizeof(transactions)); - - for(i=0; itd_list ); - free_queue_head( my_current->qh ); - - last = my_current; - my_current = my_current->next; - } - - last->next = free_transactions; - free_transactions = trans; -} - -transaction_t *new_transaction(td_t *td) -{ - transaction_t *trans = free_transactions; - queue_head_t *qh; - - if(!trans) { - DPRINTF("new_transaction( td = %x) failed!\n", td); - return(NULL); - } - - free_transactions = trans->next; - - memset(trans, 0, sizeof(transaction_t)); - - if(td) { - qh = new_queue_head(); - if(!qh) { - free_transaction(trans); - return(NULL); - } - - trans->qh = qh; - trans->td_list = td; - qh->depth.link = LINK_ADDR(td); - qh->depth.terminate = 0; - qh->bredth.terminate=1; - } - - return(trans); -} - -transaction_t *add_transaction( transaction_t *trans, td_t *td) -{ - transaction_t *t1; - - - t1 = new_transaction(td); - if(!t1) - return(NULL); - - trans->next = t1; - trans->qh->bredth.terminate=0; - trans->qh->bredth.link = LINK_ADDR(t1->qh); - trans->qh->bredth.queue=1; - - return(trans); -} - -link_pointer_t *frame_list[MAX_CONTROLLERS]; -#if 0 -uchar fl_buffer[MAX_CONTROLLERS][8192]; -#endif - -void init_framelist(uchar dev) -{ - - int i; -#if 0 - DPRINTF("raw frame_list is at %x\n", fl_buffer[dev]); - frame_list[dev] = (link_pointer_t *) ((bus_to_virt)(((unsigned int)virt_to_bus(fl_buffer[dev]) & ~0xfff) + 0x1000)); -#else - frame_list[dev] = (link_pointer_t *) allot2(sizeof(link_pointer_t)*1024, 0xfff); // 4K alignment - if(frame_list[dev]==0) { - printf("init_framelist: no mem\n"); - } -#endif - memset(frame_list[dev], 0, 1024 * sizeof(link_pointer_t)); - - - DPRINTF("frame_list is at %x\n", frame_list[dev]); - - for(i=0;i<1024;i++) - frame_list[dev][i].terminate=1; - -} - - -extern int num_controllers; - -extern uint32_t hc_base[MAX_CONTROLLERS]; -extern uint8_t hc_type[MAX_CONTROLLERS]; - -void uhc_clear_stat() -{ - unsigned short value; - - value = inw(USBSTS(0)); - outw(value, USBSTS(0)); -} - -void clear_uport_stat(unsigned short port) -{ - unsigned short value; - - value = inw(port); - outw(value, port); -} - -void uport_suspend( unsigned short port) -{ - unsigned short value; - - value = inw(port); - value |= 0x1000; - outw( value, port); - -} - -void uport_wakeup( unsigned short port) -{ - unsigned short value; - - value = inw(port); - value &= ~0x1000; - outw( value, port); - -} - -#if 0 -void uport_resume( unsigned short port) -{ - unsigned short value; - - value = inw(port); - value |= 0x40; - outw(value, port); - udelay(20000+usec_offset); - value &= ~0x40; - outw(value, port); - - do { - value = inw(port); - } while(value & 0x40); -} - -#endif -void uport_enable( unsigned short port) -{ - unsigned short value; - - value = inw(port); - value |= 0x04; - outw( value, port); - - do { - value = inw(port); - } while( !(value & 0x04) && (value & 0x01)); - -} - - -void uport_disable( unsigned short port) -{ - unsigned short value; - - value = inw(port); - value &= ~0x04; - outw( value, port); -} - -void uport_reset(unsigned short port) -{ - unsigned short value; - int i; - - value = inw(port); - value |= 0x200; - - outw( value, port); - - for(i=0;i<5;i++) - udelay(10000+usec_offset); - - value &= ~0x200; - outw( value, port); - -// DPRINTF("Port %04x reset\n", port); -} - -void uport_reset_long(unsigned short port) -{ - unsigned short value; - int i; - - value = inw(port); - value |= 0x200; - outw( value, port); - - for(i=0; i<20; i++) - udelay(10000); - - value &= ~0x200; - outw( value, port); - -// DPRINTF("Port %04x reset\n", port); -} - -void uhc_reset(uchar controller) -{ - DPRINTF("Resetting UHCI\n"); - outw(0x04, USBCMD(controller)); - udelay(20000); - outw(0, USBCMD(controller)); -} -#if 0 -int uhc_stop(uchar dev) -{ - unsigned short tmp; - - tmp = inw(USBCMD(dev)); - tmp &= ~USBCMDRUN; - outw( tmp, USBCMD(dev)); - - while(! (inw(USBSTS(dev)) & USBSTSHALTED) ); - outw( USBSTSHALTED, USBSTS(dev)); // clear the status - - return(0); -} - -#endif - -int uhc_start(uchar dev) { - unsigned short tmp; - - DPRINTF("Starting UHCI\n"); - - tmp = inw(USBCMD(dev)); - tmp |= USBCMDRUN; - -// tmp |= USBCMD_DEBUG; - outw( tmp, USBCMD(dev)); - - return(0); -} - -int uhc_init(struct pci_device *dev) -{ - int16_t word; - - - pci_read_config_word(dev, 0x20, &word); - hc_base[num_controllers] = word; - hc_base[num_controllers] &= ~1; - - DPRINTF("Found UHCI at %04x\n", hc_base[num_controllers]); - uhc_reset(num_controllers); - - // set master - pci_read_config_word(dev, 0x04, &word); - word |= 0x04; - pci_write_config_word(dev, 0x04, word); - -#if 0 - if( ((unsigned int) virt_to_bus(frame_list[num_controllers])) != ( ( (unsigned int)virt_to_bus(frame_list[num_controllers])) & ~0x7ff) ) { - DPRINTF("UHCI: grave error, misaligned framelist (%x)\n", frame_list[num_controllers]); - return(-1); - } -#endif - - DPRINTF("uhc_init setting framelist to: %08x\n", (unsigned int) virt_to_bus( (frame_list[num_controllers]) )); - outl( (unsigned int) virt_to_bus(frame_list[num_controllers]), FLBASE(num_controllers)); - outw( 0, FRNUM(num_controllers)); - outw( 0, USBINTR(num_controllers)); // no interrupts! - - outw(0x1000, PORTSC1(num_controllers)); - outw(0x1000, PORTSC2(num_controllers)); - - uhc_start(num_controllers); - - dump_uhci(hc_base[num_controllers]); - - num_controllers++; - return(0); -} - -queue_head_t *sched_queue[MAX_CONTROLLERS]; -queue_head_t *term_qh[MAX_CONTROLLERS]; -//td_t *dummy_td[MAX_CONTROLLERS]; -td_t *loop_td[MAX_CONTROLLERS]; - -void init_sched(uchar dev) -{ - int i; - -// dummy_td[dev] = new_td(); - loop_td[dev] = new_td(); - term_qh[dev] = new_queue_head(); - - sched_queue[dev] = new_queue_head(); - sched_queue[dev]->bredth.terminate=0; - sched_queue[dev]->bredth.queue=1; - sched_queue[dev]->bredth.link=LINK_ADDR(term_qh[dev]); - sched_queue[dev]->depth.terminate=1; - - term_qh[dev]->bredth.terminate=1; - term_qh[dev]->depth.link = LINK_ADDR(loop_td[dev]); - term_qh[dev]->depth.terminate=0; - -// dummy_td->link.link = LINK_ADDR(sched_queue); -// dummy_td->link.queue = 1; -// dummy_td->link.depth=1; -// dummy_td->link.terminate=0; -// dummy_td->packet_type = IN_TOKEN; -// dummy_td->max_transfer = 0x7; -// dummy_td->isochronous=1; -// dummy_td->active=1; -// dummy_td->device_addr = 0x7f; -// dummy_td->endpoint=0x01; -// dummy_td->buffer = virt_to_bus(&dummy_td->data[2]); -// dummy_td->retrys=3; - -//dump_hex( (uchar *) dummy_td, sizeof(td_t), "dummy_td "); - - loop_td[dev]->link.link = LINK_ADDR(loop_td[dev]); - loop_td[dev]->link.terminate=0; - loop_td[dev]->link.queue=0; - loop_td[dev]->packet_type = IN_TOKEN; - loop_td[dev]->max_transfer=7; - loop_td[dev]->retrys=0; - loop_td[dev]->device_addr=0x7f; - - for(i=0; i< 1024; i++) { - frame_list[dev][i].link = LINK_ADDR(sched_queue[dev]); - frame_list[dev][i].queue=1; - frame_list[dev][i].terminate=0; -// frame_list[dev][i].terminate=1; - } - - dump_link( frame_list[dev], "frame_list_link: "); -// DPRINTF("dummy_td = %x\n", dummy_td[dev]); - -// dump_frame_list("sched:"); - -} - -void uhci_init(void) -{ - int i; - - init_td(); - init_qh(); - init_transactions(); - - for(i=0;idepth.terminate) - return(1); - - while(strikes--) { - if(qh->depth.terminate) - return(1); - - td = MEM_ADDR(qh->depth.link); - - if(td->active) - return(0); - - udelay(1000); - -// if(!td->active) -// return(1); - } - - return(1); -} - -int wait_queue_complete( queue_head_t *qh) -{ - int ret; - int spins=1000; - - while( --spins && !(ret = poll_queue_head(qh))) { - udelay(1500); -// if(!(spins%30)) -// DPRINTF("wait_queue_complete: spin\n"); - } -// DPRINTF("wait_queue_complete: returning %d\n", ret); - - if(!spins) - return(-1); - - return(ret); -} - -#define BULK_DEPTH 1 - -transaction_t *_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data) -{ - uchar dt; - transaction_t *trans; - td_t *td, *cur, *last; - int remaining = len; - uchar *pos = data; - int max; - uchar type = OUT_TOKEN; - int packet_length; - - - if(ep & 0x80) - type = IN_TOKEN; - - ep &= 0x7f; - - td = cur = last = NULL; - dt = usb_device[devnum].toggle[ep]; - max = usb_device[devnum].max_packet[ep]; - - while(remaining) { - cur = new_td(); - cur->packet_type = type; - cur->data_toggle = dt; - cur->endpoint = ep&0x7f; - cur->device_addr = devnum; - cur->detect_short=1; - cur->active=1; - dt = dt^0x01; - - if(!td){ - td = cur; - } - - if(last) { - last->link.terminate=0; - last->link.link = LINK_ADDR(cur); - } - - cur->buffer = (void *) virt_to_bus(pos); - - if(remaining>max) { - packet_length = max; - } - else { - packet_length = remaining; - } - - cur->max_transfer=packet_length-1; - cur->link.depth = BULK_DEPTH; - - remaining -= packet_length; - pos+= packet_length; - last = cur; - } - -// if( packet_length == max) { // if final packet wasn't short, add a zero packet -// cur = new_td(); -// dt = dt^0x01; -// cur->packet_type = type; -// cur->max_transfer = 0x7ff; // zero length code -// last->link.terminate=0; -// last->link.link = LINK_ADDR(cur); -// -// } - - cur->link.terminate=1; - - trans = new_transaction(td); - usb_device[devnum].toggle[ep] = dt; - - return(trans); -} - -#define DEPTH 0 - -transaction_t *ctrl_msg(uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, uchar *data) -{ - td_t *td; - td_t *current_td; - td_t *last_td; - transaction_t *trans; - - ctrl_msg_t *message; - - unsigned char type; - int remaining = wLength; - uchar *pos = data; - uchar dt=1; - -// DPRINTF("ctrl_msg( %02x, %02x, %02x, %04x, %04x, %04x, %p)\n", devnum, request_type, request, wValue, wIndex, wLength, data); -// DPRINTF("%d bytes in payload\n", remaining); -// DPRINTF("lowspeed = %u\n", usb_device[devnum].lowspeed); - last_td = td = new_td(); - - td->packet_type = SETUP_TOKEN; - td->device_addr = devnum & 0x7f; - td->max_transfer = 7; // fixed for setup packets - td->retrys = CTRL_RETRIES; - td->active=1; - td->data_toggle=0; - td->link.depth=DEPTH; - td->detect_short=0; - td->interrupt=1; - td->lowspeed = usb_device[devnum].lowspeed; - -// steal 8 bytes from so-called software area to hole the control message itself - td->buffer = (void *) virt_to_bus(&(td->data[2])); - message = bus_to_virt( (unsigned int) td->buffer); - - message->bmRequestType = request_type; - message->bRequest = request; - message->wValue = wValue; - message->wIndex = wIndex; - message->wLength = wLength; -//dump_hex(td, sizeof(td_t), "ctrl_msg:"); - trans = new_transaction(td); - - if(!trans) { - DPRINTF("ctrl_msg: couldn't allocate a transaction!\n"); - return(NULL); - } - - if(request_type & CONTROL_DIR_MASK) - type = IN_TOKEN; - else - type = OUT_TOKEN; - - while(remaining >0) { - int length; - -// DPRINTF("ctrl_msg loop %d remaining, maxpacket = %u\n", remaining, usb_device[devnum].max_packet[0]); - current_td = new_td(); - - last_td->link.link = LINK_ADDR(current_td); - last_td->link.terminate=0; - last_td->link.queue=0; - last_td->link.depth=DEPTH; - - - current_td->device_addr = devnum & 0x7f; - current_td->retrys = CTRL_RETRIES; - current_td->active=1; - current_td->data_toggle=dt; - current_td->link.depth=DEPTH; - current_td->lowspeed = usb_device[devnum].lowspeed; - current_td->detect_short=1; - - dt = dt^0x01; - - current_td->packet_type = type; -// if(type == IN_TOKEN) -// current_td->detect_short=1; - - if(remaining >usb_device[devnum].max_packet[0]) - length = usb_device[devnum].max_packet[0]; - else - length = remaining; - - current_td->max_transfer = length-1; - current_td->buffer = (void *) virt_to_bus(pos); - remaining -= length; - pos += length; - - last_td = current_td; - } - - current_td = new_td(); - - current_td->device_addr = devnum & 0x7f; - current_td->retrys = CONTROL_STS_RETRIES; - current_td->active=1; - current_td->lowspeed = usb_device[devnum].lowspeed; - - if(type == IN_TOKEN) - current_td->packet_type = OUT_TOKEN; - else - current_td->packet_type = IN_TOKEN; - - current_td->max_transfer=0x7ff; - - current_td->link.terminate=1; - current_td->data_toggle=1; - current_td->link.depth=DEPTH; - - - last_td->link.link = LINK_ADDR(current_td); - last_td->link.terminate=0; - last_td->link.queue=0; - last_td->link.depth=DEPTH; - - return(trans); -} - - -int schedule_transaction( uchar dev, transaction_t *trans) -{ - unsigned short value; - - if(!sched_queue[dev]->depth.terminate) - return(-EBUSY); - - sched_queue[dev]->depth.link = LINK_ADDR(trans->qh); - sched_queue[dev]->depth.terminate = 0; - sched_queue[dev]->depth.queue=1; - - if(hc_type[dev]==0x00) { - value = inw(hc_base[dev]); - value |=1; - outw( value, hc_base[dev]); - } -#if 0 - else if (hc_type[dev]==0x10) { - uint32_t value; - ohci_regs_t *ohci_regs = (ohci_regs_t *) hc_base[dev]; - value = readl(&ohci_regs->control); - value |=OHCI_USB_OPER; - writel( value, &ohci_regs->control); - - } -#endif - - return(0); -} - -int wait_transaction( transaction_t *trans) -{ - queue_head_t *qh; - - qh = trans->qh; - - while(!qh->bredth.terminate) - qh = MEM_ADDR(qh->bredth.link); - - return( wait_queue_complete(qh)); -} - -void unlink_transaction( uchar dev, transaction_t *trans) -{ - sched_queue[dev]->depth.terminate=1; - sched_queue[dev]->depth.link = 0; // just in case -} - -int uhci_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data) -{ - transaction_t *trans; - td_t *td; - int data_len; - int ret; - uchar *buffer; - DPRINTF("bulk_transfer: ep = %x len=%d\n", ep, len); -#if ALLOCATE==1 - buffer = allot2(2048, 0x7ff); - if(buffer==0){ - printf("bulk_transfer: can not allot\n"); - } - memset(buffer,0,2048); -// DPRINTF("bulk_transfer: buffer(virt) = %x buffer(phys) = %x len = %d\n", buffer, virt_to_phys(buffer), len); - - if( !(ep & 0x80)) - memcpy(buffer, data, len); -#else - buffer = data; -#endif - - - trans = _bulk_transfer(devnum, ep, len, buffer); -#if 0 -#ifdef DEBUG - dump_transaction(trans, "bulk_transfer:"); -#endif -#endif - schedule_transaction( usb_device[devnum].controller, trans); - ret = wait_transaction(trans); - - if(ret<0) { -#ifdef DEBUG - dump_uhci(hc_base[usb_device[devnum].controller] ); - dump_td(trans->td_list, "failed_bulk_transaction: "); -#endif - unlink_transaction( usb_device[devnum].controller, trans); - free_transaction(trans); -#if ALLOCATE==1 - forget2(buffer); -#endif - return(-1); - } - - unlink_transaction( usb_device[devnum].controller, trans); - - data_len=0; - td = trans->td_list; - do { - if(td->active) - break; - - if(td->max_transfer == 0x7ff) - break; - - data_len += td->actual +1; - - if(td->actual < td->max_transfer) // short packet also check for errors here - break; - - if(!td->link.terminate){ - td = MEM_ADDR(td->link.link); - } - else { - td=NULL; - } - } while(td); -#if 0 - -#ifdef DEBUG - dump_td(trans->td_list, "bulk_transfer_success:"); -#endif -#endif - - if(data_len < len) { - DPRINTF("bulk_transfer( dev= %d, ep = %d, len = %d, buffer = %x) = %d:short transaction:\n", devnum, ep, len, data, data_len); - dump_td(trans->td_list, "short_transaction:"); - } - - free_transaction(trans); - -#if ALLOCATE==1 - if( (ep & 0x80)) - memcpy(data, buffer, len); - forget2(buffer); -#endif - - - DPRINTF("bulk_transfer returning %d\n", data_len); - return(data_len); -} - -int uhci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, void *data) -{ - transaction_t *trans; - td_t *td; - int data_len=0; - uchar *buffer; - int ret; - DPRINTF("uhci_control_msg: request_type = %x request = %x wLength=%d\n", request_type, request, wLength); -#if ALLOCATE==1 -// if( (wLength!=0) && (data!=NULL) ) { - buffer = allot2(2048+wLength,0x7ff); - if(buffer==0){ - printf("uhci_control_msg: can not allot\n"); - } - - memset(buffer,0,2048+wLength); - //DPRINTF("uhci_control_msg: buffer(virt) = %x buffer(phys) = %x wLength=%d\n", buffer, virt_to_phys(buffer), wLength); - if( !(request_type & 0x80)) - memcpy(buffer, data, wLength); -// } else { -// buffer=NULL; -// } - -#else - buffer = data; -#endif - - trans = ctrl_msg(devnum, request_type, request, wValue, wIndex, wLength, buffer); - if(!trans) { - DPRINTF("uhci_control_msg: ctrl_msg failed!\n"); -#if ALLOCATE==1 - forget2(buffer); -#endif - return(-1); - } - - schedule_transaction( usb_device[devnum].controller, trans); - ret = wait_transaction(trans); - - if(ret<0) { -#ifdef DEBUG - dump_uhci(hc_base[usb_device[devnum].controller] ); - dump_td(trans->td_list, "failed_transaction: "); -#endif - unlink_transaction( usb_device[devnum].controller, trans); - free_transaction(trans); -#if ALLOCATE==1 - forget2(buffer); -#endif - return(ret); - } - -//#ifdef DEBUG -// dump_td(trans->td_list, "success: "); -//#endif - - unlink_transaction( usb_device[devnum].controller, trans); - - // now, see what happened - - if(!trans->qh->depth.terminate) { -// handle setup error - - dump_uhci(hc_base); - dump_td(trans->td_list, "qh->depth failed_transaction: "); - - free_transaction(trans); -#if ALLOCATE==1 - forget2(buffer); -#endif - return(-1); - } - - td = trans->td_list; - - do { - if(td->packet_type != SETUP_TOKEN) - data_len += td->actual; - - if(td->actual < td->max_transfer) // short packet also check for errors here - break; - - if(!td->link.terminate) { - td = MEM_ADDR(td->link.link); - } - else { - td=NULL; - } - } while(td); - - free_transaction(trans); - -#if ALLOCATE==1 - if ( (wLength!=0) && (data!=NULL)){ - if( (request_type & 0x80)) - memcpy(data, buffer, wLength); - forget2(buffer); - } -#endif - - DPRINTF("usb_control_message returning %d\n", data_len); - - return(data_len); -} - - -int poll_u_root_hub(unsigned short port, uchar controller) -{ - ushort value; - int addr=0; - int i; - static int do_over=0; - - value = inw(port); - - debug("poll_u_root_hub1 v=%08x\t", value); - - if(value & 0x02 || do_over == port) { - debug("poll_u_root_hub2 v=%08x\t", value); - do_over=0; - if(value & 0x01 ) { // if port connected - debug("poll_u_root_hub21 v=%08x\t", value); - DPRINTF("Connection on port %04x\n", port); - - outw(value, port); - for(i=0; i<40; i++) { - udelay(10000+usec_offset); - value = inw(port); - if(value & 0x02) { - outw(value, port); - i=0; - DPRINTF("BOUNCE!\n"); - } - } - - uport_wakeup(port); -// DPRINTF("Wakup %04x\n", port); - - uport_reset(port); - udelay(10); - uport_enable(port); - - if(!value & 0x01) { - DPRINTF("Device went away!\n"); - return(-1); - } - - addr = configure_device( port, controller, value & 0x100); - - if(addr<0) { - uport_disable(port); - udelay(20000); -// uport_reset(port); - uport_reset_long(port); - uport_suspend(port); - do_over=port; - uhc_clear_stat(); -// dump_uhci(0x38c0); - } - } else { - uport_suspend(port); - uport_disable(port); - DPRINTF("Port %04x disconnected\n", port); - // wave hands, deconfigure devices on this port! - } - } - - - return(addr); -} - -#endif diff --git a/src/filo/usb/uhci.h b/src/filo/usb/uhci.h deleted file mode 100644 index 17370a13..00000000 --- a/src/filo/usb/uhci.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef _UHCI_H -#define _UHCI_H - -/* - * The link pointer is multi use. Some fields are valid only for some uses. - * In other cases, they must be 0 - * - */ - -#define MAX_POLLDEV 10 - -#define MAX_TRANSACTIONS 10 -#define MAX_QUEUEHEAD 255 -#define MAX_TD 1024 - - -typedef struct link_pointer { - unsigned long terminate:1; - unsigned long queue:1; - unsigned long depth:1; - unsigned long reserved:1; - unsigned long link:28; -} __attribute__((packed)) link_pointer_t; - -extern link_pointer_t *frame_list[]; - -void init_framelist(uchar dev); - - -#define SETUP_TOKEN 0x2d -#define IN_TOKEN 0x69 -#define OUT_TOKEN 0xe1 - -#define CTRL_RETRIES 3 -#define CONTROL_STS_RETRIES 0 - - -// some port features -#define PORT_CONNECTION 0 -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define PORT_LOW_SPEED 9 -#define C_PORT_CONNECTION 16 -#define C_PORT_ENABLE 17 -#define C_PORT_SUSPEND 18 -#define C_PORT_OVER_CURRENT 19 -#define C_PORT_RESET 20 - -// features -#define FEATURE_HALT 0 - -typedef struct td { - - link_pointer_t link; - - unsigned long actual:11; // actual length - unsigned long reserved2:5; - -// status/error flags - unsigned long res1:1; - unsigned long bitstuff:1; - unsigned long crc:1; - unsigned long nak:1; - unsigned long babble:1; - unsigned long buffer_error:1; - unsigned long stall:1; - unsigned long active:1; - - unsigned long interrupt:1; // interrupt on complete - unsigned long isochronous:1; - unsigned long lowspeed:1; - unsigned long retrys:2; - unsigned long detect_short:1; - unsigned long reserved3:2; - - unsigned long packet_type:8; // one of in (0x69), out (0xe1) or setup (0x2d) - unsigned long device_addr:7; - unsigned long endpoint:4; - unsigned long data_toggle:1; - unsigned long reserved:1; - unsigned long max_transfer:11; // misnamed. Desired length might be better - - void *buffer; - unsigned long data[4]; // free use by driver -} __attribute__((packed)) td_t; - -typedef struct queue_head { - link_pointer_t bredth; // depth must = 0 - link_pointer_t depth; // depth may vary randomly, ignore - unsigned long int udata[2]; -} __attribute__((packed)) queue_head_t; - -typedef struct transaction { - queue_head_t *qh; - td_t *td_list; - struct transaction *next; -} transaction_t; - -//##################################################### -int wait_head( queue_head_t *head, int count); - -extern queue_head_t *free_qh; -extern queue_head_t *queue_heads; - -queue_head_t *new_queue_head(void); -void free_queue_head( queue_head_t *qh); -void init_qh(void); - -extern td_t *free_td_list; -extern td_t *tds; - -void init_td(void); -td_t *new_td(void); -td_t *find_last_td(td_t *td); -void free_td( td_t *td); -link_pointer_t *queue_end( queue_head_t *queue); -void add_td( queue_head_t *head, td_t *td); - -extern transaction_t transactions[MAX_TRANSACTIONS]; -extern transaction_t *free_transactions; - -void init_transactions(void); -void free_transaction( transaction_t *trans ); -transaction_t *new_transaction(td_t *td); -transaction_t *add_transaction( transaction_t *trans, td_t *td); - - -#define USBCMD(x) hc_base[x] -#define USBSTS(x) (hc_base[x] + 0x02) -#define USBINTR(x) (hc_base[x] + 0x04) -#define FRNUM(x) ( hc_base[x] + 0x06) -#define FLBASE(x) ( hc_base[x] + 0x08) -#define SOFMOD(x) ( hc_base[x] + 0x0c) -#define PORTSC1(x) ( hc_base[x] + 0x10) -#define PORTSC2(x) ( hc_base[x] + 0x12) - -#define USBCMDRUN 0x01 -#define USBCMD_DEBUG 0x20 - -#define USBSTSHALTED 0x20 - - -void hc_reset(uchar dev); -int hc_stop(void); -int hc_start(uchar dev); - -extern queue_head_t *sched_queue[]; - -void init_sched(uchar dev); -int poll_queue_head( queue_head_t *qh); -int wait_queue_complete( queue_head_t *qh); - -extern int num_polls; -extern int (*devpoll[MAX_POLLDEV])(uchar); -extern uchar parm[MAX_POLLDEV]; - -transaction_t *_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data); -transaction_t *ctrl_msg(uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, uchar *data); -int schedule_transaction( uchar dev, transaction_t *trans); -int wait_transaction( transaction_t *trans); -void unlink_transaction( uchar dev, transaction_t *trans); -int uhci_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data); -int uhci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, void *data); - - -// defined in uhci.c -int uhc_init(struct pci_device *dev); -void uhci_init(void); -void clear_uport_stat(unsigned short port); -int poll_u_root_hub(unsigned short port, uchar controller); - -#endif diff --git a/src/filo/usb/usb.c b/src/filo/usb/usb.c deleted file mode 100644 index 23afe9a7..00000000 --- a/src/filo/usb/usb.c +++ /dev/null @@ -1,803 +0,0 @@ -#ifdef USB_DISK - -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - - -#include "usb.h" -#include "uhci.h" -#include "ohci.h" -#include "debug_x.h" - - -#define ALLOCATE 1 - -int usec_offset=0; - -int num_controllers=0; - -uint32_t hc_base[MAX_CONTROLLERS]; -uint8_t hc_type[MAX_CONTROLLERS]; - - -void hci_init(void) -{ - int i; - struct pci_device *dev; - uint8_t prog_if; - - - for(i=0;iclass>>8) & 0xff); - if(prog_if == 0x00 ) { // UHCI - hc_type[num_controllers] = prog_if; - uhc_init(dev); - } - else if(prog_if == 0x10) { // OHCI - hc_type[num_controllers] = prog_if; - ohc_init(dev); - } -#if 0 - else if(prog_if == 0x20) { // EHCI - hc_type[num_controllers] = prog_if; - ehc_init(dev); - } -#endif - i++; - } - // From now should not change num_controllers any more - - uhci_init(); - ohci_init(); -} - - -int next_usb_dev; -usbdev_t usb_device[MAX_USB_DEV]; - -void init_devices(void) -{ - - memset(usb_device,0,sizeof(usb_device)); - usb_device[0].max_packet[0] = 8; - next_usb_dev=2; // 0 for all controller root hub, use MAX_CONTROLLERS instead??? - // do we need have one for every controller ?? or just use hc_base and hc_type instead - // For example 0 --> controller 1 root hub - // 1 --> controller 2 root hub - // 2 --> controller 3 root hub.... -} - - -inline int set_address( uchar address) -{ - int ret; - - ret = usb_control_msg(0, 0, SET_ADDRESS, address, 0, 0, NULL); - - return(ret); -} - -inline int clear_stall(uchar device, uchar endpoint) -{ - int ret; - - ret = usb_control_msg(device, CONTROL_ENDPOINT, CLEAR_FEATURE, FEATURE_HALT, endpoint, 0, NULL); - if(hc_type[device]==0x00) { - usb_device[device].toggle[endpoint]=0; - } - else if(hc_type[device]==0x10) { - usb_settoggle(&usb_device[device], endpoint & 0xf, ((endpoint & 0x80)>>7)^1, 0); - } - - return(ret); -} - -inline int device_reset(uchar device) { - return usb_control_msg(device, 0x21, 0xff, 0, 0, 0, NULL); -} - -/////////////////////////////////////////////////////////////////////////////////////// -// -// String Descriptors -// -////////////////////////////////////////////////////////////////////////////////////// - -#define STRING_DESCRIPTOR 0x0300 - -int get_string( uchar addr, uchar string, int len, uchar *buffer) -{ - int ret; - int i,j; - int real_len; - ushort lang; - - if(!string) { - strcpy(buffer, "unknown"); - return(0); - } - - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, 0, 4, buffer); - real_len = buffer[0]; - if(real_len>len) - real_len = len; - - lang = buffer[2] | buffer[3]<<8; - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, lang, real_len, buffer); - - // de-unicode it! - for(i=0, j=2; jlen) - real_len = len; - - if(real_len<=4) { - strcpy(buffer, "USB"); - real_len = 3; - buffer[real_len] = 0; - } else { - // de-unicode it! - for(i=0, j=2; jbNbrPorts; i++) { - ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, i, 4, &status); -// DPRINTF("Get status for port %u returns: %d\n", i, ret); -// dump_hex(&status, 4, "status="); - - if(status.change.c_port_connection) { - ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, i, 0, NULL); // clear status - - if(status.stat.port_connection) { - udelay(desc->bPwrOn2PwrGood * 20000); - - hub_port_resume(addr, i); - - ret = hub_port_reset(addr,i); - udelay(10); - ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_ENABLE, i, 0, NULL); // enable port - -// ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, i, 4, &status); -// DPRINTF("*****Get status again for port %u returns: %d\n", i, ret); -// dump_hex(&status, 4, "status="); - - devaddr = configure_device(i, usb_device[addr].controller, status.stat.port_lowspeed); - - // configure - } else { - ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_SUSPEND, i, 0, NULL); // suspend port - ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, PORT_ENABLE, i, 0, NULL); // disable port - DPRINTF("Hub %d, Port %04x disconnected\n", addr, i); - // deconfigure - } - } - } - return(devaddr); - -} - -int usb_hub_init( uchar addr) -{ - int i; - int ret; - hub_descriptor_t *desc; - - desc = allot(sizeof(hub_descriptor_t)); - - memset(desc, 0 , sizeof(hub_descriptor_t)); - - DPRINTF("hub init (%d)\n", addr); - - ret = usb_control_msg(addr, 0xa0, GET_DESCRIPTOR, 0x2900, 0, 8, desc); - ret = usb_control_msg(addr, 0xa0, GET_DESCRIPTOR, 0x2900, 0, desc->bLength, desc); - - usb_device[addr].private = desc; - - for(i=1; i<=desc->bNbrPorts; i++) - ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_POWER, i, 0, NULL); // power port - - - // register hub to be polled - - devpoll[num_polls] = poll_hub; - parm[num_polls++] = addr; - - return(0); -} - -extern void ohci_dump_x(uchar controller); - -// will set up whatever device is answering at address 0. -int configure_device(uint32_t port, uchar controller, unsigned int lowspeed) -{ - device_descriptor_t *desc; - config_descriptor_t *conf; - interface_descriptor_t *iface; - endpoint_descriptor_t *epd; - int ret; - int i; - int addr = next_usb_dev++; - uchar buffer[512]; - uchar string[255]; - ushort lang; - uchar x[2]; - - desc = (device_descriptor_t *) buffer; - - memset( &usb_device[addr], 0, sizeof(usbdev_t)); - - printf("New USB device, setting address %d\n", addr); - if(lowspeed) { - usb_device[addr].lowspeed = usb_device[0].lowspeed = 1; - DPRINTF("LOWSPEED\n"); - } else - usb_device[addr].lowspeed = usb_device[0].lowspeed = 0; - - usb_device[0].port = usb_device[addr].port = port; - usb_device[0].controller = usb_device[addr].controller = controller; - usb_device[addr].toggle2[0]=0; - usb_device[addr].toggle2[1]=0; - -// hc_clear_stat(); - - ret = set_address(addr); - if(ret<0) { - DPRINTF("configure_device: set_address failed!\n"); - next_usb_dev--; - return(-1); - } - - mdelay(10); /* Let the SET_ADDRESS settle */ - - usb_device[addr].max_packet[0] = 8; - - - DPRINTF("Fetching device descriptor length\n"); - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x100, 0, 8, desc); - - usb_device[addr].max_packet[0] = desc->max_packet; - - DPRINTF("Fetching device descriptor\n"); - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x100, 0, desc->bLength, desc); - if(ret < desc->bLength) - return(-1); - - DPRINTF("Fetching config descriptor length\n"); - conf = (config_descriptor_t *) (buffer + sizeof(device_descriptor_t)); - - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x200, 0, 8, conf); - - DPRINTF("Fetching config descriptor\n"); - ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x200, 0, conf->wTotalLength, conf); - if(ret < conf->wTotalLength) - return(-1); - - iface = (interface_descriptor_t *) (buffer + sizeof(device_descriptor_t) + conf->bLength); - epd = (endpoint_descriptor_t *) (buffer + conf->bLength + iface->bLength + sizeof(device_descriptor_t)); - - DPRINTF("device:\n"); - dump_device_descriptor( desc, ""); - DPRINTF("config:\n"); - dump_config_descriptor( (uchar *)conf, ""); - - DPRINTF("Selecting Configuration number %x:\n", conf->bConfigurationValue); - ret = usb_control_msg(addr, 0, SET_CONFIGURATION, conf->bConfigurationValue, 0, 0, NULL); - -// mdelay(20); - -#if 0 - usb_control_msg(addr, 0x80, GET_CONFIGURATION, 0, 0, 1 , x); - DPRINTF("Configuration number = %x\n", x[0]); - - usb_control_msg(addr, 0x80, GET_STATUS, 0, addr, 2, x); - DPRINTF("status = %x %x\n", x[0], x[1]); - - usb_control_msg(addr, 0x81, GET_STATUS, 0, 0, 2, x); - DPRINTF("status = %x %x\n", x[0], x[1]); -#endif - - for(i=0; ibNumEndpoints;i++) { - if(!epd[i].bEndpointAddress) { - usb_device[addr].max_packet[ 1 ] = epd[i].wMaxPacketSize & 0x3ff; - } else { - usb_device[addr].max_packet[ epd[i].bEndpointAddress & 0x7f ] = epd[i].wMaxPacketSize & 0x3ff; - } - - if( (epd[i].bmAttributes & 0x03) == 0x01) // interrupt - usb_device[addr].interrupt = epd[i].bEndpointAddress; - - if( (epd[i].bmAttributes & 0x03) == 0x02) { // bulk -#if 0 - DPRINTF("clear stall on ep=%x\n", epd[i].bEndpointAddress); - clear_stall(addr, epd[i].bEndpointAddress); // to reset data toggle - udelay(10); -#endif - -#if 0 - usb_control_msg(addr, 0x82, GET_STATUS, 0, epd[i].bEndpointAddress, 2, x); - DPRINTF("status = %x %x\n", x[0], x[1]); -#endif - - if(epd[i].bEndpointAddress & 0x80){ //in - usb_device[addr].bulk_in = epd[i].bEndpointAddress; - } - else { //out - usb_device[addr].bulk_out = epd[i].bEndpointAddress; - } - } - - } - - // determine device class - if(desc->Class) { - usb_device[addr].class = desc->Class; - usb_device[addr].subclass = desc->SubClass; - usb_device[addr].protocol = desc->protocol; - } else { - usb_device[addr].class = iface->bInterfaceClass; - usb_device[addr].subclass = iface->bInterfaceSubClass; - usb_device[addr].protocol = iface->bInterfaceProtocol; - } - - printf("%02x:%02x:%02x\n", usb_device[addr].class, usb_device[addr].subclass, usb_device[addr].protocol); -#if 0 - get_string(addr, desc->iManufacturor, sizeof(string), string); - printf("Manufacturor: %s\n", string); - - get_string(addr, desc->iProduct, sizeof(string), string); - printf("Product: %s\n", string); - - get_string(addr, desc->iSerial, sizeof(string), string); - printf("Serial: %s\n", string); -#else - lang = get_lang(addr, 0, sizeof(string), string); - - get_string2(addr, desc->iManufacturor, lang, sizeof(string), string); - printf("Manufacturor: %s\n", string); - - get_string2(addr, desc->iProduct, lang,sizeof(string), string); - printf("Product: %s\n", string); - - get_string2(addr, desc->iSerial, lang, sizeof(string), string); - printf("Serial: %s\n", string); -#endif - - switch( usb_device[addr].class) { - case 0x09: // hub - usb_hub_init(addr); - break; - - default: - break; - - } - - DPRINTF("DEVICE CONFIGURED\n"); - - return(addr); -} - -int num_polls=0; -int (*devpoll[MAX_POLLDEV])(uchar); -uchar parm[MAX_POLLDEV]; - -int poll_usb() -{ - int addr; - int found=0; - int i; - int j; - - for(i=0; i0, should probably see what was attached! - if(hc_type[i]==0x00) { - addr = poll_u_root_hub(PORTSC1(i), i); - if(addr && !found) - found=addr; - - addr = poll_u_root_hub(PORTSC2(i), i); - if(addr && !found) - found=addr; - } - - else if(hc_type[i]==0x10) { - int NDP; - NDP = readl(&ohci_regs->roothub.a) & 0xff; - ohci_regs = (ohci_regs_t *)hc_base[i]; - for(j=0;jroothub.portstatus[j], i); - if(addr && !found) - found=addr; - } - - } - - } - - // now poll registered drivers (such as the hub driver - for(i=0;iurb; - } else { - urb = NULL; - } -#endif - - memset(urb, 0, sizeof(*urb)); - - return urb; -} -/** - * usb_free_urb - frees the memory used by a urb - * @urb: pointer to the urb to free - * - * If an urb is created with a call to usb_create_urb() it should be - * cleaned up with a call to usb_free_urb() when the driver is finished - * with it. - */ -void usb_free_urb(struct urb* urb) -{ -#if URB_PRE_ALLOCATE!=1 - if (urb) - forget2(urb); -#endif -} - -void usb_wait_urb_done(struct urb* urb, int timeout) -{ - usbdev_t *usb_dev = urb->dev; - if(hc_type[usb_dev->controller]==0x10) { - ohci_wait_urb_done(urb, timeout); - } - -} - - -int usb_submit_urb(struct urb *urb) -{ - if (urb && urb->dev) { -#if 0 - if(hc_type[urb->dev->controller] == 0x00) { - return uhci_submit_urb(urb); - } else -#endif - if(hc_type[urb->dev->controller] == 0x10) { - return ohci_submit_urb(urb); - } -#if 0 - else if(hc_type[urb->dev->controller] == 0x20) { - return ohci_submit_urb(urb); - } -#endif - return 0; - } - else - return -ENODEV; -} - -// Starts urb and waits for completion or timeout -static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) -{ - int status; - status = usb_submit_urb(urb); - -//for OHCI We will check the BLF and CLF, because HC after processing all td list, it will clear the BLF and CLF - usb_wait_urb_done(urb, timeout); -//Add by LYH to call complete function - if(urb->complete!=0) urb->complete(urb); - - if (actual_length) - *actual_length = urb->actual_length; - - usb_free_urb(urb); - return status; -} -// returns status (negative) or length (positive) -int usb_internal_control_msg(struct usbdev *usb_dev, unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, int len, int timeout, usb_complete_t complete) -{ - struct urb *urb; - int retv; - int length; - - urb = usb_alloc_urb(usb_dev->controller); - if (!urb) - return -ENOMEM; - - FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, - complete,0); - - retv = usb_start_wait_urb(urb, timeout, &length); - if (retv < 0) - return retv; - else - return length; -} -int usb_control_msg_x(struct usbdev *dev, unsigned int pipe, u8 request, u8 requesttype, - u16 value, u16 index, void *data, u16 size, int timeout, usb_complete_t complete) -{ - struct usb_ctrlrequest *dr; - int ret; - int controller = dev->controller; - ohci_t *ohci; - -#if URB_PRE_ALLOCATE!=1 - dr = allot2(sizeof(struct usb_ctrlrequest), 0xf); - if (!dr) { - printf("usb_control_msg_x: dr allocate no MEM\n"); - return -ENOMEM; - } -#else - if(hc_type[controller] == 0x10) { //OHCI - ohci = &_ohci_x[controller]; - dr = ohci->dr; - } else { - dr = NULL; - } - -#endif - - dr->bRequestType = requesttype; - dr->bRequest = request; - dr->wValue = cpu_to_le16p(&value); - dr->wIndex = cpu_to_le16p(&index); - dr->wLength = cpu_to_le16p(&size); - - ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout, complete); - -#if URB_PRE_ALLOCATE!=1 - forget2(dr); -#endif - - return ret; -} -int usb_bulk_msg_x(struct usbdev *usb_dev, unsigned int pipe, - void *data, int len, int *actual_length, int timeout, usb_complete_t complete) -{ - struct urb *urb; - - if (len < 0) - return -EINVAL; - - urb=usb_alloc_urb(usb_dev->controller); - if (!urb) - return -ENOMEM; - - FILL_BULK_URB(urb, usb_dev, pipe, data, len, - complete, 0); - - return usb_start_wait_urb(urb,timeout,actual_length); -} - -#endif diff --git a/src/filo/usb/usb.h b/src/filo/usb/usb.h deleted file mode 100644 index 58fd5734..00000000 --- a/src/filo/usb/usb.h +++ /dev/null @@ -1,435 +0,0 @@ -#ifndef _USB_H -#define _USB_H - -#define URB_PRE_ALLOCATE 1 - -#define u32 uint32_t -#define u16 uint16_t -#define u8 uint8_t - -#define uchar uint8_t -#define ushort uint16_t -#define EBUSY 1 -#define ENOMEM 12 -#define ENODEV 19 -#define EINVAL 22 -#define EINPROGRESS 115 - -#define LINK_ADDR(x) ( virt_to_bus(x) >> 4) -#define MEM_ADDR(x) (void *) ( bus_to_virt( ((unsigned int) (x)) <<4) ) - -#define MAX_CONTROLLERS 4 - -extern int num_controllers; - -extern uint32_t hc_base[]; -extern uint8_t hc_type[]; - -// Some control message bmRequestType defines -#define CTRL_DEVICE 0 -#define CONTROL_INTERFACE 1 -#define CONTROL_ENDPOINT 2 -#define CONTROL_OTHER 3 -#define CONTROL_RECIPIENT_MASK 0x1f - -#define CONTROL_TYPE_STD 0 -#define CONTROL_TYPE_CLASS 0x20 -#define CONTROL_CLASS_VENDOR 0x40 -#define CONTROL_CLASS_MASK 0x60 - -#define CONTROL_OUT 0 -#define CONTROL_IN 0x80 -#define CONTROL_DIR_MASK 0x80 - -// bRequest values -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 -#define SET_FEATURE 3 -#define SET_ADDRESS 5 - -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 - -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 - -#define GET_INTERFACE 10 -#define SET_INTERFACE 11 - -#define SYNC_FRAME 12 - -// descriptor types -#define DEVICE_DESC 1 -#define CONFIGURATION_DESC 2 -#define STRING_DESC 3 -#define INTERFACE_DESC 4 -#define ENDPOINT_DESC 5 -#define OTHERSPEED_DESC 7 -#define POWER_DESC 8 - - -typedef struct device_descriptor { - uchar bLength; - uchar type; - - uchar bcdVersion[2]; - uchar Class; - uchar SubClass; - uchar protocol; - uchar max_packet; - - unsigned short idVendor; - unsigned short idProduct; - - uchar bcdDevice[2]; - uchar iManufacturor; - uchar iProduct; - uchar iSerial; - uchar bNumConfig; -} __attribute__((packed)) device_descriptor_t; - -#define GET_DESCRIPTOR 6 - -typedef struct config_descriptor { - uchar bLength; - uchar type; - - unsigned short wTotalLength; - uchar bNumInterfaces; - uchar bConfigurationValue; - uchar iConfiguration; - - uchar bmAttributes; - uchar bMaxPower; -} __attribute__((packed)) config_descriptor_t; - -typedef struct interface_descriptor { - uchar bLength; - uchar type; - - uchar bInterfaceNumber; - uchar bAlternateSetting; - - uchar bNumEndpoints; - uchar bInterfaceClass; - uchar bInterfaceSubClass; - uchar bInterfaceProtocol; - uchar iInterface; -} __attribute__((packed)) interface_descriptor_t; - -typedef struct endpoint_descriptor { - uchar bLength; - uchar type; - - uchar bEndpointAddress; - uchar bmAttributes; - unsigned short wMaxPacketSize; - uchar bInterval; -} __attribute__((packed)) endpoint_descriptor_t; - -typedef struct ctrl_msg { - uchar bmRequestType; - uchar bRequest; - unsigned short wValue; - unsigned short wIndex; - unsigned short wLength; -} __attribute__((packed)) ctrl_msg_t; - -// Some descriptors for hubs, will be moved later -typedef struct hub_descriptor { - uchar bLength; - uchar type; - - uchar bNbrPorts; - ushort wHubCharacteristics; - uchar bPwrOn2PwrGood; - uchar bHubCntrCurrent; - - uchar DeviceRemovable; // assume bNbrPorts <=8 - uchar PortPwrCntrMask; -} __attribute__((packed)) hub_descriptor_t; - -#define MAX_USB_DEV 127 -#define MAX_EP 8 - -typedef struct usbdev { - uint32_t port; - uchar address; - uchar controller; - uchar class; - uchar subclass; - uchar protocol; - uchar bulk_in; - uchar bulk_out; - uchar interrupt; - uchar lowspeed; - uint32_t toggle2[2]; //For OHCI - uint32_t halted[2]; - uchar toggle[MAX_EP]; //for UHCI - unsigned short max_packet[MAX_EP]; - void *private; -} usbdev_t; - -// I will use urb as transaction for OHCI to remember the td and ed - -struct urb; -typedef void (*usb_complete_t)(struct urb *); - -struct urb -{ -#if 0 - spinlock_t lock; // lock for the URB -#endif - void *hcpriv; // private data for host controller -#if 0 - struct list_head urb_list; // list pointer to all active urbs - struct urb *next; // pointer to next URB -#endif - struct usbdev *dev; // pointer to associated USB device - unsigned int pipe; // pipe information - int status; // returned status - unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc. - void *transfer_buffer; // associated data buffer - void *transfer_dma; // dma addr for transfer_buffer - int transfer_buffer_length; // data buffer length - int actual_length; // actual data buffer length - int bandwidth; // bandwidth for this transfer request (INT or ISO) - unsigned char *setup_packet; // setup packet (control only) - void * setup_dma; // dma addr for setup_packet - // - int start_frame; // start frame (iso/irq only) - int number_of_packets; // number of packets in this request (iso) - int interval; // polling interval (irq only) - int error_count; // number of errors in this transfer (iso only) - int timeout; // timeout (in jiffies) - // - void *context; // context for completion routine - usb_complete_t complete; // pointer to completion routine - // -#if 0 - struct iso_packet_descriptor iso_frame_desc[0]; -#endif -}; - -typedef struct urb urb_t; - -/* - * urb->transfer_flags: - */ -#define USB_DISABLE_SPD 0x0001 -#define URB_SHORT_NOT_OK USB_DISABLE_SPD -#define USB_ISO_ASAP 0x0002 -#define USB_ASYNC_UNLINK 0x0008 -#define USB_QUEUE_BULK 0x0010 -#define USB_NO_FSBR 0x0020 -#define USB_ZERO_PACKET 0x0040 // Finish bulk OUTs always with zero length packet -#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */ - /* ... less overhead for QUEUE_BULK */ -#define USB_TIMEOUT_KILLED 0x1000 // only set by HCD! - - -struct usb_ctrlrequest { - u8 bRequestType; - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -} __attribute__ ((packed)); - -/* - * USB-status codes: - * USB_ST* maps to -E* and should go away in the future - */ - -#define USB_ST_NOERROR 0 -#define USB_ST_CRC (-EILSEQ) -#define USB_ST_BITSTUFF (-EPROTO) -#define USB_ST_NORESPONSE (-ETIMEDOUT) /* device not responding/handshaking */ -#define USB_ST_DATAOVERRUN (-EOVERFLOW) -#define USB_ST_DATAUNDERRUN (-EREMOTEIO) -#define USB_ST_BUFFEROVERRUN (-ECOMM) -#define USB_ST_BUFFERUNDERRUN (-ENOSR) -#define USB_ST_INTERNALERROR (-EPROTO) /* unknown error */ -#define USB_ST_SHORT_PACKET (-EREMOTEIO) -#define USB_ST_PARTIAL_ERROR (-EXDEV) /* ISO transfer only partially completed */ -#define USB_ST_URB_KILLED (-ENOENT) /* URB canceled by user */ -#define USB_ST_URB_PENDING (-EINPROGRESS) -#define USB_ST_REMOVED (-ENODEV) /* device not existing or removed */ -#define USB_ST_TIMEOUT (-ETIMEDOUT) /* communication timed out, also in urb->status**/ -#define USB_ST_NOTSUPPORTED (-ENOSYS) -#define USB_ST_BANDWIDTH_ERROR (-ENOSPC) /* too much bandwidth used */ -#define USB_ST_URB_INVALID_ERROR (-EINVAL) /* invalid value/transfer type */ -#define USB_ST_URB_REQUEST_ERROR (-ENXIO) /* invalid endpoint */ -#define USB_ST_STALL (-EPIPE) /* pipe stalled, also in urb->status*/ - -/** - * FILL_CONTROL_URB - macro to help initialize a control urb - * @URB: pointer to the urb to initialize. - * @DEV: pointer to the struct usb_device for this urb. - * @PIPE: the endpoint pipe - * @SETUP_PACKET: pointer to the setup_packet buffer - * @TRANSFER_BUFFER: pointer to the transfer buffer - * @BUFFER_LENGTH: length of the transfer buffer - * @COMPLETE: pointer to the usb_complete_t function - * @CONTEXT: what to set the urb context to. - * - * Initializes a control urb with the proper information needed to submit - * it to a device. This macro is depreciated, the usb_fill_control_urb() - * function should be used instead. - */ -#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \ - do {\ - (URB)->dev=DEV;\ - (URB)->pipe=PIPE;\ - (URB)->setup_packet=SETUP_PACKET;\ - (URB)->transfer_buffer=TRANSFER_BUFFER;\ - (URB)->transfer_buffer_length=BUFFER_LENGTH;\ - (URB)->complete=COMPLETE;\ - (URB)->context=CONTEXT;\ - } while (0) - - -/** - * FILL_BULK_URB - macro to help initialize a bulk urb - * @URB: pointer to the urb to initialize. - * @DEV: pointer to the struct usb_device for this urb. - * @PIPE: the endpoint pipe - * @TRANSFER_BUFFER: pointer to the transfer buffer - * @BUFFER_LENGTH: length of the transfer buffer - * @COMPLETE: pointer to the usb_complete_t function - * @CONTEXT: what to set the urb context to. - * - * Initializes a bulk urb with the proper information needed to submit it - * to a device. This macro is depreciated, the usb_fill_bulk_urb() - * function should be used instead. - */ -#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \ - do {\ - (URB)->dev=DEV;\ - (URB)->pipe=PIPE;\ - (URB)->transfer_buffer=TRANSFER_BUFFER;\ - (URB)->transfer_buffer_length=BUFFER_LENGTH;\ - (URB)->complete=COMPLETE;\ - (URB)->context=CONTEXT;\ - } while (0) - - -/* - * USB directions - */ -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ - -/* - * USB Packet IDs (PIDs) - */ -#define USB_PID_UNDEF_0 0xf0 -#define USB_PID_OUT 0xe1 -#define USB_PID_ACK 0xd2 -#define USB_PID_DATA0 0xc3 -#define USB_PID_PING 0xb4 /* USB 2.0 */ -#define USB_PID_SOF 0xa5 -#define USB_PID_NYET 0x96 /* USB 2.0 */ -#define USB_PID_DATA2 0x87 /* USB 2.0 */ -#define USB_PID_SPLIT 0x78 /* USB 2.0 */ -#define USB_PID_IN 0x69 -#define USB_PID_NAK 0x5a -#define USB_PID_DATA1 0x4b -#define USB_PID_PREAMBLE 0x3c /* Token mode */ -#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ -#define USB_PID_SETUP 0x2d -#define USB_PID_STALL 0x1e -#define USB_PID_MDATA 0x0f /* USB 2.0 */ - -#define PIPE_ISOCHRONOUS 0 -#define PIPE_INTERRUPT 1 -#define PIPE_CONTROL 2 -#define PIPE_BULK 3 - -#define usb_maxpacket(dev, pipe, out) ((dev)->max_packet[usb_pipeendpoint(pipe)]) -#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT) - -#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) -#define usb_pipein(pipe) (((pipe) >> 7) & 1) -#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) -#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) -#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) -#define usb_pipedata(pipe) (((pipe) >> 19) & 1) -#define usb_pipeslow(pipe) (((pipe) >> 26) & 1) -#define usb_pipetype(pipe) (((pipe) >> 30) & 3) -#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) -#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) -#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) -#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) - -#define PIPE_DEVEP_MASK 0x0007ff00 - - -/* The D0/D1 toggle bits */ -#define usb_gettoggle(dev, ep, out) (((dev)->toggle2[out] >> (ep)) & 1) -#define usb_dotoggle(dev, ep, out) ((dev)->toggle2[out] ^= (1 << (ep))) -static inline void usb_settoggle(struct usbdev *dev, - unsigned int ep, - unsigned int out, - int bit) -{ - dev->toggle2[out] &= ~(1 << ep); - dev->toggle2[out] |= bit << ep; -} - - -/* Endpoint halt control/status */ -#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) -#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) -#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) -#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) - - -static inline unsigned int __create_pipe(usbdev_t *dev, unsigned int endpoint) -{ - return (dev->address << 8) | (endpoint << 15) | - ((dev->lowspeed == 1) << 26); -} - -static inline unsigned int __default_pipe(struct usbdev *dev) -{ - return ((dev->lowspeed == 1) << 26); -} - -/* Create various pipes... */ -#define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#if 0 -#define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#endif -#define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#if 0 -#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#endif -#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev)) -#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN) - - -extern int next_usb_dev; -usbdev_t usb_device[MAX_USB_DEV]; - -void init_devices(void); -void hci_init(void); -int hc_init(struct pci_device *dev); -inline int set_address(uchar address); -inline int clear_stall(uchar device, uchar endpoint); -int poll_usb(); -int configure_device(uint32_t port, uchar controller, unsigned int lowspeed); -int usb_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data); -int usb_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, - unsigned short wLength, void *data); - -int usb_control_msg_x(struct usbdev *dev, unsigned int pipe, u8 request, u8 requesttype, - u16 value, u16 index, void *data, u16 size, int timeout, usb_complete_t complete); -int usb_bulk_msg_x(struct usbdev *usb_dev, unsigned int pipe, - void *data, int len, int *actual_length, int timeout, usb_complete_t complete); - -#endif diff --git a/src/filo/usb/usb_scsi_low.c b/src/filo/usb/usb_scsi_low.c deleted file mode 100644 index 20afecae..00000000 --- a/src/filo/usb/usb_scsi_low.c +++ /dev/null @@ -1,172 +0,0 @@ -#ifdef USB_DISK -/******************************************************************************* - * - * - * Copyright 2003 Steven James and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - -#define uchar uint8_t - -//#include "debug_x.h" -#include "usb_scsi_low.h" - -int usb_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data); - -#define SG_DXFER_FROM_DEV -3 -#define SG_DXFER_TO_DEV -2 - -#define REQUEST_SENSE 0x03 - -#define CBW_SIG 0x43425355 - -typedef struct usb_cbw { - unsigned int signature; - unsigned int tag; - unsigned int transfer_len; // this is exclusive of cbw and csw - - uchar res1:7; - uchar direction:1; // 1 = device to host (read) - - uchar lun:4; - uchar res:4; - - uchar cbw_len:5; // the length of the SCSI command - uchar res3:3; - - uchar scsi_cmd[16]; -} __attribute__ ((packed)) usb_cbw_t; - -#define CSW_SIG 0x53425355 - -typedef struct usb_csw { - unsigned int signature; - unsigned int tag; - unsigned int residue; - uchar status; -} __attribute__ ((packed)) usb_csw_t; - - -int scsi_command( uchar device, unsigned char *cmd, int cmd_len, int direction, unsigned char *data, int data_len, char *sense_data, int sense_len) -{ - usb_cbw_t cbw; - usb_csw_t csw; - int ret; - - memset(&cbw,0,sizeof(usb_cbw_t)); - memset(&csw,0,sizeof(usb_csw_t)); - - cbw.signature = CBW_SIG; - cbw.tag = 777; - - memcpy(cbw.scsi_cmd, cmd, cmd_len); - cbw.cbw_len = cmd_len; - - if(direction == SG_DXFER_FROM_DEV) - cbw.direction=1; - - cbw.transfer_len = data_len; - - ret = usb_bulk_transfer(device, 2, sizeof(cbw), (uchar *) &cbw); - if(ret<0){ - DPRINTF("ERROR:Bulk write:\n"); - } - - if(data_len) { - if(cbw.direction) { - DPRINTF("scsi_command reading %d bytes\n", data_len); - ret = usb_bulk_transfer(device, 0x81, data_len, data); - DPRINTF("scsi_command read %d bytes\n", ret); - if(ret<0 || ret and - * LinuxLabs http://www.linuxlabs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include - -#define DEBUG_THIS DEBUG_USB -#include - -#define DPRINTF debug - -#include "usb.h" -#include "scsi_cmds.h" - -struct usbdisk_info_t { - struct controller *ctrl; - uint16_t heads; - uint16_t cylinders; - uint16_t sectors_per_track; - uint8_t model_number[41]; - uint8_t slave; - sector_t sectors; - int address_mode; -#define ADDRESS_MODE_CHS 0 -#define ADDRESS_MODE_LBA 1 -#define ADDRESS_MODE_LBA48 2 -#define ADDRESS_MODE_PACKET 3 - uint32_t hw_sector_size; - unsigned drive_exists : 1; - unsigned slave_absent : 1; - unsigned removable : 1; - - unsigned char usb_device_address; -}; - -struct usbdisk_info_t usbdisk_info; - -#define TEST 0 - -#if TEST==1 -#include "usb_scsi_low.h" -typedef struct partition_entry { - uchar boot_flag; - - uchar chs[7]; - - unsigned int lba_start; - unsigned int lba_len; -} __attribute__ ((packed)) partition_entry_t; - -typedef struct partition { - char loader[446]; - partition_entry_t entry[4]; - char sig[2]; -} __attribute__ ((packed)) partition_t; -#endif - -int usb_probe(int drive) -{ - struct usbdisk_info_t *info = &usbdisk_info; -#if TEST==1 - partition_t part; - unsigned char sense_data[32]; -#endif - int i,res; - int error_count=100; - - printf("LinuxLabs USB bootloader\n"); - -// outb( 0x30, 0x70); // reset primary boot -// outb( 0xff, 0x71); - init_devices(); - hci_init(); - - info->usb_device_address = 0; - // find first usb device - - while(error_count && (res = poll_usb())) // keep polling usb until no more devices are enumerated - if(res<0) - if(!--error_count) - printf("There is a USB device, but it won't init! This is a bad thing.\n"); - - for(i=0; i< next_usb_dev ; i++) { - if(usb_device[i].class == 0x08 && usb_device[i].subclass == 0x06 && usb_device[i].protocol == 0x50) { - printf("Found USB block device %d\n", i); - if(drive==0) { - info->usb_device_address = i; - break; - } - drive--; - } - } - - if(info->usb_device_address == 0) return -1; - - UnitReady(info->usb_device_address); - -#if TEST==1 -//Test - printf("Requesting initial sense data\n"); - request_sense( info->usb_device_address, sense_data, 32); - PrintSense(sense_data, 32); - - res = ll_read_block(info->usb_device_address, (uint8_t *)&part, 0, 1); - - printf("ll_read_block returns %d\n", res); - - res=-1; - - debug("part address (phy) = %x, (virt) = %x\n", (uint32_t) virt_to_phys(&part), (uint32_t)&part); - - for(i=0; i<4; i++) { - printf("%d: boot=%02x, start=%08x length=%08x\n",i, part.entry[i].boot_flag, part.entry[i].lba_start, part.entry[i] -.lba_len); - } - - -#endif - - return 0; -} -int usb_read(int drive, sector_t sector, void *buffer) -{ - struct usbdisk_info_t *info = &usbdisk_info; - int result; - int blocknum = sector; - int i; -// printf("sector= %d\t", blocknum); - result = ll_read_block(info->usb_device_address, buffer,blocknum, 1); -#if 0 - for(i=0;i<128;i++) { - if((i%4)==0) printf("\n %08x:",i*4); - printf(" %08x ",(uint32_t)*((uint32_t *)buffer+i)); - } -#endif - - if(result!=512) return -1; - - return 0; -} -#endif