+++ /dev/null
-# !!! 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
+++ /dev/null
-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 <Esc> key is pressed
- during this time period, automatic boot is canceled.
- Pressing <Enter> 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 <Esc> 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 <ts1@tsn.or.jp>.
-
-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 <ts1@tsn.or.jp> and others.
- This program is licensed under the terms of GNU General Public License.
- See the COPYING file for details.
+++ /dev/null
-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
+++ /dev/null
-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
+++ /dev/null
-/* Derived from Etherboot 5.1 */
-
-#include <etherboot.h>
-#include <pci.h>
-#include <timer.h>
-#include <lib.h>
-
-#define DEBUG_THIS DEBUG_IDE
-#include <debug.h>
-
-#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: */
+++ /dev/null
-#include <etherboot.h>
-
-#include <lib.h>
-#include <fs.h>
-
-#define DEBUG_THIS DEBUG_BLOCKDEV
-#include <debug.h>
-
-#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;
-}
+++ /dev/null
-
-#include <etherboot.h>
-#include <fs.h>
-#include <lib.h>
-
-#define DEBUG_THIS DEBUG_ELTORITO
-#include <debug.h>
-
-#define ELTORITO_PLATFORM_X86 0
-#define ELTORITO_PLATFORM_PPC 1
-#define ELTORITO_PLATFORM_MAC 2
-#include <bits/eltorito.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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)))
+++ /dev/null
-/* 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 <lib.h>
-#include <etherboot.h>
-
-#include <fs.h>
-
-/* 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 */
+++ /dev/null
-/*
- * 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 <lib.h>
-#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 */
+++ /dev/null
-/*
- * 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 <lib.h>
-#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 */
+++ /dev/null
-/*
- * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
- * including Rock Ridge Extensions support
- *
- * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>
- *
- * 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 <lly@pisem.net> 2003
- */
-
-/*
- * Modified to make it work with FILO
- * 2003-10 by SONE Takeshi
- */
-
-#ifdef FSYS_ISO9660
-
-#include <lib.h>
-#include "string.h"
-#include "shared.h"
-#include "filesys.h"
-#include "iso9660.h"
-#define DEBUG_THIS 1
-#include <debug.h>
-
-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 */
-
+++ /dev/null
-/* 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 */
+++ /dev/null
-/*
- * 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<<BLOCK_SIZE_BITS)
-
-/* made up, defaults to 1 but can be passed via mount_opts */
-#define WHICH_SUPER 1
-/* kind of from fs/ext2/super.c (is OK for minix) */
-#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
-
-/* include/asm-i386/type.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;
-
-/* include/linux/minix_fs.h */
-#define MINIX_ROOT_INO 1
-
-/* Not the same as the bogus LINK_MAX in <linux/limits.h>. 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 */
+++ /dev/null
-/* 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 <lib.h>
-#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 */
+++ /dev/null
-/* 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 */
+++ /dev/null
-/*
- * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
- * including Rock Ridge Extensions support
- *
- * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>
- *
- * 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<<ISO_SECTOR_BITS)
-
-#define ISO_REGULAR 1 /* regular file */
-#define ISO_DIRECTORY 2 /* directory */
-#define ISO_OTHER 0 /* other file (with Rock Ridge) */
-
-#define RR_FLAG_PX 0x01 /* have POSIX file attributes */
-#define RR_FLAG_NM 0x08 /* have alternate file name */
-
-/* POSIX file attributes for Rock Ridge extensions */
-#define POSIX_S_IFMT 0xF000
-#define POSIX_S_IFREG 0x8000
-#define POSIX_S_IFDIR 0x4000
-
-/* volume descriptor types */
-#define ISO_VD_PRIMARY 1
-#define ISO_VD_END 255
-
-#define ISO_STANDARD_ID "CD001"
-
-#ifndef ASM_FILE
-
-typedef uint8_t u_int8_t;
-typedef uint16_t u_int16_t;
-typedef uint32_t u_int32_t;
-
-typedef union {
- u_int8_t l,b;
-} iso_8bit_t;
-
-typedef struct __iso_16bit {
- u_int16_t l, b;
-} iso_16bit_t __attribute__ ((packed));
-
-typedef struct __iso_32bit {
- u_int32_t l, b;
-} iso_32bit_t __attribute__ ((packed));
-
-typedef u_int8_t iso_date_t[7];
-
-struct iso_directory_record {
- iso_8bit_t length;
- iso_8bit_t ext_attr_length;
- iso_32bit_t extent;
- iso_32bit_t size;
- iso_date_t date;
- iso_8bit_t flags;
- iso_8bit_t file_unit_size;
- iso_8bit_t interleave;
- iso_16bit_t volume_seq_number;
- iso_8bit_t name_len;
- u_int8_t name[1];
-} __attribute__ ((packed));
-
-struct iso_primary_descriptor {
- iso_8bit_t type;
- u_int8_t id[5];
- iso_8bit_t version;
- u_int8_t _unused1[1];
- u_int8_t system_id[32];
- u_int8_t volume_id[32];
- u_int8_t _unused2[8];
- iso_32bit_t volume_space_size;
- u_int8_t _unused3[32];
- iso_16bit_t volume_set_size;
- iso_16bit_t volume_seq_number;
- iso_16bit_t logical_block_size;
- iso_32bit_t path_table_size;
- u_int8_t type_l_path_table[4];
- u_int8_t opt_type_l_path_table[4];
- u_int8_t type_m_path_table[4];
- u_int8_t opt_type_m_path_table[4];
- struct iso_directory_record root_directory_record;
- u_int8_t volume_set_id[128];
- u_int8_t publisher_id[128];
- u_int8_t preparer_id[128];
- u_int8_t application_id[128];
- u_int8_t copyright_file_id[37];
- u_int8_t abstract_file_id[37];
- u_int8_t bibliographic_file_id[37];
- u_int8_t creation_date[17];
- u_int8_t modification_date[17];
- u_int8_t expiration_date[17];
- u_int8_t effective_date[17];
- iso_8bit_t file_structure_version;
- u_int8_t _unused4[1];
- u_int8_t application_data[512];
- u_int8_t _unused5[653];
-} __attribute__ ((packed));
-
-struct rock_ridge {
- u_int16_t signature;
- u_int8_t len;
- u_int8_t version;
- union {
- struct CE {
- iso_32bit_t extent;
- iso_32bit_t offset;
- iso_32bit_t size;
- } ce;
- struct NM {
- iso_8bit_t flags;
- u_int8_t name[0];
- } nm;
- struct PX {
- iso_32bit_t mode;
- iso_32bit_t nlink;
- iso_32bit_t uid;
- iso_32bit_t gid;
- } px;
- struct RR {
- iso_8bit_t flags;
- } rr;
- } u;
-} __attribute__ ((packed));
-
-typedef union RR_ptr {
- struct rock_ridge *rr;
- char *ptr;
- int i;
-} RR_ptr_t;
-
-#define RRMAGIC(c1, c2) ((c1)|(c2) << 8)
-
-#define CHECK2(ptr, c1, c2) \
- (*(unsigned short *)(ptr) == (((c1) | (c2) << 8) & 0xFFFF))
-#define CHECK4(ptr, c1, c2, c3, c4) \
- (*(unsigned long *)(ptr) == ((c1) | (c2)<<8 | (c3)<<16 | (c4)<<24))
-
-#endif /* !ASM_FILE */
-
-#endif /* _ISO9660_H_ */
+++ /dev/null
-/* jfs.h - an extractions from linux/include/linux/jfs/jfs* into one file */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2000 International Business Machines Corp.
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _JFS_H_
-#define _JFS_H_
-
-/* those are from jfs_filsys.h */
-
-/*
- * file system option (superblock flag)
- */
-/* platform option (conditional compilation) */
-#define JFS_AIX 0x80000000 /* AIX support */
-/* POSIX name/directory support */
-
-#define JFS_OS2 0x40000000 /* OS/2 support */
-/* case-insensitive name/directory support */
-
-#define JFS_LINUX 0x10000000 /* Linux support */
-/* case-sensitive name/directory support */
-
-/* directory option */
-#define JFS_UNICODE 0x00000001 /* unicode name */
-
-/* bba */
-#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */
-
-
-/*
- * buffer cache configuration
- */
-/* page size */
-#ifdef PSIZE
-#undef PSIZE
-#endif
-#define PSIZE 4096 /* page size (in byte) */
-
-/*
- * fs fundamental size
- *
- * PSIZE >= 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_ */
+++ /dev/null
-/* Sorry, nothing is shared here ;) Just for GRUB compatibility. */
+++ /dev/null
-/* Interface between GRUB's fs drivers and application code */
-#include <lib.h>
-
-#include "filesys.h"
-#include <fs.h>
-
-#define DEBUG_THIS DEBUG_VFS
-#include <debug.h>
-
-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)
-{
-}
-
+++ /dev/null
-/* 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 */
+++ /dev/null
-/*
- * context switching
- * 2003-10 by SONE Takeshi
- */
-#include <etherboot.h>
-
-#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
+++ /dev/null
-#ifndef i386_CONTEXT_H
-#define i386_CONTEXT_H
-
-#include <stdint.h>
-
-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 */
+++ /dev/null
-/*
- * 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 <etherboot.h>
-
-#include <lib.h>
-
-#include <fs.h>
-#include <sys_info.h>
-
-#include "context.h"
-#include "segment.h"
-
-#define DEBUG_THIS DEBUG_LINUXLOAD
-#include <debug.h>
-
-#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=<file>, 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=<size>, 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)
-