david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

GPXE code cleanup and purge.

This commit is contained in:
Michael Brown 2006-03-17 14:09:45 +00:00
parent cdf1511d3e
commit a2b15fd1fe
52 changed files with 0 additions and 16693 deletions

View File

@ -1,68 +0,0 @@
# !!! NOTE !!!
# Do NOT add spaces or comments at the end of option lines.
# It confuses some versions of make.
# Image filename for automatic boot and optional command line parameter
#AUTOBOOT_FILE = "hda3:/boot/vmlinuz root=/dev/hda3 console=tty0 console=ttyS0,115200"
AUTOBOOT_FILE = "hda2:/boot/vmlinuz initrd=/boot/initrd pci=noacpi ro root=/dev/hda2 console=tty0 console=ttyS0,115200"
#AUTOBOOT_FILE = "mem@0xfff80000"
#AUTOBOOT_FILE = "hde1@0"
#AUTOBOOT_FILE = "uda1:/ram0_2.5_2.6.5_k8.2_mydisk7.elf"
#AUTOBOOT_FILE = "hda5:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hda7 console=tty0 console=ttyS0,115200"
# Time in second before booting AUTOBOOT_FILE
AUTOBOOT_DELAY = 2
# Driver for hard disk, CompactFlash, and CD-ROM on IDE bus
IDE_DISK = 1
# Driver for USB disk
USB_DISK = 1
# Filesystems
# To make filo.zelf < 32 k, You may not enable JFS, MINIX, XFS
# Is anyone still using these file system? BY LYH
FSYS_EXT2FS = 1
FSYS_FAT = 1
#FSYS_JFS = 1
#FSYS_MINIX = 1
FSYS_REISERFS = 1
#FSYS_XFS = 1
FSYS_ISO9660 = 1
# Support for boot disk image in bootable CD-ROM (El Torito)
ELTORITO = 1
# PCI support
SUPPORT_PCI = 1
# Debugging
#DEBUG_ALL = 1
#DEBUG_ELFBOOT = 1
#DEBUG_ELFNOTE = 1
#DEBUG_LINUXBIOS = 1
#DEBUG_MALLOC = 1
#DEBUG_MULTIBOOT = 1
#DEBUG_SEGMENT = 1
#DEBUG_SYS_INFO = 1
#DEBUG_TIMER = 1
#DEBUG_BLOCKDEV = 1
#DEBUG_PCI = 1
#DEBUG_LINUXLOAD = 1
#DEBUG_IDE = 1
#DEBUG_USB = 1
#DEBUG_ELTORITO = 1
# i386 options
# Loader for standard Linux kernel image, a.k.a. /vmlinuz
LINUX_LOADER = 1
# Boot FILO from Multiboot loader (eg. GRUB)
# You need to modify i386/multiboot.c to use it. change mmrange to e820entries.
# By LYH
#MULTIBOOT_IMAGE = 1
# Use PCI Configuration Mechanism #1 (most boards)
PCI_CONFIG_1 = 1

View File

@ -1,125 +0,0 @@
This is FILO, a bootloader which loads boot images from local filesystem,
without help from legacy BIOS services.
Expected usage is to flash it into the BIOS ROM together with LinuxBIOS.
FEATURES
- Supported boot devices: IDE hard disk and CD-ROM, and system memory (ROM)
- Supported filesystems: ext2, fat, jfs, minix, reiserfs, xfs, and iso9660
- Supported image formats: ELF and [b]zImage (a.k.a. /vmlinuz)
- Supports boot disk image of El Torito bootable CD-ROM
- Supports loading image from raw device with user-specified offset
- Console on VGA + keyboard, serial port, or both
- Line editing with ^H, ^W and ^U keys to type arbitrary filename to boot
- Full support for the ELF Boot Proposal (where is it btw, Eric?)
- Auxiliary tool to compute checksum of ELF boot images
- Full 32-bit code, no BIOS calls
REQUIREMENT
Only i386 PC architecture is currently supported.
x86-64 (AMD 64) machines in 32-bit mode should also work.
(It looks like LinuxBIOS uses 32-bit mode and Linux kernel does
the transition to 64-bit mode)
I'm using a VIA EPIA 5000 mini-ITX board, with a 2.5" IDE hard disk
and a 32x CD-RW, for testing, and Bochs and VMware for development.
Recent version of GNU toolchain is required to build.
I have tested with Debian/woody (gcc 2.95.4, binutils 2.12.90.0.1,
make 3.79.1) and Debian/sid (gcc 3.3.2, binutils 2.14.90.0.6,
make 3.80).
INSTALL
First invocation of make creates the default Config file.
$ make
Edit this file as you like. It's fairly straightforward (I hope).
$ vi Config
Then running make again will build filo.elf, the ELF boot image of FILO.
$ make
Use filo.elf as your payload of LinuxBIOS, or a boot image for
Etherboot.
If you enable MULTIBOOT_IMAGE option in Config, you can
also boot filo.elf from GNU GRUB or other Multiboot bootloader.
This feature is intended for testing or development purpose.
USING
When FILO starts, it displays "boot:" prompt.
At "boot:" prompt, type the name of your boot image, and optionally
the kernel parameter, in the form:
DEVICE:FILENAME[ PARAM]
for example:
boot: hda1:/vmlinuz root=/dev/hda1
Notation of DEVICE for IDE disk and CD-ROM is same as in Linux
(eg. hda1 means the first partition of master device on primary
IDE channel).
FILENAME can be standard bzImage/zImage (vmlinuz) Linux kernels,
Linux-compatible images such as memtest.bin of Memtest86,
and any bootable ELF images, which include Linux kernel converted
by mkelfImage, Etherboot .elf and .zelf, Memtest86, FILO itself, etc.
If AUTOBOOT_FILE is set in Config, FILO tries to boot this file
first, and falls back to boot: prompt if it fails.
If AUTOBOOT_DELAY is also set, FILO waits for specified time in
seconds before booting AUTOBOOT_FILE. If <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.

View File

@ -1,48 +0,0 @@
Moved from FILO into Etherboot, yhlu add boot from SATA disk and move usb boot framework
from Steven James baremetal in LinuxBIOS, also add the OHCI support.
1. refer to README.filo
but don't need to use make config.
2. CFLAG added
CONSOLE_BTEXT --- for btext console support
CONSOLE_PC_KBD --- for direct pc keyboard support
CONFIG_FILO --- It will make main call pci_init
3. to make:
make bin/filo.zelf
or
make bin/tg3--filo.zelf
You can not use filo and ide_disk at the same time.
Some input for boot:
boot from BIOS ROM area
4G-128K
mem@0xfffe0000
4G-512K
mem@0xfff80000
boot from suse
hda2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hda2 console=tty0 console=ttyS0,115200
for suse install from CD
hdc:/boot/loader/linux initrd=/boot/loader/initrd ramdisk_size=65536 splash=silent showopts console=tty0 console=ttyS0,115200
boot from RH
for RH install from CD
hdc:/isolinux/vmlinuz initrd=/isolinux/initrd.img expert nofb acpi=off devfs=nomount ramdisk_size=65536 console=ttyS0,115200
for serial ATA support (using port1 and port2 only)
1) if your kernel think SATA as SCSI
hde2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/sda2 console=tty0 console=ttyS0,115200
2) if your kernel think SATA as normal IDE
hde2:/boot/vmlinuz initrd=/boot/initrd ro root=/dev/hde2 console=tty0 console=ttyS0,115200
for usb support
uda1:/ram0_2.5_2.6.5_k8.2_mydisk7.elf
Yinghai Lu yhlu@tyan.com
to do:
add menu to filo boot

View File

@ -1,15 +0,0 @@
It is from steven james's baremetal in linuxbios util.
yhlu seperate common functions from uhci.c to usb.c and create ohci.c to support ohci.
ohci.c mainly cames from kernel 2.4.22 dirvers/usb/host/usb-ohci.c.
it includes several parts
1. UHCI+OHCI--->USB: privide usb init and usb_control_msg and usb_bulk_msg interface
2. USB_SCSI: bulk only device
3. USB_X interface to FILO
other changes in Etherboot
1. Add allot2 and forget2, it will produce the required aligned memory.
todo:
1. EHCI support
yhlu 6/2/2004

File diff suppressed because it is too large Load Diff

View File

@ -1,383 +0,0 @@
#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;
}

View File

@ -1,147 +0,0 @@
#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;
}

View File

@ -1,100 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Defines for the FAT BIOS Parameter Block (embedded in the first block
* of the partition.
*/
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
/* Note that some shorts are not aligned, and must therefore
* be declared as array of two bytes.
*/
struct fat_bpb {
__s8 ignored[3]; /* Boot strap short or near jump */
__s8 system_id[8]; /* Name - can be used to special case
partition manager volumes */
__u8 bytes_per_sect[2]; /* bytes per logical sector */
__u8 sects_per_clust;/* sectors/cluster */
__u8 reserved_sects[2]; /* reserved sectors */
__u8 num_fats; /* number of FATs */
__u8 dir_entries[2]; /* root directory entries */
__u8 short_sectors[2]; /* number of sectors */
__u8 media; /* media code (unused) */
__u16 fat_length; /* sectors/FAT */
__u16 secs_track; /* sectors per track */
__u16 heads; /* number of heads */
__u32 hidden; /* hidden sectors (unused) */
__u32 long_sectors; /* number of sectors (if short_sectors == 0) */
/* The following fields are only used by FAT32 */
__u32 fat32_length; /* sectors/FAT */
__u16 flags; /* bit 8: fat mirroring, low 4: active fat */
__u8 version[2]; /* major, minor filesystem version */
__u32 root_cluster; /* first cluster in root directory */
__u16 info_sector; /* filesystem info sector */
__u16 backup_boot; /* backup boot sector */
__u16 reserved2[6]; /* Unused */
};
#define FAT_CVT_U16(bytarr) (* (__u16*)(bytarr))
/*
* Defines how to differentiate a 12-bit and 16-bit FAT.
*/
#define FAT_MAX_12BIT_CLUST 4087 /* 4085 + 2 */
/*
* Defines for the file "attribute" byte
*/
#define FAT_ATTRIB_OK_MASK 0x37
#define FAT_ATTRIB_NOT_OK_MASK 0xC8
#define FAT_ATTRIB_DIR 0x10
#define FAT_ATTRIB_LONGNAME 0x0F
/*
* Defines for FAT directory entries
*/
#define FAT_DIRENTRY_LENGTH 32
#define FAT_DIRENTRY_ATTRIB(entry) \
(*((unsigned char *) (entry+11)))
#define FAT_DIRENTRY_VALID(entry) \
( ((*((unsigned char *) entry)) != 0) \
&& ((*((unsigned char *) entry)) != 0xE5) \
&& !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) )
#define FAT_DIRENTRY_FIRST_CLUSTER(entry) \
((*((unsigned short *) (entry+26)))+(*((unsigned short *) (entry+20)) << 16))
#define FAT_DIRENTRY_FILELENGTH(entry) \
(*((unsigned long *) (entry+28)))
#define FAT_LONGDIR_ID(entry) \
(*((unsigned char *) (entry)))
#define FAT_LONGDIR_ALIASCHECKSUM(entry) \
(*((unsigned char *) (entry+13)))

View File

@ -1,233 +0,0 @@
/* GRUB compatibility header */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//#include <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 */

View File

@ -1,779 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_EXT2FS
#include "shared.h"
#include "filesys.h"
#include <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 */

View File

@ -1,494 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_FAT
#include "shared.h"
#include "filesys.h"
#include "fat.h"
#include <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 */

View File

@ -1,348 +0,0 @@
/*
* 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 */

View File

@ -1,403 +0,0 @@
/* fsys_jfs.c - an implementation for the IBM JFS file system */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2001,2002 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_JFS
#include "shared.h"
#include "filesys.h"
#include "jfs.h"
#define MAX_LINK_COUNT 8
#define DTTYPE_INLINE 0
#define DTTYPE_PAGE 1
struct jfs_info
{
int bsize;
int l2bsize;
int bdlog;
int xindex;
int xlastindex;
int sindex;
int slastindex;
int de_index;
int dttype;
xad_t *xad;
ldtentry_t *de;
};
static struct jfs_info jfs;
#define xtpage ((xtpage_t *)FSYS_BUF)
#define dtpage ((dtpage_t *)((char *)FSYS_BUF + 4096))
#define fileset ((dinode_t *)((char *)FSYS_BUF + 8192))
#define inode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t)))
#define dtroot ((dtroot_t *)(&inode->di_btroot))
static ldtentry_t de_always[2] = {
{1, -1, 2, {'.', '.'}},
{1, -1, 1, {'.'}}
};
static int
isinxt (s64 key, s64 offset, s64 len)
{
return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
}
static xad_t *
first_extent (dinode_t *di)
{
xtpage_t *xtp;
jfs.xindex = 2;
xtp = (xtpage_t *)&di->di_btroot;
jfs.xad = &xtp->xad[2];
if (xtp->header.flag & BT_LEAF) {
jfs.xlastindex = xtp->header.nextindex;
} else {
do {
devread (addressXAD (jfs.xad) << jfs.bdlog, 0,
sizeof(xtpage_t), (char *)xtpage);
jfs.xad = &xtpage->xad[2];
} while (!(xtpage->header.flag & BT_LEAF));
jfs.xlastindex = xtpage->header.nextindex;
}
return jfs.xad;
}
static xad_t *
next_extent (void)
{
if (++jfs.xindex < jfs.xlastindex) {
} else if (xtpage->header.next) {
devread (xtpage->header.next << jfs.bdlog, 0,
sizeof(xtpage_t), (char *)xtpage);
jfs.xlastindex = xtpage->header.nextindex;
jfs.xindex = XTENTRYSTART;
jfs.xad = &xtpage->xad[XTENTRYSTART];
} else {
return NULL;
}
return ++jfs.xad;
}
static void
di_read (u32 inum, dinode_t *di)
{
s64 key;
u32 xd, ioffset;
s64 offset;
xad_t *xad;
pxd_t pxd;
key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize;
xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT;
ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE;
xad = first_extent (fileset);
do {
offset = offsetXAD (xad);
if (isinxt (key, offset, lengthXAD (xad))) {
devread ((addressXAD (xad) + key - offset) << jfs.bdlog,
3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd);
devread (addressPXD (&pxd) << jfs.bdlog,
ioffset, DISIZE, (char *)di);
break;
}
} while ((xad = next_extent ()));
}
static ldtentry_t *
next_dentry (void)
{
ldtentry_t *de;
s8 *stbl;
if (jfs.dttype == DTTYPE_INLINE) {
if (jfs.sindex < jfs.slastindex) {
return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]];
}
} else {
de = (ldtentry_t *)dtpage->slot;
stbl = (s8 *)&de[(int)dtpage->header.stblindex];
if (jfs.sindex < jfs.slastindex) {
return &de[(int)stbl[jfs.sindex++]];
} else if (dtpage->header.next) {
devread (dtpage->header.next << jfs.bdlog, 0,
sizeof(dtpage_t), (char *)dtpage);
jfs.slastindex = dtpage->header.nextindex;
jfs.sindex = 1;
return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]];
}
}
return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL;
}
static ldtentry_t *
first_dentry (void)
{
dtroot_t *dtr;
pxd_t *xd;
idtentry_t *de;
dtr = (dtroot_t *)&inode->di_btroot;
jfs.sindex = 0;
jfs.de_index = 0;
de_always[0].inumber = inode->di_parent;
de_always[1].inumber = inode->di_number;
if (dtr->header.flag & BT_LEAF) {
jfs.dttype = DTTYPE_INLINE;
jfs.slastindex = dtr->header.nextindex;
} else {
de = (idtentry_t *)dtpage->slot;
jfs.dttype = DTTYPE_PAGE;
xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd;
for (;;) {
devread (addressPXD (xd) << jfs.bdlog, 0,
sizeof(dtpage_t), (char *)dtpage);
if (dtpage->header.flag & BT_LEAF)
break;
xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd;
}
jfs.slastindex = dtpage->header.nextindex;
}
return next_dentry ();
}
static dtslot_t *
next_dslot (int next)
{
return (jfs.dttype == DTTYPE_INLINE)
? (dtslot_t *)&dtroot->slot[next]
: &((dtslot_t *)dtpage->slot)[next];
}
static void
uni2ansi (UniChar *uni, char *ansi, int len)
{
for (; len; len--, uni++)
*ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni;
}
int
jfs_mount (void)
{
struct jfs_superblock super;
if (part_length < MINJFS >> SECTOR_BITS
|| !devread (SUPER1_OFF >> SECTOR_BITS, 0,
sizeof(struct jfs_superblock), (char *)&super)
|| (super.s_magic != JFS_MAGIC)
|| !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I,
0, DISIZE, (char*)fileset)) {
return 0;
}
jfs.bsize = super.s_bsize;
jfs.l2bsize = super.s_l2bsize;
jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
return 1;
}
int
jfs_read (char *buf, int len)
{
xad_t *xad;
s64 endofprev, endofcur;
s64 offset, xadlen;
int toread, startpos, endpos;
startpos = filepos;
endpos = filepos + len;
endofprev = (1ULL << 62) - 1;
xad = first_extent (inode);
do {
offset = offsetXAD (xad);
xadlen = lengthXAD (xad);
if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) {
endofcur = (offset + xadlen) << jfs.l2bsize;
toread = (endofcur >= endpos)
? len : (endofcur - filepos);
disk_read_func = disk_read_hook;
devread (addressXAD (xad) << jfs.bdlog,
filepos - (offset << jfs.l2bsize), toread, buf);
disk_read_func = NULL;
buf += toread;
len -= toread;
filepos += toread;
} else if (offset > endofprev) {
toread = ((offset << jfs.l2bsize) >= endpos)
? len : ((offset - endofprev) << jfs.l2bsize);
len -= toread;
filepos += toread;
for (; toread; toread--) {
*buf++ = 0;
}
continue;
}
endofprev = offset + xadlen;
xad = next_extent ();
} while (len > 0 && xad);
return filepos - startpos;
}
int
jfs_dir (char *dirname)
{
char *ptr, *rest, ch;
ldtentry_t *de;
dtslot_t *ds;
u32 inum, parent_inum;
s64 di_size;
u32 di_mode;
int namlen, cmp, n, link_count;
char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX];
parent_inum = inum = ROOT_I;
link_count = 0;
for (;;) {
di_read (inum, inode);
di_size = inode->di_size;
di_mode = inode->di_mode;
if ((di_mode & IFMT) == IFLNK) {
if (++link_count > MAX_LINK_COUNT) {
errnum = ERR_SYMLINK_LOOP;
return 0;
}
if (di_size < (di_mode & INLINEEA ? 256 : 128)) {
grub_memmove (linkbuf, inode->di_fastsymlink, di_size);
n = di_size;
} else if (di_size < JFS_PATH_MAX - 1) {
filepos = 0;
filemax = di_size;
n = jfs_read (linkbuf, filemax);
} else {
errnum = ERR_FILELENGTH;
return 0;
}
inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum;
while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++));
linkbuf[n] = 0;
dirname = linkbuf;
continue;
}
if (!*dirname || isspace (*dirname)) {
if ((di_mode & IFMT) != IFREG) {
errnum = ERR_BAD_FILETYPE;
return 0;
}
filepos = 0;
filemax = di_size;
return 1;
}
if ((di_mode & IFMT) != IFDIR) {
errnum = ERR_BAD_FILETYPE;
return 0;
}
for (; *dirname == '/'; dirname++);
for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
*rest = 0;
de = first_dentry ();
for (;;) {
namlen = de->namlen;
if (de->next == -1) {
uni2ansi (de->name, namebuf, namlen);
namebuf[namlen] = 0;
} else {
uni2ansi (de->name, namebuf, DTLHDRDATALEN);
ptr = namebuf;
ptr += DTLHDRDATALEN;
namlen -= DTLHDRDATALEN;
ds = next_dslot (de->next);
while (ds->next != -1) {
uni2ansi (ds->name, ptr, DTSLOTDATALEN);
ptr += DTSLOTDATALEN;
namlen -= DTSLOTDATALEN;
ds = next_dslot (ds->next);
}
uni2ansi (ds->name, ptr, namlen);
ptr += namlen;
*ptr = 0;
}
cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
#ifndef STAGE1_5
if (print_possibilities && ch != '/'
&& cmp <= 0) {
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
print_a_completion (namebuf);
} else
#endif
if (cmp == 0) {
parent_inum = inum;
inum = de->inumber;
*(dirname = rest) = ch;
break;
}
de = next_dentry ();
if (de == NULL) {
if (print_possibilities < 0)
return 1;
errnum = ERR_FILE_NOT_FOUND;
*rest = ch;
return 0;
}
}
}
}
int
jfs_embed (int *start_sector, int needed_sectors)
{
struct jfs_superblock super;
if (needed_sectors > 63
|| !devread (SUPER1_OFF >> SECTOR_BITS, 0,
sizeof (struct jfs_superblock),
(char *)&super)
|| (super.s_magic != JFS_MAGIC)) {
return 0;
}
*start_sector = 1;
return 1;
}
#endif /* FSYS_JFS */

View File

@ -1,534 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Restrictions:
This is MINIX V1 only (yet)
Disk creation is like:
mkfs.minix -c DEVICE
*/
#ifdef FSYS_MINIX
#include "shared.h"
#include "filesys.h"
/* #define DEBUG_MINIX */
/* indirect blocks */
static int mapblock1, mapblock2, namelen;
/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
#define DEV_BSIZE 512
/* include/linux/fs.h */
#define BLOCK_SIZE_BITS 10
#define BLOCK_SIZE (1<<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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,624 +0,0 @@
/* fsys_xfs.c - an implementation for the SGI XFS file system */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2001,2002 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_XFS
#include "shared.h"
#include "filesys.h"
#include "xfs.h"
#define MAX_LINK_COUNT 8
typedef struct xad {
xfs_fileoff_t offset;
xfs_fsblock_t start;
xfs_filblks_t len;
} xad_t;
struct xfs_info {
int bsize;
int dirbsize;
int isize;
unsigned int agblocks;
int bdlog;
int blklog;
int inopblog;
int agblklog;
int agnolog;
unsigned int nextents;
xfs_daddr_t next;
xfs_daddr_t daddr;
xfs_dablk_t forw;
xfs_dablk_t dablk;
xfs_bmbt_rec_32_t *xt;
xfs_bmbt_ptr_t ptr0;
int btnode_ptr0_off;
int i8param;
int dirpos;
int dirmax;
int blkoff;
int fpos;
xfs_ino_t rootino;
};
static struct xfs_info xfs;
#define dirbuf ((char *)FSYS_BUF)
#define filebuf ((char *)FSYS_BUF + 4096)
#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
#define icore (inode->di_core)
#define mask32lo(n) (((__uint32_t)1 << (n)) - 1)
#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1))
#define XFS_INO_OFFSET_BITS xfs.inopblog
#define XFS_INO_AGBNO_BITS xfs.agblklog
#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
#define XFS_INO_AGNO_BITS xfs.agnolog
static inline xfs_agblock_t
agino2agbno (xfs_agino_t agino)
{
return agino >> XFS_INO_OFFSET_BITS;
}
static inline xfs_agnumber_t
ino2agno (xfs_ino_t ino)
{
return ino >> XFS_INO_AGINO_BITS;
}
static inline xfs_agino_t
ino2agino (xfs_ino_t ino)
{
return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
}
static inline int
ino2offset (xfs_ino_t ino)
{
return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
}
static inline __const__ __uint16_t
le16 (__uint16_t x)
{
__asm__("xchgb %b0,%h0" \
: "=q" (x) \
: "0" (x)); \
return x;
}
static inline __const__ __uint32_t
le32 (__uint32_t x)
{
#if 0
/* 386 doesn't have bswap. */
__asm__("bswap %0" : "=r" (x) : "0" (x));
#else
/* This is slower but this works on all x86 architectures. */
__asm__("xchgb %b0, %h0" \
"\n\troll $16, %0" \
"\n\txchgb %b0, %h0" \
: "=q" (x) : "0" (x));
#endif
return x;
}
static inline __const__ __uint64_t
le64 (__uint64_t x)
{
__uint32_t h = x >> 32;
__uint32_t l = x & ((1ULL<<32)-1);
return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h)));
}
static xfs_fsblock_t
xt_start (xfs_bmbt_rec_32_t *r)
{
return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
(((xfs_fsblock_t)le32 (r->l2)) << 11) |
(((xfs_fsblock_t)le32 (r->l3)) >> 21);
}
static xfs_fileoff_t
xt_offset (xfs_bmbt_rec_32_t *r)
{
return (((xfs_fileoff_t)le32 (r->l0) &
mask32lo(31)) << 23) |
(((xfs_fileoff_t)le32 (r->l1)) >> 9);
}
static xfs_filblks_t
xt_len (xfs_bmbt_rec_32_t *r)
{
return le32(r->l3) & mask32lo(21);
}
static inline int
xfs_highbit32(__uint32_t v)
{
int i;
if (--v) {
for (i = 0; i < 31; i++, v >>= 1) {
if (v == 0)
return i;
}
}
return 0;
}
static int
isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
{
return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
}
static xfs_daddr_t
agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
{
return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
}
static xfs_daddr_t
fsb2daddr (xfs_fsblock_t fsbno)
{
return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
(xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
}
#undef offsetof
#define offsetof(t,m) ((int)&(((t *)0)->m))
static inline int
btroot_maxrecs (void)
{
int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
(sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
}
static int
di_read (xfs_ino_t ino)
{
xfs_agino_t agino;
xfs_agnumber_t agno;
xfs_agblock_t agbno;
xfs_daddr_t daddr;
int offset;
agno = ino2agno (ino);
agino = ino2agino (ino);
agbno = agino2agbno (agino);
offset = ino2offset (ino);
daddr = agb2daddr (agno, agbno);
devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
xfs.ptr0 = *(xfs_bmbt_ptr_t *)
(inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
return 1;
}
static void
init_extents (void)
{
xfs_bmbt_ptr_t ptr0;
xfs_btree_lblock_t h;
switch (icore.di_format) {
case XFS_DINODE_FMT_EXTENTS:
xfs.xt = inode->di_u.di_bmx;
xfs.nextents = le32 (icore.di_nextents);
break;
case XFS_DINODE_FMT_BTREE:
ptr0 = xfs.ptr0;
for (;;) {
xfs.daddr = fsb2daddr (le64(ptr0));
devread (xfs.daddr, 0,
sizeof(xfs_btree_lblock_t), (char *)&h);
if (!h.bb_level) {
xfs.nextents = le16(h.bb_numrecs);
xfs.next = fsb2daddr (le64(h.bb_rightsib));
xfs.fpos = sizeof(xfs_btree_block_t);
return;
}
devread (xfs.daddr, xfs.btnode_ptr0_off,
sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
}
}
}
static xad_t *
next_extent (void)
{
static xad_t xad;
switch (icore.di_format) {
case XFS_DINODE_FMT_EXTENTS:
if (xfs.nextents == 0)
return NULL;
break;
case XFS_DINODE_FMT_BTREE:
if (xfs.nextents == 0) {
xfs_btree_lblock_t h;
if (xfs.next == 0)
return NULL;
xfs.daddr = xfs.next;
devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
xfs.nextents = le16(h.bb_numrecs);
xfs.next = fsb2daddr (le64(h.bb_rightsib));
xfs.fpos = sizeof(xfs_btree_block_t);
}
/* Yeah, I know that's slow, but I really don't care */
devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
}
xad.offset = xt_offset (xfs.xt);
xad.start = xt_start (xfs.xt);
xad.len = xt_len (xfs.xt);
++xfs.xt;
--xfs.nextents;
return &xad;
}
/*
* Name lies - the function reads only first 100 bytes
*/
static void
xfs_dabread (void)
{
xad_t *xad;
xfs_fileoff_t offset;;
init_extents ();
while ((xad = next_extent ())) {
offset = xad->offset;
if (isinxt (xfs.dablk, offset, xad->len)) {
devread (fsb2daddr (xad->start + xfs.dablk - offset),
0, 100, dirbuf);
break;
}
}
}
static inline xfs_ino_t
sf_ino (char *sfe, int namelen)
{
void *p = sfe + namelen + 3;
return (xfs.i8param == 0)
? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p);
}
static inline xfs_ino_t
sf_parent_ino (void)
{
return (xfs.i8param == 0)
? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
: le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
}
static inline int
roundup8 (int n)
{
return ((n+7)&~7);
}
static char *
next_dentry (xfs_ino_t *ino)
{
int namelen = 1;
int toread;
static char *usual[2] = {".", ".."};
static xfs_dir2_sf_entry_t *sfe;
char *name = usual[0];
if (xfs.dirpos >= xfs.dirmax) {
if (xfs.forw == 0)
return NULL;
xfs.dablk = xfs.forw;
xfs_dabread ();
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
xfs.dirmax = le16 (h->count) - le16 (h->stale);
xfs.forw = le32 (h->info.forw);
#undef h
xfs.dirpos = 0;
}
switch (icore.di_format) {
case XFS_DINODE_FMT_LOCAL:
switch (xfs.dirpos) {
case -2:
*ino = 0;
break;
case -1:
*ino = sf_parent_ino ();
++name;
++namelen;
sfe = (xfs_dir2_sf_entry_t *)
(inode->di_u.di_c
+ sizeof(xfs_dir2_sf_hdr_t)
- xfs.i8param);
break;
default:
namelen = sfe->namelen;
*ino = sf_ino ((char *)sfe, namelen);
name = sfe->name;
sfe = (xfs_dir2_sf_entry_t *)
((char *)sfe + namelen + 11 - xfs.i8param);
}
break;
case XFS_DINODE_FMT_BTREE:
case XFS_DINODE_FMT_EXTENTS:
#define dau ((xfs_dir2_data_union_t *)dirbuf)
for (;;) {
if (xfs.blkoff >= xfs.dirbsize) {
xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
filepos &= ~(xfs.dirbsize - 1);
filepos |= xfs.blkoff;
}
xfs_read (dirbuf, 4);
xfs.blkoff += 4;
if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
toread = roundup8 (le16(dau->unused.length)) - 4;
xfs.blkoff += toread;
filepos += toread;
continue;
}
break;
}
xfs_read ((char *)dirbuf + 4, 5);
*ino = le64 (dau->entry.inumber);
namelen = dau->entry.namelen;
#undef dau
toread = roundup8 (namelen + 11) - 9;
xfs_read (dirbuf, toread);
name = (char *)dirbuf;
xfs.blkoff += toread + 5;
}
++xfs.dirpos;
name[namelen] = 0;
return name;
}
static char *
first_dentry (xfs_ino_t *ino)
{
xfs.forw = 0;
switch (icore.di_format) {
case XFS_DINODE_FMT_LOCAL:
xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
xfs.dirpos = -2;
break;
case XFS_DINODE_FMT_EXTENTS:
case XFS_DINODE_FMT_BTREE:
filepos = 0;
xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
#define tail ((xfs_dir2_block_tail_t *)dirbuf)
filepos = xfs.dirbsize - sizeof(*tail);
xfs_read (dirbuf, sizeof(*tail));
xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
#undef tail
} else {
xfs.dablk = (1ULL << 35) >> xfs.blklog;
#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
#define n ((xfs_da_intnode_t *)dirbuf)
for (;;) {
xfs_dabread ();
if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
|| (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
xfs.dirmax = le16 (h->count) - le16 (h->stale);
xfs.forw = le32 (h->info.forw);
break;
}
xfs.dablk = le32 (n->btree[0].before);
}
#undef n
#undef h
}
xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
filepos = xfs.blkoff;
xfs.dirpos = 0;
}
return next_dentry (ino);
}
int
xfs_mount (void)
{
xfs_sb_t super;
if (!devread (0, 0, sizeof(super), (char *)&super)
|| (le32(super.sb_magicnum) != XFS_SB_MAGIC)
|| ((le16(super.sb_versionnum)
& XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
return 0;
}
xfs.bsize = le32 (super.sb_blocksize);
xfs.blklog = super.sb_blocklog;
xfs.bdlog = xfs.blklog - SECTOR_BITS;
xfs.rootino = le64 (super.sb_rootino);
xfs.isize = le16 (super.sb_inodesize);
xfs.agblocks = le32 (super.sb_agblocks);
xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
xfs.inopblog = super.sb_inopblog;
xfs.agblklog = super.sb_agblklog;
xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
xfs.btnode_ptr0_off =
((xfs.bsize - sizeof(xfs_btree_block_t)) /
(sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
* sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
return 1;
}
int
xfs_read (char *buf, int len)
{
xad_t *xad;
xfs_fileoff_t endofprev, endofcur, offset;
xfs_filblks_t xadlen;
int toread, startpos, endpos;
if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
grub_memmove (buf, inode->di_u.di_c + filepos, len);
filepos += len;
return len;
}
startpos = filepos;
endpos = filepos + len;
endofprev = (xfs_fileoff_t)-1;
init_extents ();
while (len > 0 && (xad = next_extent ())) {
offset = xad->offset;
xadlen = xad->len;
if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
endofcur = (offset + xadlen) << xfs.blklog;
toread = (endofcur >= endpos)
? len : (endofcur - filepos);
disk_read_func = disk_read_hook;
devread (fsb2daddr (xad->start),
filepos - (offset << xfs.blklog), toread, buf);
disk_read_func = NULL;
buf += toread;
len -= toread;
filepos += toread;
} else if (offset > endofprev) {
toread = ((offset << xfs.blklog) >= endpos)
? len : ((offset - endofprev) << xfs.blklog);
len -= toread;
filepos += toread;
for (; toread; toread--) {
*buf++ = 0;
}
continue;
}
endofprev = offset + xadlen;
}
return filepos - startpos;
}
int
xfs_dir (char *dirname)
{
xfs_ino_t ino, parent_ino, new_ino;
xfs_fsize_t di_size;
int di_mode;
int cmp, n, link_count;
char linkbuf[xfs.bsize];
char *rest, *name, ch;
parent_ino = ino = xfs.rootino;
link_count = 0;
for (;;) {
di_read (ino);
di_size = le64 (icore.di_size);
di_mode = le16 (icore.di_mode);
if ((di_mode & IFMT) == IFLNK) {
if (++link_count > MAX_LINK_COUNT) {
errnum = ERR_SYMLINK_LOOP;
return 0;
}
if (di_size < xfs.bsize - 1) {
filepos = 0;
filemax = di_size;
n = xfs_read (linkbuf, filemax);
} else {
errnum = ERR_FILELENGTH;
return 0;
}
ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
linkbuf[n] = 0;
dirname = linkbuf;
continue;
}
if (!*dirname || isspace (*dirname)) {
if ((di_mode & IFMT) != IFREG) {
errnum = ERR_BAD_FILETYPE;
return 0;
}
filepos = 0;
filemax = di_size;
return 1;
}
if ((di_mode & IFMT) != IFDIR) {
errnum = ERR_BAD_FILETYPE;
return 0;
}
for (; *dirname == '/'; dirname++);
for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
*rest = 0;
name = first_dentry (&new_ino);
for (;;) {
cmp = (!*dirname) ? -1 : substring (dirname, name);
#ifndef STAGE1_5
if (print_possibilities && ch != '/' && cmp <= 0) {
if (print_possibilities > 0)
print_possibilities = -print_possibilities;
print_a_completion (name);
} else
#endif
if (cmp == 0) {
parent_ino = ino;
if (new_ino)
ino = new_ino;
*(dirname = rest) = ch;
break;
}
name = next_dentry (&new_ino);
if (name == NULL) {
if (print_possibilities < 0)
return 1;
errnum = ERR_FILE_NOT_FOUND;
*rest = ch;
return 0;
}
}
}
}
#endif /* FSYS_XFS */

View File

@ -1,168 +0,0 @@
/*
* 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_ */

View File

@ -1,601 +0,0 @@
/* 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_ */

View File

@ -1 +0,0 @@
/* Sorry, nothing is shared here ;) Just for GRUB compatibility. */

View File

@ -1,193 +0,0 @@
/* 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)
{
}

View File

@ -1,546 +0,0 @@
/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef _BITS_TYPES_H
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short __int16_t;
typedef unsigned short __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
typedef long long __int64_t;
typedef unsigned long long __uint64_t;
#endif
typedef __uint64_t xfs_ino_t;
typedef __uint32_t xfs_agino_t;
typedef __int64_t xfs_daddr_t;
typedef __int64_t xfs_off_t;
typedef __uint8_t uuid_t[16];
/* those are from xfs_types.h */
typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */
typedef __uint32_t xfs_extlen_t; /* extent length in blocks */
typedef __uint32_t xfs_agnumber_t; /* allocation group number */
typedef __int32_t xfs_extnum_t; /* # of extents in a file */
typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */
typedef __int64_t xfs_fsize_t; /* bytes in a file */
typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */
/*
* Disk based types:
*/
typedef __uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
typedef __uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
typedef __uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
typedef __uint64_t xfs_dfiloff_t; /* block number in a file */
typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
typedef __uint64_t xfs_fileoff_t; /* block number in a file */
typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */
/* those are from xfs_sb.h */
#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
#define XFS_SB_VERSION_NUMBITS 0x000f
typedef struct xfs_sb
{
__uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
__uint32_t sb_blocksize; /* logical block size, bytes */
xfs_drfsbno_t sb_dblocks; /* number of data blocks */
xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */
xfs_drtbno_t sb_rextents; /* number of realtime extents */
uuid_t sb_uuid; /* file system unique id */
xfs_dfsbno_t sb_logstart; /* starting block of log if internal */
xfs_ino_t sb_rootino; /* root inode number */
xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */
xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */
xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */
xfs_agblock_t sb_agblocks; /* size of an allocation group */
xfs_agnumber_t sb_agcount; /* number of allocation groups */
xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */
xfs_extlen_t sb_logblocks; /* number of log blocks */
__uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
__uint16_t sb_sectsize; /* volume sector size, bytes */
__uint16_t sb_inodesize; /* inode size, bytes */
__uint16_t sb_inopblock; /* inodes per block */
char sb_fname[12]; /* file system name */
__uint8_t sb_blocklog; /* log2 of sb_blocksize */
__uint8_t sb_sectlog; /* log2 of sb_sectsize */
__uint8_t sb_inodelog; /* log2 of sb_inodesize */
__uint8_t sb_inopblog; /* log2 of sb_inopblock */
__uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
__uint8_t sb_rextslog; /* log2 of sb_rextents */
__uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
__uint8_t sb_imax_pct; /* max % of fs for inode space */
/* statistics */
/*
* These fields must remain contiguous. If you really
* want to change their layout, make sure you fix the
* code in xfs_trans_apply_sb_deltas().
*/
__uint64_t sb_icount; /* allocated inodes */
__uint64_t sb_ifree; /* free inodes */
__uint64_t sb_fdblocks; /* free data blocks */
__uint64_t sb_frextents; /* free realtime extents */
/*
* End contiguous fields.
*/
xfs_ino_t sb_uquotino; /* user quota inode */
xfs_ino_t sb_gquotino; /* group quota inode */
__uint16_t sb_qflags; /* quota flags */
__uint8_t sb_flags; /* misc. flags */
__uint8_t sb_shared_vn; /* shared version number */
xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
__uint32_t sb_unit; /* stripe or raid unit */
__uint32_t sb_width; /* stripe or raid width */
__uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
__uint8_t sb_dummy[7]; /* padding */
} xfs_sb_t;
/* those are from xfs_btree.h */
/*
* Long form header: bmap btrees.
*/
typedef struct xfs_btree_lblock
{
__uint32_t bb_magic; /* magic number for block type */
__uint16_t bb_level; /* 0 is a leaf */
__uint16_t bb_numrecs; /* current # of data records */
xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
} xfs_btree_lblock_t;
/*
* Combined header and structure, used by common code.
*/
typedef struct xfs_btree_hdr
{
__uint32_t bb_magic; /* magic number for block type */
__uint16_t bb_level; /* 0 is a leaf */
__uint16_t bb_numrecs; /* current # of data records */
} xfs_btree_hdr_t;
typedef struct xfs_btree_block
{
xfs_btree_hdr_t bb_h; /* header */
union {
struct {
xfs_agblock_t bb_leftsib;
xfs_agblock_t bb_rightsib;
} s; /* short form pointers */
struct {
xfs_dfsbno_t bb_leftsib;
xfs_dfsbno_t bb_rightsib;
} l; /* long form pointers */
} bb_u; /* rest */
} xfs_btree_block_t;
/* those are from xfs_bmap_btree.h */
/*
* Bmap root header, on-disk form only.
*/
typedef struct xfs_bmdr_block
{
__uint16_t bb_level; /* 0 is a leaf */
__uint16_t bb_numrecs; /* current # of data records */
} xfs_bmdr_block_t;
/*
* Bmap btree record and extent descriptor.
* For 32-bit kernels,
* l0:31 is an extent flag (value 1 indicates non-normal).
* l0:0-30 and l1:9-31 are startoff.
* l1:0-8, l2:0-31, and l3:21-31 are startblock.
* l3:0-20 are blockcount.
* For 64-bit kernels,
* l0:63 is an extent flag (value 1 indicates non-normal).
* l0:9-62 are startoff.
* l0:0-8 and l1:21-63 are startblock.
* l1:0-20 are blockcount.
*/
#define BMBT_USE_64 1
typedef struct xfs_bmbt_rec_32
{
__uint32_t l0, l1, l2, l3;
} xfs_bmbt_rec_32_t;
typedef struct xfs_bmbt_rec_64
{
__uint64_t l0, l1;
} xfs_bmbt_rec_64_t;
#if BMBT_USE_64
typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
#else /* !BMBT_USE_64 */
typedef __uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
#endif /* BMBT_USE_64 */
/*
* Key structure for non-leaf levels of the tree.
*/
typedef struct xfs_bmbt_key
{
xfs_dfiloff_t br_startoff; /* starting file offset */
} xfs_bmbt_key_t, xfs_bmdr_key_t;
typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
/* btree block header type */
typedef struct xfs_btree_lblock xfs_bmbt_block_t;
/* those are from xfs_dir2.h */
/*
* Directory version 2.
* There are 4 possible formats:
* shortform
* single block - data with embedded leaf at the end
* multiple data blocks, single leaf+freeindex block
* data blocks, node&leaf blocks (btree), freeindex blocks
*
* The shortform format is in xfs_dir2_sf.h.
* The single block format is in xfs_dir2_block.h.
* The data block format is in xfs_dir2_data.h.
* The leaf and freeindex block formats are in xfs_dir2_leaf.h.
* Node blocks are the same as the other version, in xfs_da_btree.h.
*/
/*
* Byte offset in data block and shortform entry.
*/
typedef __uint16_t xfs_dir2_data_off_t;
/*
* Byte offset in a directory.
*/
typedef xfs_off_t xfs_dir2_off_t;
/* those are from xfs_da_btree.h */
/*========================================================================
* Directory Structure when greater than XFS_LBSIZE(mp) bytes.
*========================================================================*/
/*
* This structure is common to both leaf nodes and non-leaf nodes in the Btree.
*
* Is is used to manage a doubly linked list of all blocks at the same
* level in the Btree, and to identify which type of block this is.
*/
#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
typedef struct xfs_da_blkinfo {
xfs_dablk_t forw; /* previous block in list */
xfs_dablk_t back; /* following block in list */
__uint16_t magic; /* validity check on block */
__uint16_t pad; /* unused */
} xfs_da_blkinfo_t;
/*
* This is the structure of the root and intermediate nodes in the Btree.
* The leaf nodes are defined above.
*
* Entries are not packed.
*
* Since we have duplicate keys, use a binary search but always follow
* all match in the block, not just the first match found.
*/
typedef struct xfs_da_intnode {
struct xfs_da_node_hdr { /* constant-structure header block */
xfs_da_blkinfo_t info; /* block type, links, etc. */
__uint16_t count; /* count of active entries */
__uint16_t level; /* level above leaves (leaf == 0) */
} hdr;
struct xfs_da_node_entry {
xfs_dahash_t hashval; /* hash value for this descendant */
xfs_dablk_t before; /* Btree block before this key */
} btree[1]; /* variable sized array of keys */
} xfs_da_intnode_t;
/* those are from xfs_dir2_data.h */
/*
* Directory format 2, data block structures.
*/
/*
* Constants.
*/
#define XFS_DIR2_DATA_FREE_TAG 0xffff
#define XFS_DIR2_DATA_FD_COUNT 3
/*
* Structures.
*/
/*
* Describe a free area in the data block.
* The freespace will be formatted as a xfs_dir2_data_unused_t.
*/
typedef struct xfs_dir2_data_free {
xfs_dir2_data_off_t offset; /* start of freespace */
xfs_dir2_data_off_t length; /* length of freespace */
} xfs_dir2_data_free_t;
/*
* Header for the data blocks.
* Always at the beginning of a directory-sized block.
* The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
*/
typedef struct xfs_dir2_data_hdr {
__uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
/* or XFS_DIR2_BLOCK_MAGIC */
xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
} xfs_dir2_data_hdr_t;
/*
* Active entry in a data block. Aligned to 8 bytes.
* Tag appears as the last 2 bytes.
*/
typedef struct xfs_dir2_data_entry {
xfs_ino_t inumber; /* inode number */
__uint8_t namelen; /* name length */
__uint8_t name[1]; /* name bytes, no null */
/* variable offset */
xfs_dir2_data_off_t tag; /* starting offset of us */
} xfs_dir2_data_entry_t;
/*
* Unused entry in a data block. Aligned to 8 bytes.
* Tag appears as the last 2 bytes.
*/
typedef struct xfs_dir2_data_unused {
__uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
xfs_dir2_data_off_t length; /* total free length */
/* variable offset */
xfs_dir2_data_off_t tag; /* starting offset of us */
} xfs_dir2_data_unused_t;
typedef union {
xfs_dir2_data_entry_t entry;
xfs_dir2_data_unused_t unused;
} xfs_dir2_data_union_t;
/* those are from xfs_dir2_leaf.h */
/*
* Directory version 2, leaf block structures.
*/
/*
* Leaf block header.
*/
typedef struct xfs_dir2_leaf_hdr {
xfs_da_blkinfo_t info; /* header for da routines */
__uint16_t count; /* count of entries */
__uint16_t stale; /* count of stale entries */
} xfs_dir2_leaf_hdr_t;
/* those are from xfs_dir2_block.h */
/*
* xfs_dir2_block.h
* Directory version 2, single block format structures
*/
/*
* The single block format is as follows:
* xfs_dir2_data_hdr_t structure
* xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
* xfs_dir2_leaf_entry_t structures
* xfs_dir2_block_tail_t structure
*/
#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
typedef struct xfs_dir2_block_tail {
__uint32_t count; /* count of leaf entries */
__uint32_t stale; /* count of stale lf entries */
} xfs_dir2_block_tail_t;
/* those are from xfs_dir2_sf.h */
/*
* Directory layout when stored internal to an inode.
*
* Small directories are packed as tightly as possible so as to
* fit into the literal area of the inode.
*/
/*
* Inode number stored as 8 8-bit values.
*/
typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
/*
* Inode number stored as 4 8-bit values.
* Works a lot of the time, when all the inode numbers in a directory
* fit in 32 bits.
*/
typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
typedef union {
xfs_dir2_ino8_t i8;
xfs_dir2_ino4_t i4;
} xfs_dir2_inou_t;
/*
* Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
* Only need 16 bits, this is the byte offset into the single block form.
*/
typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t;
/*
* The parent directory has a dedicated field, and the self-pointer must
* be calculated on the fly.
*
* Entries are packed toward the top as tightly as possible. The header
* and the elements must be bcopy()'d out into a work area to get correct
* alignment for the inode number fields.
*/
typedef struct xfs_dir2_sf_hdr {
__uint8_t count; /* count of entries */
__uint8_t i8count; /* count of 8-byte inode #s */
xfs_dir2_inou_t parent; /* parent dir inode number */
} xfs_dir2_sf_hdr_t;
typedef struct xfs_dir2_sf_entry {
__uint8_t namelen; /* actual name length */
xfs_dir2_sf_off_t offset; /* saved offset */
__uint8_t name[1]; /* name, variable size */
xfs_dir2_inou_t inumber; /* inode number, var. offset */
} xfs_dir2_sf_entry_t;
typedef struct xfs_dir2_sf {
xfs_dir2_sf_hdr_t hdr; /* shortform header */
xfs_dir2_sf_entry_t list[1]; /* shortform entries */
} xfs_dir2_sf_t;
/* those are from xfs_dinode.h */
#define XFS_DINODE_VERSION_1 1
#define XFS_DINODE_VERSION_2 2
#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
/*
* Disk inode structure.
* This is just the header; the inode is expanded to fill a variable size
* with the last field expanding. It is split into the core and "other"
* because we only need the core part in the in-core inode.
*/
typedef struct xfs_timestamp {
__int32_t t_sec; /* timestamp seconds */
__int32_t t_nsec; /* timestamp nanoseconds */
} xfs_timestamp_t;
/*
* Note: Coordinate changes to this structure with the XFS_DI_* #defines
* below and the offsets table in xfs_ialloc_log_di().
*/
typedef struct xfs_dinode_core
{
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__uint16_t di_mode; /* mode and type of file */
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */
__uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
__uint16_t di_projid; /* owner's project id */
__uint8_t di_pad[10]; /* unused, zeroed space */
xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */
xfs_fsize_t di_size; /* number of bytes in file */
xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
xfs_extnum_t di_nextents; /* number of extents in data fork */
xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
__uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
__int8_t di_aformat; /* format of attr fork's data */
__uint32_t di_dmevmask; /* DMIG event mask */
__uint16_t di_dmstate; /* DMIG state info */
__uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
__uint32_t di_gen; /* generation number */
} xfs_dinode_core_t;
typedef struct xfs_dinode
{
xfs_dinode_core_t di_core;
xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
union {
xfs_bmdr_block_t di_bmbt; /* btree root block */
xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
char di_c[1]; /* local contents */
} di_u;
} xfs_dinode_t;
/*
* Values for di_format
*/
typedef enum xfs_dinode_fmt
{
XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
/* LNK: di_symlink */
XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
XFS_DINODE_FMT_UUID /* MNT: di_uuid */
} xfs_dinode_fmt_t;
/*
* File types (mode field)
*/
#define IFMT 0170000 /* type of file */
#define IFDIR 0040000 /* directory */
#define IFREG 0100000 /* regular */
#define IFLNK 0120000 /* symbolic link */

View File

@ -1,125 +0,0 @@
/*
* 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

View File

@ -1,50 +0,0 @@
#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 */

View File

@ -1,629 +0,0 @@
/*
* Linux/i386 loader
* Supports bzImage, zImage and Image format.
*
* Based on work by Steve Gehlbach.
* Portions are taken from mkelfImage.
*
* 2003-09 by SONE Takeshi
*/
#include <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)
end = max;
/* If "mem=" option is given, we have to put the initrd within
* the specified range. */
if (forced_memsize) {
forced = forced_memsize;
if (forced > max)
forced = max;
/* If the "mem=" is lower, it's easy */
if (forced <= end)
end = forced;
else {
/* Otherwise, see if we can put it above us */
if (virt_to_phys(_end) + size <= forced)
end = forced; /* Ok */
}
}
start = end - size;
start &= ~0xfff; /* page align */
end = start + size;
debug("start=%#x end=%#x\n", start, end);
if (start < kern_end) {
printf("Initrd is too big\n");
return -1;
}
printf("Loading initrd... ");
if (file_read(phys_to_virt(start), size) != size) {
printf("Can't read initrd\n");
return -1;
}
printf("ok\n");
params->initrd_start = start;
params->initrd_size = size;
return 0;
}
static void hardware_setup(void)
{
/* Disable nmi */
outb(0x80, 0x70);
/* Make sure any coprocessor is properly reset.. */
outb(0, 0xf0);
outb(0, 0xf1);
/* we're getting screwed again and again by this problem of the 8259.
* so we're going to leave this lying around for inclusion into
* crt0.S on an as-needed basis.
*
* well, that went ok, I hope. Now we have to reprogram the interrupts :-(
* we put them right after the intel-reserved hardware interrupts, at
* int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
* messed this up with the original PC, and they haven't been able to
* rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
* which is used for the internal hardware interrupts as well. We just
* have to reprogram the 8259's, and it isn't fun.
*/
outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
outb(0x11, 0xA0); /* and to 8259A-2 */
outb(0x20, 0x21); /* start of hardware int's (0x20) */
outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
outb(0x04, 0x21); /* 8259-1 is master */
outb(0x02, 0xA1); /* 8259-2 is slave */
outb(0x01, 0x21); /* 8086 mode for both */
outb(0x01, 0xA1);
outb(0xFF, 0xA1); /* mask off all interrupts for now */
outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
}
/* Start Linux */
static int start_linux(uint32_t kern_addr, struct linux_params *params)
{
struct segment_desc *linux_gdt;
struct context *ctx;
#if 0
extern int cursor_x, cursor_y;
#endif
ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
/* Linux expects GDT being in low memory */
linux_gdt = phys_to_virt(GDT_LOC);
memset(linux_gdt, 0, 13*sizeof(struct segment_desc));
/* Normal kernel code/data segments */
linux_gdt[2] = gdt[FLAT_CODE];
linux_gdt[3] = gdt[FLAT_DATA];
/* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible
* segments (2 and 3), so it SHOULD not be a problem.
* However, some distro kernels (eg. RH9) with backported threading
* patch use 12 and 13 also when booting... */
linux_gdt[12] = gdt[FLAT_CODE];
linux_gdt[13] = gdt[FLAT_DATA];
ctx->gdt_base = GDT_LOC;
ctx->gdt_limit = 14*8-1;
ctx->cs = 0x10;
ctx->ds = 0x18;
ctx->es = 0x18;
ctx->fs = 0x18;
ctx->gs = 0x18;
ctx->ss = 0x18;
/* Parameter location */
ctx->esi = virt_to_phys(params);
/* Entry point */
ctx->eip = kern_addr;
debug("eip=%#x\n", kern_addr);
printf("Jumping to entry point...\n");
#ifdef VGA_CONSOLE
/* Update VGA cursor position.
* This must be here because the printf changes the value! */
#if 0
params->orig_x = cursor_x;
params->orig_y = cursor_y;
#endif
#endif
/* Go... */
ctx = switch_to(ctx);
/* It's impossible but... */
printf("Returned with eax=%#x\n", ctx->eax);
return ctx->eax;
}
int linux_load(struct sys_info *info, const char *file, const char *cmdline)
{
struct linux_header hdr;
struct linux_params *params;
uint32_t kern_addr, kern_size;
char *initrd_file = 0;
if (!file_open(file))
return -1;
kern_addr = load_linux_header(&hdr);
if (kern_addr == 0)
return LOADER_NOT_SUPPORT;
params = phys_to_virt(LINUX_PARAM_LOC);
init_linux_params(params, &hdr);
set_memory_size(params, info);
initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
set_command_line_loc(params, &hdr);
kern_size = load_linux_kernel(&hdr, kern_addr);
if (kern_size == 0) {
if (initrd_file)
forget(initrd_file);
return -1;
}
if (initrd_file) {
if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file)
!= 0) {
forget(initrd_file);
return -1;
}
forget(initrd_file);
}
hardware_setup();
start_linux(kern_addr, params);
return 0;
}

View File

@ -1,129 +0,0 @@
/* Support for Multiboot */
#include <etherboot.h>
#include <lib.h>
#include <sys_info.h>
#include <arch/io.h>
#define DEBUG_THIS DEBUG_MULTIBOOT
#include <debug.h>
/* Multiboot header, gives information to loader */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MULTIBOOT_HEADER_FLAGS 0x00000003
struct mbheader {
unsigned int magic, flags, checksum;
};
const struct mbheader multiboot_header
__attribute__((section (".hdr"))) =
{
MULTIBOOT_HEADER_MAGIC,
MULTIBOOT_HEADER_FLAGS,
-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
};
/* Multiboot information structure, provided by loader to us */
struct multiboot_mmap {
unsigned entry_size;
unsigned base_lo, base_hi;
unsigned size_lo, size_hi;
unsigned type;
};
struct multiboot_info {
unsigned flags;
#define MULTIBOOT_MEM_VALID 0x01
#define MULTIBOOT_BOOT_DEV_VALID 0x02
#define MULTIBOOT_CMDLINE_VALID 0x04
#define MULTIBOOT_MODS_VALID 0x08
#define MULTIBOOT_AOUT_SYMS_VALID 0x10
#define MULTIBOOT_ELF_SYMS_VALID 0x20
#define MULTIBOOT_MMAP_VALID 0x40
unsigned mem_lower;
unsigned mem_upper;
unsigned char boot_device[4];
unsigned command_line;
unsigned mods_count;
unsigned mods_addr;
unsigned syms_num;
unsigned syms_size;
unsigned syms_addr;
unsigned syms_shndx;
unsigned mmap_length;
unsigned mmap_addr;
};
void collect_multiboot_info(struct sys_info *info)
{
struct multiboot_info *mbinfo;
struct multiboot_mmap *mbmem;
unsigned mbcount, mbaddr;
int i;
struct memrange *mmap;
int mmap_count;
if (info->boot_type != 0x2BADB002)
return;
debug("Using Multiboot information at %#lx\n", info->boot_data);
mbinfo = phys_to_virt(info->boot_data);
if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
/* convert mmap records */
mbmem = phys_to_virt(mbinfo->mmap_addr);
mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
mmap = malloc(mbcount * sizeof *mmap);
mmap_count = 0;
mbaddr = mbinfo->mmap_addr;
for (i = 0; i < mbcount; i++) {
mbmem = phys_to_virt(mbaddr);
debug("%08x%08x %08x%08x (%d)\n",
mbmem->base_hi,
mbmem->base_lo,
mbmem->size_hi,
mbmem->size_lo,
mbmem->type);
if (mbmem->type == 1) { /* Only normal RAM */
mmap[mmap_count].base = mbmem->base_lo
+ (((unsigned long long) mbmem->base_hi) << 32);
mmap[mmap_count].size = mbmem->size_lo
+ (((unsigned long long) mbmem->size_hi) << 32);
mmap_count++;
}
mbaddr += mbmem->entry_size + 4;
if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
break;
}
/* simple sanity check - there should be at least 2 RAM segments
* (base 640k and extended) */
if (mmap_count >= 2)
goto got_it;
printf("Multiboot mmap is broken\n");
free(mmap);
/* fall back to mem_lower/mem_upper */
}
if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
/* use mem_lower and mem_upper */
mmap_count = 2;
mmap = malloc(2 * sizeof(*mmap));
mmap[0].base = 0;
mmap[0].size = mbinfo->mem_lower << 10;
mmap[1].base = 1 << 20; /* 1MB */
mmap[1].size = mbinfo->mem_upper << 10;
goto got_it;
}
printf("Can't get memory information from Multiboot\n");
return;
got_it:
info->memrange = mmap;
info->n_memranges = mmap_count;
return;
}

View File

@ -1,48 +0,0 @@
/* Segmentation of the i386 architecture.
*
* 2003-07 by SONE Takeshi
*/
#include <etherboot.h>
//#include <lib.h>
#include <sys_info.h>
#include "segment.h"
#define DEBUG_THIS DEBUG_SEGMENT
#include <debug.h>
/* i386 lgdt argument */
struct gdtarg {
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* GDT, the global descriptor table */
struct segment_desc gdt[NUM_SEG] = {
/* 0x00: null segment */
{0, 0, 0, 0, 0, 0},
/* 0x08: flat code segment */
{0xffff, 0, 0, 0x9f, 0xcf, 0},
/* 0x10: flat data segment */
{0xffff, 0, 0, 0x93, 0xcf, 0},
/* 0x18: code segment for relocated execution */
{0xffff, 0, 0, 0x9f, 0xcf, 0},
/* 0x20: data segment for relocated execution */
{0xffff, 0, 0, 0x93, 0xcf, 0},
};
/* Copy GDT to new location and reload it */
void move_gdt(unsigned long newgdt)
{
struct gdtarg gdtarg;
debug("Moving GDT to %#lx...", newgdt);
memcpy(phys_to_virt(newgdt), gdt, sizeof gdt);
gdtarg.base = newgdt;
gdtarg.limit = GDT_LIMIT;
debug("reloading GDT...");
__asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
debug("reloading CS for fun...");
__asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS));
debug("ok\n");
}

View File

@ -1,29 +0,0 @@
/* Segment indexes. Must match the gdt definition in segment.c. */
enum {
NULL_SEG,
FLAT_CODE,
FLAT_DATA,
RELOC_CODE,
RELOC_DATA,
NUM_SEG,
};
/* Values for segment selector register */
#define FLAT_CS (FLAT_CODE << 3)
#define FLAT_DS (FLAT_DATA << 3)
#define RELOC_CS (RELOC_CODE << 3)
#define RELOC_DS (RELOC_DATA << 3)
/* i386 segment descriptor */
struct segment_desc {
unsigned short limit_0;
unsigned short base_0;
unsigned char base_16;
unsigned char types;
unsigned char flags;
unsigned char base_24;
};
extern struct segment_desc gdt[NUM_SEG];
#define GDT_LIMIT ((NUM_SEG << 3) - 1)

View File

@ -1,116 +0,0 @@
.globl entry, __switch_context, __exit_context, halt
.text
.align 4
/*
* Entry point
* We start execution from here.
* It is assumed that CPU is in 32-bit protected mode and
* all segments are 4GB and base zero (flat model).
*/
entry:
/* Save boot context and switch to our main context.
* Main context is statically defined in C.
*/
pushl %cs
call __switch_context
/* We get here when the main context switches back to
* the boot context.
* Return to previous bootloader.
*/
ret
/*
* Switch execution context
* This saves registers, segments, and GDT in the stack, then
* switches the stack, and restores everything from the new stack.
* This function takes no argument. New stack pointer is
* taken from global variable __context, and old stack pointer
* is also saved to __context. This way we can just jump to
* this routine to get back to the original context.
*
* Call this routine with lcall or pushl %cs; call.
*/
__switch_context:
/* Save everything in current stack */
pushfl /* 56 */
pushl %ds /* 52 */
pushl %es /* 48 */
pushl %fs /* 44 */
pushl %gs /* 40 */
pushal /* 8 */
subl $8, %esp
movw %ss, (%esp) /* 0 */
sgdt 2(%esp) /* 2 */
#if 0
/* Swap %cs and %eip on the stack, so lret will work */
movl 60(%esp), %eax
xchgl %eax, 64(%esp)
movl %eax, 60(%esp)
#endif
/* At this point we don't know if we are on flat segment
* or relocated. So compute the address offset from %eip.
* Assuming CS.base==DS.base==SS.base.
*/
call 1f
1: popl %ebx
subl $1b, %ebx
/* Interrupts are not allowed... */
cli
/* Current context pointer is our stack pointer */
movl %esp, %esi
/* Normalize the ctx pointer */
subl %ebx, %esi
/* Swap it with new value */
xchgl %esi, __context(%ebx)
/* Adjust new ctx pointer for current address offset */
addl %ebx, %esi
/* Load new %ss and %esp to temporary */
movzwl (%esi), %edx
movl 20(%esi), %eax
/* Load new GDT */
lgdt 2(%esi)
/* Load new stack segment with new GDT */
movl %edx, %ss
/* Set new stack pointer, but we have to adjust it because
* pushal saves %esp value before pushal, and we want the value
* after pushal.
*/
leal -32(%eax), %esp
/* Load the rest from new stack */
popal
popl %gs
popl %fs
popl %es
popl %ds
popfl
/* Finally, load new %cs and %eip */
lret
__exit_context:
/* Get back to the original context */
pushl %cs
call __switch_context
/* We get here if the other context attempt to switch to this
* dead context. This should not happen. */
halt:
cli
hlt
jmp halt

View File

@ -1,29 +0,0 @@
#include <etherboot.h>
#include <sys_info.h>
#include "context.h"
#define DEBUG_THIS DEBUG_SYS_INFO
#include <debug.h>
void collect_multiboot_info(struct sys_info *);
void collect_sys_info(struct sys_info *info)
{
/* Pick up paramters given by bootloader to us */
info->boot_type = boot_ctx->eax;
info->boot_data = boot_ctx->ebx;
info->boot_arg = boot_ctx->param[0];
debug("boot eax = %#lx\n", info->boot_type);
debug("boot ebx = %#lx\n", info->boot_data);
debug("boot arg = %#lx\n", info->boot_arg);
collect_elfboot_info(info);
collect_linuxbios_info(info);
#ifdef MULTIBOOT_IMAGE
collect_multiboot_info(info);
#endif
#if 0
debug("RAM %Ld MB\n", (meminfo.memsize + 512*1024) >> 20);
#endif
}

View File

@ -1,74 +0,0 @@
#include "etherboot.h"
#include <lib.h>
int getline(char *buf, int max)
{
int cur, ch, nonspace_seen;
cur = 0;
while (buf[cur]) {
putchar(buf[cur]);
cur++;
}
for (;;) {
ch = getchar();
switch (ch) {
/* end of line */
case '\r':
case '\n':
putchar('\n');
goto out;
/* backspace */
case '\b':
case '\x7f':
if (cur > 0) {
cur--;
putchar('\b');
putchar(' ');
putchar('\b');
}
break;
/* word erase */
case 'W' & 0x1f: /* ^W */
nonspace_seen = 0;
while (cur) {
if (buf[cur-1] != ' ')
nonspace_seen = 1;
putchar('\b');
putchar(' ');
putchar('\b');
cur--;
if (nonspace_seen && cur < max-1 && cur > 0 && buf[cur-1]==' ')
break;
}
break;
/* line erase */
case 'U' & 0x1f: /* ^U */
while (cur) {
putchar('\b');
putchar(' ');
putchar('\b');
cur--;
}
cur = 0;
break;
default:
if (ch < 0x20)
break; /* ignore control char */
if (ch >= 0x7f)
break;
if (cur + 1 < max) {
putchar(ch); /* echo back */
buf[cur] = ch;
cur++;
}
}
}
out:
if (cur >= max)
cur = max - 1;
buf[cur] = '\0';
return cur;
}

View File

@ -1,398 +0,0 @@
/* ELF Boot loader
* As we have seek, this implementation can be straightforward.
* 2003-07 by SONE Takeshi
*/
#include <etherboot.h>
#include <elf.h>
#include <bits/elf_x.h>
#include <elf_boot.h>
#include <lib.h>
#include <sys_info.h>
#include <fs.h>
#define DEBUG_THIS DEBUG_ELFBOOT
#include <debug.h>
#if 1
//Use that in Etherboot
extern int elf_start(unsigned long __unused_i386, unsigned long entry, unsigned long param);
#define start_elf(x,y) elf_start(0, x, y)
#else
// original in filo
extern unsigned int start_elf(unsigned long entry_point, unsigned long param);
#endif
extern char _virt_start[], _end[];
static char *image_name, *image_version;
static int check_mem_ranges(struct sys_info *info,
Elf_phdr *phdr, int phnum)
{
int i, j;
unsigned long start, end;
unsigned long prog_start, prog_end;
#if 0
struct memrange *mem;
#else
struct e820entry *mem;
#endif
prog_start = virt_to_phys(&_virt_start);
prog_end = virt_to_phys(&_end);
for (i = 0; i < phnum; i++) {
if (phdr[i].p_type != PT_LOAD)
continue;
start = phdr[i].p_paddr;
end = start + phdr[i].p_memsz;
if (start < prog_start && end > prog_start)
goto conflict;
if (start < prog_end && end > prog_end)
goto conflict;
#if 0
for (j = 0; j < info->n_memranges; j++) {
mem = &info->memrange[j];
if (mem->base <= start && mem->base + mem->size >= end)
break;
}
if (j >= info->n_memranges)
goto badseg;
#else
#define LB_MEM_RAM 1
for (j = 0; j < meminfo.map_count; j++) {
mem = &meminfo.map[j];
if (mem->type!=LB_MEM_RAM) continue;
if (mem->addr <= start && mem->addr + mem->size >= end)
break;
}
if (j >= meminfo.map_count)
goto badseg;
#endif
}
return 1;
conflict:
printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
badseg:
printf("Segment %d [%#lx-%#lx] doesn't fit into memory\n", i, start, end-1);
return 0;
}
static unsigned long process_image_notes(Elf_phdr *phdr, int phnum,
unsigned short *sum_ptr)
{
int i;
char *buf = NULL;
int retval = 0;
unsigned long addr, end;
Elf_Nhdr *nhdr;
const char *name;
void *desc;
for (i = 0; i < phnum; i++) {
if (phdr[i].p_type != PT_NOTE)
continue;
buf = allot(phdr[i].p_filesz);
file_seek(phdr[i].p_offset);
if (file_read(buf, phdr[i].p_filesz) != phdr[i].p_filesz) {
printf("Can't read note segment\n");
goto out;
}
addr = (unsigned long) buf;
end = addr + phdr[i].p_filesz;
while (addr < end) {
nhdr = (Elf_Nhdr *) addr;
addr += sizeof(Elf_Nhdr);
name = (const char *) addr;
addr += (nhdr->n_namesz+3) & ~3;
desc = (void *) addr;
addr += (nhdr->n_descsz+3) & ~3;
if (nhdr->n_namesz==sizeof(ELF_NOTE_BOOT)
&& memcmp(name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT))==0) {
if (nhdr->n_type == EIN_PROGRAM_NAME) {
image_name = calloc(1, nhdr->n_descsz + 1);
memcpy(image_name, desc, nhdr->n_descsz);
}
if (nhdr->n_type == EIN_PROGRAM_VERSION) {
image_version = calloc(1, nhdr->n_descsz + 1);
memcpy(image_version, desc, nhdr->n_descsz);
}
if (nhdr->n_type == EIN_PROGRAM_CHECKSUM) {
*sum_ptr = *(unsigned short *) desc;
debug("Image checksum: %04x\n", *sum_ptr);
/* Where in the file */
retval = phdr[i].p_offset
+ (unsigned long) desc - (unsigned long) buf;
}
}
}
}
out:
if (buf)
forget(buf);
return retval;
}
static int load_segments(Elf_phdr *phdr, int phnum,
unsigned long checksum_offset)
{
unsigned long bytes;
unsigned int start_time, time;
int i;
int j;
bytes = 0;
start_time = currticks();
#if 0
for (j = 0; j < phnum; j++) {
if (phdr[j].p_type != PT_LOAD)
continue;
debug("0 segment %d addr:%#x file:%#x mem:%#x, phdr%#x\n",
j, phdr[j].p_paddr, phdr[j].p_filesz, phdr[j].p_memsz, virt_to_phys(&phdr[j]));
}
#endif
for (i = 0; i < phnum; i++) {
if (phdr[i].p_type != PT_LOAD)
continue;
debug("segment %d addr:%#x file:%#x mem:%#x phdr:%#x ",
i, phdr[i].p_paddr, phdr[i].p_filesz, phdr[i].p_memsz, virt_to_phys(&phdr[i]));
file_seek(phdr[i].p_offset);
debug("loading... ");
if (file_read(phys_to_virt(phdr[i].p_paddr), phdr[i].p_filesz)
!= phdr[i].p_filesz) {
printf("Can't read program segment %d\n", i);
return 0;
}
bytes += phdr[i].p_filesz;
debug("clearing... ");
memset(phys_to_virt(phdr[i].p_paddr + phdr[i].p_filesz), 0,
phdr[i].p_memsz - phdr[i].p_filesz);
if (phdr[i].p_offset <= checksum_offset
&& phdr[i].p_offset + phdr[i].p_filesz >= checksum_offset+2) {
debug("clearing checksum... ");
memset(phys_to_virt(phdr[i].p_paddr + checksum_offset
- phdr[i].p_offset), 0, 2);
}
debug("ok\n");
}
time = (currticks() - start_time)*1000/18;
printf("Loaded %d bytes in %dms (%dKB/s)\n", bytes, time,
time? bytes/time : 0);
return 1;
}
static int verify_image(Elf_ehdr *ehdr, Elf_phdr *phdr, int phnum,
unsigned short image_sum)
{
unsigned short sum, part_sum;
unsigned long offset;
int i;
sum = 0;
offset = 0;
part_sum = ipchksum(ehdr, sizeof *ehdr);
sum = add_ipchksums(offset, sum, part_sum);
offset += sizeof *ehdr;
part_sum = ipchksum(phdr, phnum * sizeof(*phdr));
sum = add_ipchksums(offset, sum, part_sum);
offset += phnum * sizeof(*phdr);
for (i = 0; i < phnum; i++) {
if (phdr[i].p_type != PT_LOAD)
continue;
part_sum = ipchksum(phys_to_virt(phdr[i].p_paddr), phdr[i].p_memsz);
sum = add_ipchksums(offset, sum, part_sum);
offset += phdr[i].p_memsz;
}
if (sum != image_sum) {
printf("Verify FAILED (image:%04x vs computed:%04x)\n",
image_sum, sum);
return 0;
}
return 1;
}
static inline unsigned const padded(unsigned s)
{
return (s + 3) & ~3;
}
static Elf_Bhdr *add_boot_note(Elf_Bhdr *bhdr, const char *name,
unsigned type, const char *desc, unsigned descsz)
{
Elf_Nhdr nhdr;
unsigned ent_size, new_size, pad;
char *addr;
if (!bhdr)
return NULL;
nhdr.n_namesz = name? strlen(name)+1 : 0;
nhdr.n_descsz = descsz;
nhdr.n_type = type;
ent_size = sizeof(nhdr) + padded(nhdr.n_namesz) + padded(nhdr.n_descsz);
if (bhdr->b_size + ent_size > 0xffff) {
printf("Boot notes too big\n");
forget(bhdr);
return NULL;
}
if (bhdr->b_size + ent_size > bhdr->b_checksum) {
do {
new_size = bhdr->b_checksum * 2;
} while (new_size < bhdr->b_size + ent_size);
if (new_size > 0xffff)
new_size = 0xffff;
debug("expanding boot note size to %u\n", new_size);
bhdr = realloc(bhdr, new_size);
bhdr->b_checksum = new_size;
}
addr = (char *) bhdr;
addr += bhdr->b_size;
memcpy(addr, &nhdr, sizeof(nhdr));
addr += sizeof(nhdr);
memcpy(addr, name, nhdr.n_namesz);
addr += nhdr.n_namesz;
pad = padded(nhdr.n_namesz) - nhdr.n_namesz;
memset(addr, 0, pad);
addr += pad;
memcpy(addr, desc, nhdr.n_descsz);
addr += nhdr.n_descsz;
pad = padded(nhdr.n_descsz) - nhdr.n_descsz;
memset(addr, 0, pad);
addr += pad;
bhdr->b_size += ent_size;
bhdr->b_records++;
return bhdr;
}
static inline Elf_Bhdr *add_note_string(Elf_Bhdr *bhdr, const char *name,
unsigned type, const char *desc)
{
return add_boot_note(bhdr, name, type, desc, strlen(desc) + 1);
}
static Elf_Bhdr *build_boot_notes(struct sys_info *info, const char *cmdline)
{
Elf_Bhdr *bhdr;
bhdr = allot(256);
bhdr->b_signature = ELF_BHDR_MAGIC;
bhdr->b_size = sizeof *bhdr;
bhdr->b_checksum = 256; /* XXX cache the current buffer size here */
bhdr->b_records = 0;
if (info->firmware)
bhdr = add_note_string(bhdr, NULL, EBN_FIRMWARE_TYPE, info->firmware);
bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_NAME, program_name);
bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_VERSION, program_version);
if (cmdline)
bhdr = add_note_string(bhdr, NULL, EBN_COMMAND_LINE, cmdline);
if (!bhdr)
return bhdr;
bhdr->b_checksum = 0;
bhdr->b_checksum = ipchksum(bhdr, bhdr->b_size);
return bhdr;
}
int elf_load(struct sys_info *info, const char *filename, const char *cmdline)
{
Elf_ehdr ehdr;
Elf_phdr *phdr = NULL;
unsigned long phdr_size;
unsigned long checksum_offset;
unsigned short checksum;
Elf_Bhdr *boot_notes = NULL;
int retval = -1;
int image_retval;
image_name = image_version = 0;
if (!file_open(filename))
goto out;
if (file_read(&ehdr, sizeof ehdr) != sizeof ehdr) {
debug("Can't read ELF header\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_CLASS] != ARCH_ELF_CLASS
|| ehdr.e_ident[EI_DATA] != ARCH_ELF_DATA
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_type != ET_EXEC
|| !ARCH_ELF_MACHINE_OK(ehdr.e_machine)
|| ehdr.e_version != EV_CURRENT
|| ehdr.e_phentsize != sizeof(Elf_phdr)) {
debug("Not a bootable ELF image\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
phdr_size = ehdr.e_phnum * sizeof *phdr;
phdr = allot(phdr_size);//hack LYH otherwise some one clear the last entry
file_seek(ehdr.e_phoff);
if (file_read(phdr, phdr_size) != phdr_size) {
printf("Can't read program header\n");
goto out;
}
if (!check_mem_ranges(info, phdr, ehdr.e_phnum))
goto out;
checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum);
printf("Loading %s", image_name ? image_name : "image");
if (image_version)
printf(" version %s", image_version);
printf("...\n");
if (!load_segments(phdr, ehdr.e_phnum, checksum_offset))
goto out;
if (checksum_offset) {
if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum))
goto out;
}
boot_notes = build_boot_notes(info, cmdline);
debug("current time: %x\n", currticks());
debug("entry point is %#x\n", ehdr.e_entry);
printf("Jumping to entry point...\n");
image_retval = start_elf(ehdr.e_entry, virt_to_phys(boot_notes));
#if 0
console_init();
#endif
printf("Image returned with return value %#x\n", image_retval);
retval = 0;
out:
if (phdr)
forget(phdr);
if (boot_notes)
forget(boot_notes);
if (image_name)
forget(image_name);
if (image_version)
forget(image_version);
return retval;
}

View File

@ -1,153 +0,0 @@
/* Support for ELF Boot Proposal as a boot image */
#include <etherboot.h>
#include <elf_boot.h>
#include <sys_info.h>
#include <lib.h>
#include "version.h"
#define DEBUG_THIS DEBUG_ELFNOTE
#include <debug.h>
/* ELF image notes provide information to the loader who boots us */
/* This compiles and generates correct PT_NOTE segment for me.
* If it doesn't, use assembly version below. */
struct elf_image_note {
Elf_Nhdr hdr0;
char name0[sizeof(ELF_NOTE_BOOT)];
char prog_name[sizeof(PROGRAM_NAME)];
Elf_Nhdr hdr1;
char name1[sizeof(ELF_NOTE_BOOT)];
char version[sizeof(PROGRAM_VERSION)];
Elf_Nhdr hdr2;
char name2[sizeof(ELF_NOTE_BOOT)];
unsigned short checksum;
};
const struct elf_image_note elf_image_notes
__attribute__ ((section (".note.ELFBoot"))) =
{
.hdr0 = {
.n_namesz = sizeof(ELF_NOTE_BOOT),
.n_descsz = sizeof(PROGRAM_NAME),
.n_type = EIN_PROGRAM_NAME,
},
.name0 = ELF_NOTE_BOOT,
.prog_name = PROGRAM_NAME,
.hdr1 = {
.n_namesz = sizeof(ELF_NOTE_BOOT),
.n_descsz = sizeof(PROGRAM_VERSION),
.n_type = EIN_PROGRAM_VERSION,
},
.name1 = ELF_NOTE_BOOT,
.version = PROGRAM_VERSION,
.hdr2 = {
.n_namesz = sizeof(ELF_NOTE_BOOT),
.n_descsz = sizeof(unsigned short),
.n_type = EIN_PROGRAM_CHECKSUM,
},
.name2 = ELF_NOTE_BOOT,
.checksum = 0, /* to be computed by external tool */
};
/* This is refered by other files */
const char *program_name = elf_image_notes.prog_name;
const char *program_version = elf_image_notes.version;
#if 0
/* This tells the linker to make a PT_NOTE segment.
* If the section is named just ".note", it will be
* mixed up with useless .version notes generated by GCC.
*/
.section ".note.ELFBoot", "a"
.align 4
.int 2f - 1f
.int 4f - 3f
.int EIN_PROGRAM_NAME
1: .asciz "ELFBoot"
2: .align 4
3: .asciz PROGRAM_NAME
4:
.align 4
.int 2f - 1f
.int 4f - 3f
.int EIN_PROGRAM_VERSION
1: .asciz "ELFBoot"
2: .align 4
3: .asciz PROGRAM_VERSION
4:
.align 4
.int 2f - 1f
.int 4f - 3f
.int EIN_PROGRAM_CHECKSUM
1: .asciz "ELFBoot"
2: .align 4
3: .short 0
4:
#endif
/* Collect information from the ELF bootloader
* Note that we have to copy them to our own memory,
* otherwise they might be overwritten afterward. */
void collect_elfboot_info(struct sys_info *info)
{
Elf_Bhdr *hdr = 0;
char *addr, *end;
Elf_Nhdr *nhdr;
char *name, *desc;
if (info->boot_type == ELF_BHDR_MAGIC)
hdr = phys_to_virt(info->boot_data);
else
hdr = phys_to_virt(info->boot_arg);
if (hdr->b_signature != ELF_BHDR_MAGIC)
return;
if (ipchksum(hdr, hdr->b_size) != 0) {
printf("Broken ELF boot notes\n");
return;
}
addr = (char *) (hdr + 1);
end = addr + hdr->b_size;
while (addr < end) {
nhdr = (Elf_Nhdr *) addr;
addr += sizeof(Elf_Nhdr);
name = addr;
addr += (nhdr->n_namesz + 3) & ~3;
desc = addr;
addr += (nhdr->n_descsz + 3) & ~3;
if (nhdr->n_namesz == 0) {
/* Standard notes */
switch (nhdr->n_type) {
case EBN_FIRMWARE_TYPE:
info->firmware = strdup(desc);
break;
case EBN_BOOTLOADER_NAME:
debug("Bootloader: %s\n", desc);
break;
case EBN_BOOTLOADER_VERSION:
debug("Version: %s\n", desc);
break;
case EBN_COMMAND_LINE:
info->command_line = strdup(desc);
break;
case EBN_LOADED_IMAGE:
debug("Image name: %s\n", desc);
break;
}
}
}
}

View File

@ -1,129 +0,0 @@
#include <etherboot.h>
#include <fs.h>
#include <lib.h>
#include <sys_info.h>
#define ENTER '\r'
#define ESCAPE '\x1b'
#ifndef AUTOBOOT_FILE
#define autoboot() ((void) 0) /* nop */
#endif
#ifndef AUTOBOOT_DELAY
#define autoboot_delay() 0 /* success */
#endif
struct sys_info sys_info;
static void init(void)
{
collect_sys_info(&sys_info);
printf("%s version %s\n", program_name, program_version);
}
static void boot(const char *line)
{
char file[256], *param;
/* Split filename and parameter */
memcpy(file, line,256);
// file = strdup(line);
param = strchr(file, ' ');
if (param) {
*param = '\0';
param++;
}
if (elf_load(&sys_info, file, param) == LOADER_NOT_SUPPORT){
if (linux_load(&sys_info, file, param) == LOADER_NOT_SUPPORT)
printf("Unsupported image format\n");
}
// free(file);
}
#ifdef AUTOBOOT_FILE
#if AUTOBOOT_DELAY
static inline int autoboot_delay(void)
{
unsigned int timeout;
int sec, tmp;
int key;
key = 0;
printf("Press <Enter> for default boot, or <Esc> for boot prompt... ");
for (sec = AUTOBOOT_DELAY; sec>0 && key==0; sec--) {
printf("%d", sec);
timeout = currticks() + TICKS_PER_SEC;
while (currticks() < timeout) {
if (iskey()) {
key = getchar();
if (key==ENTER || key==ESCAPE)
break;
}
}
for (tmp = sec; tmp; tmp /= 10)
printf("\b \b");
}
if (key == 0) {
printf("timed out\n");
return 0; /* success */
} else {
putchar('\n');
if (key == ESCAPE)
return -1; /* canceled */
else
return 0; /* default accepted */
}
}
#endif /* AUTOBOOT_DELAY */
static void autoboot(void)
{
/* If Escape key is pressed already, skip autoboot */
if (iskey() && getchar()==ESCAPE)
return;
if (autoboot_delay()==0) {
printf("boot: %s\n", AUTOBOOT_FILE);
boot(AUTOBOOT_FILE);
}
}
#endif /* AUTOBOOT_FILE */
/* The main routine */
int filo(void)
{
char line[256];
/* Initialize */
init();
/* Try default image */
autoboot();
/* The above didn't work, ask user */
while (iskey())
getchar();
#ifdef AUTOBOOT_FILE
strncpy(line, AUTOBOOT_FILE, sizeof(line)-1);
line[sizeof(line)-1] = '\0';
#else
line[0] = '\0';
#endif
for (;;) {
printf("boot: ");
getline(line, sizeof line);
// BY LYH add "quit" to exit filo
if (strcmp(line,"quit")==0) break;
// if (memcmp(line,"quit",4)==0) break;
if (line[0])
boot(line);
}
return 0;
}

View File

@ -1,56 +0,0 @@
#include <etherboot.h>
#include <lib.h>
char *strdup(const char *s)
{
size_t sz = strlen(s) + 1;
char *d = allot(sz);
memcpy(d, s, sz);
return d;
}
int isspace(int c)
{
switch (c) {
case ' ': case '\f': case '\n':
case '\r': case '\t': case '\v':
return 1;
default:
return 0;
}
}
unsigned int get_le32(const unsigned char *p)
{
return ((unsigned int) p[0] << 0)
| ((unsigned int) p[1] << 8)
| ((unsigned int) p[2] << 16)
| ((unsigned int) p[3] << 24);
}
unsigned int get_le16(const unsigned char *p)
{
return ((unsigned int) p[0] << 0)
| ((unsigned int) p[1] << 8);
}
#if (DEBUG_ALL || DEBUG_ELFBOOT || DEBUG_ELFNOTE || DEBUG_LINUXBIOS || \
DEBUG_MALLOC || DEBUG_MULTIBOOT || DEBUG_SEGMENT || DEBUG_SYS_INFO ||\
DEBUG_TIMER || DEBUG_BLOCKDEV || DEBUG_PCI || DEBUG_LINUXLOAD ||\
DEBUG_IDE || DEBUG_ELTORITO)
// It is needed by debug for filo
void hexdump(const void *p, unsigned int len)
{
int i;
const unsigned char *q = p;
for (i = 0; i < len; i++) {
if (i%16==0)
printf("%04x: ", i);
printf("%02x%c", q[i], i%16==15 ? '\n' : i%8==7 ? '-' : ' ');
}
if (i%16 != 0)
putchar('\n');
}
#endif

View File

@ -1,124 +0,0 @@
/* Adapted from Etherboot 5.1.8 */
#include <sys_info.h>
#define DEBUG_THIS DEBUG_LINUXBIOS
#include <debug.h>
#if 0
#define for_each_lbrec(head, rec) \
for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \
(((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \
(rec->size >= 1) && \
((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \
rec = (struct lb_record *)(((char *)rec) + rec->size))
static void convert_memmap(struct lb_memory *lbmem, struct sys_info *info)
{
int lbcount;
int i;
lbcount = lbmem->size / sizeof(struct lb_memory_range);
info->memrange = malloc(lbcount * sizeof(struct memrange));
info->n_memranges = 0;
for (i = 0; i < lbcount; i++) {
debug("%#016Lx %#016Lx %d\n",
lbmem->map[i].start, lbmem->map[i].size,
(int) lbmem->map[i].type);
if (lbmem->map[i].type != LB_MEM_RAM)
continue;
info->memrange[info->n_memranges].base = lbmem->map[i].start;
info->memrange[info->n_memranges].size = lbmem->map[i].size;
info->n_memranges++;
}
}
static int read_lbtable(struct lb_header *head, struct sys_info *info)
{
int retval = 0;
/* Read linuxbios tables... */
struct lb_record *rec;
for_each_lbrec(head, rec) {
switch(rec->tag) {
case LB_TAG_MEMORY:
convert_memmap((struct lb_memory *) rec, info);
retval = 1;
break;
};
}
return retval;
}
#endif
#if 0
//Use func in Etherboot
static unsigned long count_lb_records(void *start, unsigned long length)
{
struct lb_record *rec;
void *end;
unsigned long count;
count = 0;
end = ((char *)start) + length;
for(rec = start; ((void *)rec < end) &&
((signed long)rec->size <= (end - (void *)rec));
rec = (void *)(((char *)rec) + rec->size)) {
count++;
}
return count;
}
static int find_lb_table(void *start, void *end, struct lb_header **result)
{
unsigned char *ptr;
/* For now be stupid.... */
for(ptr = start; (void *)ptr < end; ptr += 16) {
struct lb_header *head = (struct lb_header *)ptr;
if ( (head->signature[0] != 'L') ||
(head->signature[1] != 'B') ||
(head->signature[2] != 'I') ||
(head->signature[3] != 'O')) {
continue;
}
if (head->header_bytes != sizeof(*head))
continue;
debug("Found canidate at: %p\n", head);
if (ipchksum((uint16_t *)head, sizeof(*head)) != 0)
continue;
debug("header checksum o.k.\n");
if (ipchksum((uint16_t *)(ptr + sizeof(*head)), head->table_bytes) !=
head->table_checksum) {
continue;
}
debug("table checksum o.k.\n");
if (count_lb_records(ptr + sizeof(*head), head->table_bytes) !=
head->table_entries) {
continue;
}
debug("record count o.k.\n");
*result = head;
return 1;
};
return 0;
}
#endif
void collect_linuxbios_info(struct sys_info *info)
{
#if 0
struct lb_header *lb_table;
int found;
debug("Searching for LinuxBIOS tables...\n");
found = 0;
if (!found) {
found = find_lb_table(phys_to_virt(0x00000), phys_to_virt(0x01000), &lb_table);
}
if (!found) {
found = find_lb_table(phys_to_virt(0xf0000), phys_to_virt(0x100000), &lb_table);
}
if (!found)
return;
debug("Found LinuxBIOS table at: %p\n", lb_table);
#endif
info->firmware = "LinuxBIOS";
#if 0
read_lbtable(lb_table, info);
#endif
}

View File

@ -1,45 +0,0 @@
#include <etherboot.h>
#include <lib.h>
void *calloc(size_t nmemb, size_t size)
{
size_t alloc_size = nmemb * size;
void *mem;
if (alloc_size < nmemb || alloc_size < size) {
printf("calloc overflow: %u, %u\n", nmemb, size);
return 0;
}
mem = allot(alloc_size);
memset(mem, 0, alloc_size);
return mem;
}
void *realloc(void *mem, size_t size)
{
size_t copy_size;
void *new_mem;
size_t *mark, addr;
if (mem == 0)
return allot(size);
if (size == 0) {
forget(mem);
return 0;
}
addr = virt_to_phys(mem);
mark = phys_to_virt(addr - sizeof(size_t));
copy_size = *mark;
if (size < copy_size)
copy_size = size;
/* XXX should optimze this */
new_mem = allot(size);
memcpy(new_mem, mem, copy_size);
forget(mem);
return new_mem;
}

View File

@ -1,124 +0,0 @@
#ifdef CONFIG_PCI
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*/
#include <etherboot.h>
#include <pci.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_PCI
#include <debug.h>
struct pci_device *dev_list;
int n_devs;
static void pci_scan_bus(void)
{
unsigned int first_bus, first_devfn;
unsigned int devfn, bus, buses;
uint32_t class;
uint16_t vendor, dev_id;
uint8_t hdr_type;
first_bus = 0;
first_devfn = 0;
buses=256;
for (bus = first_bus; bus < buses; ++bus) {
for (devfn = first_devfn; devfn < 0xff; ++devfn) {
#if 1
if (PCI_FUNC(devfn) == 0)
pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
else if (!(hdr_type & 0x80)) /* not a multi-function device */
continue;
#endif
pcibios_read_config_word(bus,devfn, PCI_VENDOR_ID, &vendor);
if (vendor==0xffff || vendor==0)
continue;
if (dev_list) {
dev_list[n_devs].bus = bus;
dev_list[n_devs].devfn = devfn;
dev_list[n_devs].vendor = vendor;
pcibios_read_config_word(bus,devfn, PCI_DEVICE_ID, &dev_id);
dev_list[n_devs].dev_id = dev_id;
pcibios_read_config_dword(bus,devfn, PCI_CLASS_REVISION, &class);
dev_list[n_devs].class = class;
}
n_devs++;
}
first_devfn = 0;
}
first_bus = 0;
}
#define DEBUG 0
void pci_init(void)
{
/* Count devices */
dev_list = 0;
n_devs = 0;
debug("Scanning PCI: ");
pci_scan_bus();
debug("found %d devices\n", n_devs);
/* Make the list */
dev_list = allot(n_devs * sizeof(struct pci_device));
n_devs = 0;
pci_scan_bus();
#if DEBUG
{
int i;
for (i = 0; i < n_devs; i++) {
printf("%02x:%02x.%x %04x:%04x %04x %02x\n",
dev_list[i].bus,
PCI_SLOT(dev_list[i].devfn),
PCI_FUNC(dev_list[i].devfn),
dev_list[i].vendor,
dev_list[i].dev_id,((dev_list[i].class)>>16),
((dev_list[i].class)>>8 & 0xff));
}
}
#endif
}
struct pci_device *pci_find_device_2(int vendor, int device, int devclass, int devclass2, int prog_if, int index)
{
int i;
for (i=0; i<n_devs; i++) {
if (vendor < 0 || vendor==dev_list[i].vendor)
if (device < 0 || device==dev_list[i].dev_id)
if (devclass < 0 || devclass==((dev_list[i].class)>>16) || devclass2==((dev_list[i].class)>>16))
if (prog_if < 0 || prog_if==((dev_list[i].class)>>8 & 0xff)) {
if (index == 0)
return &dev_list[i];
index--;
}
}
return NULL;
}
struct pci_device *pci_find_device(int vendor, int device, int devclass, int prog_if, int index)
{
return pci_find_device_2(vendor, device, devclass, devclass, prog_if, index);
}
#endif

View File

@ -1,400 +0,0 @@
/* Adapted from LinuxBIOS */
/*
*
* linux/lib/vsprintf.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
*/
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
* Wirzenius wrote this portably, Torvalds fucked it up :-)
*/
#include "etherboot.h"
#include <stdarg.h>
#include <lib.h>
/* haha, don't need ctype.c */
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define is_digit isdigit
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#define toupper(c) __toupper(c)
static inline unsigned char __toupper(unsigned char c)
{
if (islower(c))
c -= 'a'-'A';
return c;
}
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
{
unsigned long long result = 0,value;
if (!base) {
base = 10;
if (*cp == '0') {
base = 8;
cp++;
if ((*cp == 'x') && isxdigit(cp[1])) {
cp++;
base = 16;
}
}
}
while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
? toupper(*cp) : *cp)-'A'+10) < base) {
result = result*base + value;
cp++;
}
if (endp)
*endp = (char *)cp;
return result;
}
long long simple_strtoll(const char *cp,char **endp,unsigned int base)
{
if(*cp=='-')
return -simple_strtoull(cp+1,endp,base);
return simple_strtoull(cp,endp,base);
}
unsigned long long strtoull_with_suffix(const char *cp,char **endp,unsigned int base)
{
unsigned long long result;
if (!endp) {
printf("%s must be called with endp\n", __FUNCTION__);
return 0;
}
result = simple_strtoull(cp, endp, base);
switch (toupper(**endp)) {
case 'K':
result <<= 10;
++*endp;
break;
case 'M':
result <<= 20;
++*endp;
break;
case 'G':
result <<= 30;
++*endp;
break;
}
return result;
}
#if 0
// it can be used to substitute the vsprintf.c in etherboot. And it has better
// support in numeric output suppot
//When you want to debug filo, you need to enable it and disable vsprintf.c
// to get output from filo
// BY LYH
static int skip_atoi(const char **s)
{
int i=0;
while (is_digit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}
#define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
#define do_div(n,base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
__res; })
static int number(int (*tx_byte)(int byte), long num, int base, int size, int precision
,int type)
{
char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
int i;
int count = 0;
if (type & LARGE)
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
if (num < 0) {
sign = '-';
num = -num;
size--;
} else if (type & PLUS) {
sign = '+';
size--;
} else if (type & SPACE) {
sign = ' ';
size--;
}
}
if (type & SPECIAL) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
i = 0;
if (num == 0)
tmp[i++]='0';
else while (num != 0)
tmp[i++] = digits[do_div(num,base)];
if (i > precision)
precision = i;
size -= precision;
if (!(type&(ZEROPAD+LEFT)))
while(size-->0)
tx_byte(' '), count++;
if (sign)
tx_byte(sign), count++;
if (type & SPECIAL) {
if (base==8)
tx_byte('0'), count++;
else if (base==16) {
tx_byte('0'), count++;
tx_byte(digits[33]), count++;
}
}
if (!(type & LEFT))
while (size-- > 0)
tx_byte(c), count++;
while (i < precision--)
tx_byte('0'), count++;
while (i-- > 0)
tx_byte(tmp[i]), count++;
while (size-- > 0)
tx_byte(' '), count++;
return count;
}
int vtxprintf(int (*tx_byte)(int byte), const char *fmt, va_list args)
{
int len;
unsigned long num;
int i, base;
const char *s;
int flags; /* flags to number() */
int field_width; /* width of output field */
int precision; /* min. # of digits for integers; max
number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */
int count;
for (count=0; *fmt ; ++fmt) {
if (*fmt != '%') {
tx_byte(*fmt), count++;
continue;
}
/* process flags */
flags = 0;
repeat:
++fmt; /* this also skips first '%' */
switch (*fmt) {
case '-': flags |= LEFT; goto repeat;
case '+': flags |= PLUS; goto repeat;
case ' ': flags |= SPACE; goto repeat;
case '#': flags |= SPECIAL; goto repeat;
case '0': flags |= ZEROPAD; goto repeat;
}
/* get field width */
field_width = -1;
if (is_digit(*fmt))
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
field_width = va_arg(args, int);
if (field_width < 0) {
field_width = -field_width;
flags |= LEFT;
}
}
/* get the precision */
precision = -1;
if (*fmt == '.') {
++fmt;
if (is_digit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
precision = va_arg(args, int);
}
if (precision < 0)
precision = 0;
}
/* get the conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
qualifier = *fmt;
++fmt;
}
/* default base */
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & LEFT))
while (--field_width > 0)
tx_byte(' '), count++;
tx_byte((unsigned char) va_arg(args, int)), count++;
while (--field_width > 0)
tx_byte(' '), count++;
continue;
case 's':
s = va_arg(args, char *);
if (!s)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT))
while (len < field_width--)
tx_byte(' '), count++;
for (i = 0; i < len; ++i)
tx_byte(*s++), count++;
while (len < field_width--)
tx_byte(' '), count++;
continue;
case 'p':
if (field_width == -1) {
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
count += number(tx_byte,
(unsigned long) va_arg(args, void *), 16,
field_width, precision, flags);
continue;
case 'n':
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = count;
} else {
int * ip = va_arg(args, int *);
*ip = count;
}
continue;
case '%':
tx_byte('%'), count++;
continue;
/* integer number formats - set up the flags and "break" */
case 'o':
base = 8;
break;
case 'X':
flags |= LARGE;
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= SIGN;
case 'u':
break;
default:
tx_byte('%'), count++;
if (*fmt)
tx_byte(*fmt), count++;
else
--fmt;
continue;
}
if (qualifier == 'L')
num = va_arg(args, unsigned long long);
else if (qualifier == 'l')
num = va_arg(args, unsigned long);
else if (qualifier == 'h') {
num = (unsigned short) va_arg(args, int);
if (flags & SIGN)
num = (short) num;
} else if (flags & SIGN)
num = va_arg(args, int);
else
num = va_arg(args, unsigned int);
count += number(tx_byte, num, base, field_width, precision, flags);
}
return count;
}
/* FIXME this global makes vsprintf non-reentrant
*/
static char *str_buf;
static int str_tx_byte(int byte)
{
*str_buf = byte;
str_buf++;
return byte;
}
int vsprintf(char * buf, const char *fmt, va_list args)
{
int i;
str_buf = buf;
i = vtxprintf(str_tx_byte, fmt, args);
/* maeder/Ispiri -- The null termination was missing a deference */
/* and was just zeroing out the pointer instead */
*str_buf = '\0';
return i;
}
int sprintf(char * buf, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(buf,fmt,args);
va_end(args);
return i;
}
void printf(const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i = vtxprintf(putchar, fmt, args);
va_end(args);
return i;
}
#endif

View File

@ -1,433 +0,0 @@
#ifdef USB_DISK
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
#include <etherboot.h>
#include <pci.h>
#include <timer.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_USB
#include <debug.h>
#define DPRINTF debug
#include "usb.h"
#include "uhci.h"
#include "debug_x.h"
//#include <string.h>
void dump_link( link_pointer_t *link, char *prefix)
{
DPRINTF("%saddr: %08x\n", prefix, MEM_ADDR(link->link) );
DPRINTF("%s raw addr: %04x\n", prefix, (link->link) <<4 );
DPRINTF("%sterminate: %x\n", prefix, link->terminate);
DPRINTF("%squeue: %x\n", prefix, link->queue);
DPRINTF("%sdepth: %x\n", prefix, link->depth);
}
void dump_frame_list( link_pointer_t *addr, char *prefix)
{
int i;
DPRINTF("%sFRAMELIST:\n",prefix);
for(i=0;i<10; i++) {
dump_link(addr+i, prefix);
if(addr[i].queue)
dump_queue_head( MEM_ADDR(addr[i].link), "");
else
dump_td( MEM_ADDR(addr[i].link), "");
}
}
void dump_hex(uchar *data, int len, char *prefix)
{
int i=0;
while(i<len) {
if(!i%16) {
DPRINTF("\n%s %04x: ", prefix, i);
}
else {
DPRINTF(": ");
}
DPRINTF("%02x", data[i++]);
}
DPRINTF("\n");
}
void dump_uhci(uint32_t port)
{
#if 0
unsigned long value;
#endif
DPRINTF("HCI at %08x\n", port);
#if 0
value = inw(port);
DPRINTF("Command: %04x\n", value);
value = inw(port+2);
DPRINTF("USBSTS: %04x\n", value);
value = inw(port+4);
DPRINTF("USBINTR: %04x\n", value);
value = inw(port+6);
DPRINTF("FRNUM: %04x\n", value);
value = inl(port+8);
DPRINTF("FLBASEADD: %08x\n", value);
value = inb(port+0x0c);
DPRINTF("SOFMOD: %02x\n", value);
value = inw(port+0x10);
DPRINTF("PORTSTS1: %04x\n", value);
value = inw(port+0x12);
DPRINTF("PORTSTS2: %04x\n", value);
#endif
}
void dump_td( td_t *td, char *prefix)
{
char newpre[64];
newpre[0]='\t';
strcpy(newpre+1, prefix);
DPRINTF("%sTD(%08x):\n", prefix, td);
switch(td->packet_type) {
case SETUP_TOKEN:
DPRINTF("%stype: SETUP\n", prefix);
break;
case OUT_TOKEN:
DPRINTF("%stype: OUT\n", prefix);
break;
case IN_TOKEN:
DPRINTF("%stype: IN\n", prefix);
break;
default:
DPRINTF("%stype: INVALID (%02x)\n", prefix, td->packet_type);
break;
}
DPRINTF("%sretries: %x\n", prefix, td->retrys);
if(td->isochronous) {
DPRINTF("%sisochronous\n", prefix);
}
if(td->interrupt) {
DPRINTF("%sIOC\n", prefix);
}
if(td->lowspeed) {
DPRINTF("%slowspeed\n", prefix);
}
if(td->detect_short) {
DPRINTF("%sDETECT_SHORT\n", prefix);
}
DPRINTF("%sactive: %04x\n", prefix, td->active);
DPRINTF("%sdevice_addr: %02x\n", prefix, td->device_addr);
DPRINTF("%sendpoint: %1x\n", prefix, td->endpoint);
DPRINTF("%sdata_toggle: %1x\n", prefix, td->data_toggle);
DPRINTF("%smax_transfer: %x\n", prefix, td->max_transfer);
DPRINTF("%sactual: %x\n", prefix, td->actual);
DPRINTF("%slink:\n", prefix);
if(td->stall) {
DPRINTF("%sSTALL\n", prefix);
}
if(td->bitstuff) {
DPRINTF("%sBITSTUFF ERROR\n", prefix);
}
if(td->crc) {
DPRINTF("%sCRC ERROR\n", prefix);
}
if(td->nak) {
DPRINTF("%sNAK ERROR\n", prefix);
}
if(td->babble) {
DPRINTF("%sBABBLE ERROR\n", prefix);
}
if(td->buffer_error) {
DPRINTF("%sBUFFER ERROR\n", prefix);
}
if(MEM_ADDR(td->link.link) == td) {
DPRINTF("link loops back to me!\n");
return;
}
dump_link(&(td->link), newpre);
if(!td->link.terminate) {
if(td->link.queue)
dump_queue_head(MEM_ADDR(td->link.link), prefix );
else
dump_td(MEM_ADDR(td->link.link), prefix);
}
}
void dump_queue_head( queue_head_t *qh, char *prefix)
{
char newpre[64];
newpre[0] = '\t';
strcpy(newpre+1, prefix);
DPRINTF("%sQUEUE HEAD(%x):\n", prefix, qh);
DPRINTF("%sdepth:\n", prefix);
dump_link( &(qh->depth), newpre);
if(!qh->depth.terminate) {
if(qh->depth.queue) {
dump_queue_head(MEM_ADDR(qh->depth.link), newpre);
}
else {
dump_td( MEM_ADDR(qh->depth.link), newpre);
}
}
DPRINTF("%sbredth:\n", prefix);
dump_link( &(qh->bredth), newpre);
if(!qh->bredth.terminate) {
if(qh->bredth.queue) {
dump_queue_head(MEM_ADDR(qh->bredth.link), newpre);
}
else {
dump_td( MEM_ADDR(qh->bredth.link), newpre);
}
}
}
void dump_transaction( transaction_t *trans, char *prefix)
{
char newpre[64];
newpre[0] = '\t';
strcpy(newpre+1, prefix);
DPRINTF("%s TRANSACTION(%x):\n", prefix, trans);
dump_queue_head( trans->qh, newpre);
DPRINTF("%s TDs:\n", prefix);
dump_td( trans->td_list, newpre);
DPRINTF("\n");
if(trans->next)
dump_transaction(trans->next, prefix);
}
void dump_usbdev( usbdev_t *dev, char *prefix)
{
char newpre[64];
int i;
newpre[0] = '\t';
strcpy(newpre+1, prefix);
DPRINTF("%saddress: %x\n", prefix, dev->address);
DPRINTF("%sclass: %x\n", prefix, dev->class);
DPRINTF("%ssubclass: %x\n", prefix, dev->subclass);
DPRINTF("%sbulk_in: %x\n", prefix, dev->bulk_in);
DPRINTF("%sbulk_out: %x\n", prefix, dev->bulk_out);
DPRINTF("%sinterrupt: %x\n", prefix, dev->interrupt);
DPRINTF("%sep toggle:\n", prefix);
for(i=0;i<MAX_EP;i++) {
DPRINTF("%s%x\n", newpre, dev->toggle[i]);
}
DPRINTF("%sep max_packet:\n", prefix);
for(i=0;i<MAX_EP;i++) {
DPRINTF("%s%x\n", newpre, dev->max_packet[i]);
}
}
void dump_all_usbdev(char *prefix)
{
int i;
for(i=0;i<MAX_USB_DEV;i++) {
if(usb_device[i].address) {
DPRINTF("%sDEVICE: %x\n", prefix, i);
dump_usbdev( usb_device +i, prefix);
}
}
}
void dump_device_descriptor( device_descriptor_t *des, char *prefix)
{
DPRINTF("%sbLength: %02x\n", prefix, des->bLength);
DPRINTF("%stype: %02x\n", prefix, des->type);
DPRINTF("%sbcdVersion: %1x%1x\n", prefix, des->bcdVersion[1], des->bcdVersion[0]);
DPRINTF("%sClass: %02x\n",prefix, des->Class);
DPRINTF("%sSubClass: %02x\n",prefix, des->SubClass);
DPRINTF("%sprotocol: %02x\n",prefix, des->protocol);
DPRINTF("%smax_packet: %x\n",prefix, des->max_packet);
DPRINTF("%sidVendor: %04x\n", prefix, des->idVendor);
DPRINTF("%sidProduct: %04x\n", prefix, des->idProduct);
DPRINTF("%sbcdDeviceVersion: %1x%1x\n", prefix, des->bcdDevice[1], des->bcdDevice[0]);
DPRINTF("%siManufacturor: %02x\n", prefix, des->iManufacturor);
DPRINTF("%siProduct: %02x\n", prefix, des->iProduct);
DPRINTF("%siSerial: %02x\n", prefix, des->iSerial);
DPRINTF("%sbNumConfig: %02x\n", prefix, des->bNumConfig);
}
void dump_interface_descriptor( interface_descriptor_t *iface, char *prefix)
{
DPRINTF("%sbLength: %02x\n", prefix, iface->bLength);
DPRINTF("%stype: %02x\n", prefix, iface->type);
DPRINTF("%sbInterfaceNumber: %02x\n", prefix, iface->bInterfaceNumber);
DPRINTF("%sbAlternateSetting: %02x\n", prefix, iface->bAlternateSetting);
DPRINTF("%sbNumEndpoints: %02x\n", prefix, iface->bNumEndpoints);
DPRINTF("%sbInterfaceClass: %02x\n", prefix, iface->bInterfaceClass);
DPRINTF("%sbInterfaceSubClass: %02x\n", prefix, iface->bInterfaceSubClass);
DPRINTF("%sbInterfaceProtocol: %02x\n", prefix, iface->bInterfaceProtocol);
DPRINTF("%siInterface: %02x\n", prefix, iface->iInterface);
}
void dump_endpoint_descriptor( endpoint_descriptor_t *ep, char *prefix)
{
DPRINTF("%sbLength: %02x\n", prefix, ep->bLength);
DPRINTF("%stype: %02x\n", prefix, ep->type);
DPRINTF("%sbEndpointAddress: %02x\n", prefix, ep->bEndpointAddress);
DPRINTF("%sbmAttributes: %02x\n", prefix, ep->bmAttributes);
DPRINTF("%swMaxPacketSize: %02x\n", prefix, ep->wMaxPacketSize);
DPRINTF("%sbInterval: %02x\n", prefix, ep->bInterval);
}
void dump_config_descriptor( uchar *des, char *prefix) // YES uchar *
{
config_descriptor_t *config;
interface_descriptor_t *iface;
endpoint_descriptor_t *ep;
char newpre[64];
int i;
memset(newpre,0,sizeof(newpre));
newpre[0] = '\t';
strcpy(newpre+1, prefix);
config = (config_descriptor_t *) des;
iface = (interface_descriptor_t *) (des + config->bLength);
ep = (endpoint_descriptor_t *) (des + config->bLength + iface->bLength);
// now, the config itself
DPRINTF("%sbLength: %02x\n", prefix, config->bLength);
DPRINTF("%stype: %02x\n", prefix, config->type);
DPRINTF("%swTotalLength: %04x\n", prefix, config->wTotalLength);
DPRINTF("%sbNumInterfaces: %02x\n", prefix, config->bNumInterfaces);
DPRINTF("%sbConfigurationValue: %02x\n", prefix, config->bConfigurationValue);
DPRINTF("%siConfiguration: %02x\n", prefix, config->iConfiguration);
DPRINTF("%sbmAttributes: %02x\n", prefix, config->bmAttributes);
DPRINTF("%sbMaxPower: %02x\n", prefix, config->bMaxPower);
DPRINTF("\n%sInterface(%x):\n", prefix, iface);
dump_interface_descriptor(iface, newpre);
newpre[1] = '\t';
strcpy(newpre+2, prefix);
for(i=0; i<iface->bNumEndpoints; i++) {
DPRINTF("\n%sEndpoint (%x):\n", newpre+1, ep+i);
dump_endpoint_descriptor( ep+i, newpre);
}
}
// Some control message bmRequestType defines
#define CTRL_DEVICE 0
#define CONTROL_INTERFACE 1
#define CONTROL_ENDPOINT 2
#define CONTROL_OTHER 3
#define CONTROL_RECIPIENT_MASK 0x1f
#define CONTROL_TYPE_STD 0
#define CONTROL_TYPE_CLASS 0x20
#define CONTROL_CLASS_VENDOR 0x40
#define CONTROL_CLASS_MASK 0x60
#define CONTROL_OUT 0
#define CONTROL_IN 0x80
#define CONTROL_DIR_MASK 0x80
// bRequest values
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
#define SYNC_FRAME 12
// descriptor types
#define DEVICE_DESC 1
#define CONFIGURATION_DESC 2
#define STRING_DESC 3
#define INTERFACE_DESC 4
#define ENDPOINT_DESC 5
#define OTHERSPEED_DESC 7
#define POWER_DESC 8
// features
#define FEATURE_HALT 0
void dump_ctrlmsg( ctrl_msg_t *msg, char *prefix)
{
DPRINTF("%sbmRequestType: %02x\n", prefix, msg->bmRequestType);
DPRINTF("%sbRequest: %02x\n", prefix, msg->bRequest);
DPRINTF("%swValue: %04x\n", prefix, msg->wValue);
DPRINTF("%swIndex: %04x\n", prefix, msg->wIndex);
DPRINTF("%swLength: %04x\n", prefix, msg->wLength);
}
#endif

View File

@ -1,18 +0,0 @@
#ifndef _DEBUG_X_H
#define _DEBUG_X_H
void dump_hex(uchar *data, int len, char *prefix);
void dump_link( link_pointer_t *link, char *prefix);
void dump_td( td_t *td, char *prefix);
void dump_queue_head( queue_head_t *qh, char *prefix);
void dump_transaction( transaction_t *trans, char *prefix);
void dump_usbdev( usbdev_t *dev, char *prefix);
void dump_uhci(uint32_t port);
//void dump_all_usbdev(char *prefix);
void dump_device_descriptor( device_descriptor_t *des, char *prefix);
void dump_interface_descriptor( interface_descriptor_t *iface, char *prefix);
void dump_endpoint_descriptor( endpoint_descriptor_t *ep, char *prefix);
void dump_config_descriptor( uchar *des, char *prefix);
void dump_ctrlmsg( ctrl_msg_t *msg, char *prefix);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,316 +0,0 @@
#ifdef USB_DISK
#ifndef _OHCI_H
#define _OHCI_H
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
// for OHCI
/* ED States */
#define ED_NEW 0x00
#define ED_UNLINK 0x01
#define ED_OPER 0x02
#define ED_DEL 0x04
#define ED_URB_DEL 0x08
/* usb_ohci_ed */
struct ed {
u32 hwINFO;
u32 hwTailP;
u32 hwHeadP;
u32 hwNextED;
struct ed * ed_prev;
u8 int_period; // No use just for aligned
u8 int_branch; // No use just for aligned
u8 int_load; // No uae just for aligned
u8 int_interval; // No use just for aligned
u8 state;
u8 type;
u16 last_iso; // no use just for aligned
struct ed * ed_rm_list; // No use just for aligned
void * dma;
u32 unused[3];
};
// __attribute((aligned(16)));
typedef struct ed ed_t;
/* TD info field */
#define TD_CC 0xf0000000
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
#define TD_EC 0x0C000000
#define TD_T 0x03000000
#define TD_T_DATA0 0x02000000
#define TD_T_DATA1 0x03000000
#define TD_T_TOGGLE 0x00000000
#define TD_R 0x00040000
#define TD_DI 0x00E00000
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
#define TD_DP 0x00180000
#define TD_DP_SETUP 0x00000000
#define TD_DP_IN 0x00100000
#define TD_DP_OUT 0x00080000
#define TD_ISO 0x00010000
#define TD_DEL 0x00020000
/* CC Codes */
#define TD_CC_NOERROR 0x00
#define TD_CC_CRC 0x01
#define TD_CC_BITSTUFFING 0x02
#define TD_CC_DATATOGGLEM 0x03
#define TD_CC_STALL 0x04
#define TD_DEVNOTRESP 0x05
#define TD_PIDCHECKFAIL 0x06
#define TD_UNEXPECTEDPID 0x07
#define TD_DATAOVERRUN 0x08
#define TD_DATAUNDERRUN 0x09
#define TD_BUFFEROVERRUN 0x0C
#define TD_BUFFERUNDERRUN 0x0D
#define TD_NOTACCESSED 0x0F
#define MAXPSW 1
struct ohci_td {
u32 hwINFO;
u32 hwCBP; /* Current Buffer Pointer */
u32 hwNextTD; /* Next TD Pointer */
u32 hwBE; /* Memory Buffer End Pointer */
u16 hwPSW[MAXPSW];
u8 unused;
u8 index;
struct ed * ed;
struct ohci_td * next_dl_td;
struct urb * urb; //defined in usb.h
void * td_dma;
void * data_dma;
u32 unused2[2];
};
//__attribute((aligned(32))); /* normally 16, iso needs 32 */
typedef struct ohci_td ohci_td_t;
#define OHCI_ED_SKIP (1 << 14)
/*
* The HCCA (Host Controller Communications Area) is a 256 byte
* structure defined in the OHCI spec. that the host controller is
* told the base address of. It must be 256-byte aligned.
*/
#define NUM_INTS 32 /* part of the OHCI standard */
struct ohci_hcca {
u32 int_table[NUM_INTS]; /* Interrupt ED table */
u16 frame_no; /* current frame number */
u16 pad1; /* set to 0 on each frame_no change */
u32 done_head; /* info returned for an interrupt */
u8 reserved_for_hc[116];
} __attribute((aligned(256)));
#define MAX_ROOT_PORTS 15
struct ohci_regs {
/* control and status registers */
u32 revision;
u32 control;
u32 cmdstatus;
u32 intrstatus;
u32 intrenable;
u32 intrdisable;
/* memory pointers */
u32 hcca;
u32 ed_periodcurrent;
u32 ed_controlhead;
u32 ed_controlcurrent;
u32 ed_bulkhead;
u32 ed_bulkcurrent;
u32 donehead;
/* frame counters */
u32 fminterval;
u32 fmremaining;
u32 fmnumber;
u32 periodicstart;
u32 lsthresh;
/* Root hub ports */
struct ohci_roothub_regs {
u32 a;
u32 b;
u32 status;
u32 portstatus[MAX_ROOT_PORTS];
} roothub;
} __attribute((aligned(32)));
typedef struct ohci_regs ohci_regs_t;
/* OHCI CONTROL AND STATUS REGISTER MASKS */
/*
* HcControl (control) register masks
*/
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
/* pre-shifted values for HCFS */
# define OHCI_USB_RESET (0 << 6)
# define OHCI_USB_RESUME (1 << 6)
# define OHCI_USB_OPER (2 << 6)
# define OHCI_USB_SUSPEND (3 << 6)
/*
* HcCommandStatus (cmdstatus) register masks
*/
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_CLF (1 << 1) /* control list filled */
#define OHCI_BLF (1 << 2) /* bulk list filled */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
/*
* masks used with interrupt registers:
* HcInterruptStatus (intrstatus)
* HcInterruptEnable (intrenable)
* HcInterruptDisable (intrdisable)
*/
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
#define OHCI_INTR_SF (1 << 2) /* start frame */
#define OHCI_INTR_RD (1 << 3) /* resume detect */
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
#define OHCI_INTR_OC (1 << 30) /* ownership change */
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
/* For initializing controller (mask in an HCFS mode too) */
#define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3)
//| OHCI_CTRL_IE | OHCI_CTRL_PLE
/* OHCI ROOT HUB REGISTER MASKS */
/* roothub.portstatus [i] bits */
#define RH_PS_CCS 0x00000001 /* current connect status */
#define RH_PS_PES 0x00000002 /* port enable status*/
#define RH_PS_PSS 0x00000004 /* port suspend status */
#define RH_PS_POCI 0x00000008 /* port over current indicator */
#define RH_PS_PRS 0x00000010 /* port reset status */
#define RH_PS_PPS 0x00000100 /* port power status */
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
#define RH_PS_CSC 0x00010000 /* connect status change */
#define RH_PS_PESC 0x00020000 /* port enable status change */
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
#define RH_PS_PRSC 0x00100000 /* port reset status change */
/* roothub.status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
#define RH_HS_OCI 0x00000002 /* over current indicator */
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
#define RH_HS_LPSC 0x00010000 /* local power status change */
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
/* roothub.b masks */
#define RH_B_DR 0x0000ffff /* device removable flags */
#define RH_B_PPCM 0xffff0000 /* port power control mask */
/* roothub.a masks */
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
#define RH_A_PSM (1 << 8) /* power switching mode */
#define RH_A_NPS (1 << 9) /* no power switching */
#define RH_A_DT (1 << 10) /* device type (mbz) */
#define RH_A_OCPM (1 << 11) /* over current protection mode */
#define RH_A_NOCP (1 << 12) /* no over current protection */
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
typedef struct
{
ed_t * ed;
u16 length; // number of tds associated with this request
u16 td_cnt; // number of tds already serviced
int state;
#if 0
wait_queue_head_t * wait;
#endif
ohci_td_t * td[0]; // list pointer to all corresponding TDs associated with this request
} urb_priv_t;
#define NUM_EDS 32 /* num of preallocated endpoint descriptors */
typedef struct ohci {
struct ohci_hcca *hcca; /* hcca */
void * hcca_dma;
ohci_regs_t * regs; /* OHCI controller's memory */
ed_t * ed_bulktail; /* last endpoint of bulk list */
ed_t * ed_controltail; /* last endpoint of control list */
int intrstatus;
u32 hc_control; /* copy of the hc control reg */
uint32_t ed_cnt;
ed_t *ed; // Allocate that from ed_buffer in ohc_init
usbdev_t *dev[NUM_EDS];
urb_t *urb; // one ohci one urb
urb_priv_t *urb_priv;
struct usb_ctrlrequest *dr;
} ohci_t;
extern ohci_t _ohci_x[MAX_CONTROLLERS];
#define usb_to_ohci(usb_dev) (&_ohci_x[(usb_dev)->controller])
extern ohci_regs_t *ohci_regs;
void clear_oport_stat(uint32_t port);
int ohc_init(struct pci_device *dev);
int poll_o_root_hub(uint32_t port, uchar controller);
int ohci_bulk_transfer( uchar devnum, uchar ep, unsigned int data_len, uchar *data);
int ohci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short
wLength, void *data);
void ohci_wait_urb_done(struct urb *urb, int timeout);
void ohci_init(void);
int ohc_init(struct pci_device *dev);
int ohci_submit_urb (struct urb * urb);
#endif
#endif

View File

@ -1,226 +0,0 @@
/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/*
* This header file contains public constants and structures used by
* the scsi code for linux.
*/
#ifndef _SCSI_SCSI_H
#define _SCSI_SCSI_H 1
//#include <features.h>
/*
* SCSI opcodes
*/
#define TEST_UNIT_READY 0x00
#define REZERO_UNIT 0x01
#define REQUEST_SENSE 0x03
#define FORMAT_UNIT 0x04
#define READ_BLOCK_LIMITS 0x05
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SEEK_6 0x0b
#define READ_REVERSE 0x0f
#define WRITE_FILEMARKS 0x10
#define SPACE 0x11
#define INQUIRY 0x12
#define RECOVER_BUFFERED_DATA 0x14
#define MODE_SELECT 0x15
#define RESERVE 0x16
#define RELEASE 0x17
#define COPY 0x18
#define ERASE 0x19
#define MODE_SENSE 0x1a
#define START_STOP 0x1b
#define RECEIVE_DIAGNOSTIC 0x1c
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
#define SET_WINDOW 0x24
#define READ_CAPACITY 0x25
#define READ_10 0x28
#define WRITE_10 0x2a
#define SEEK_10 0x2b
#define WRITE_VERIFY 0x2e
#define VERIFY 0x2f
#define SEARCH_HIGH 0x30
#define SEARCH_EQUAL 0x31
#define SEARCH_LOW 0x32
#define SET_LIMITS 0x33
#define PRE_FETCH 0x34
#define READ_POSITION 0x34
#define SYNCHRONIZE_CACHE 0x35
#define LOCK_UNLOCK_CACHE 0x36
#define READ_DEFECT_DATA 0x37
#define MEDIUM_SCAN 0x38
#define COMPARE 0x39
#define COPY_VERIFY 0x3a
#define WRITE_BUFFER 0x3b
#define READ_BUFFER 0x3c
#define UPDATE_BLOCK 0x3d
#define READ_LONG 0x3e
#define WRITE_LONG 0x3f
#define CHANGE_DEFINITION 0x40
#define WRITE_SAME 0x41
#define READ_TOC 0x43
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
#define MODE_SELECT_10 0x55
#define RESERVE_10 0x56
#define RELEASE_10 0x57
#define MODE_SENSE_10 0x5a
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
#define MOVE_MEDIUM 0xa5
#define READ_12 0xa8
#define WRITE_12 0xaa
#define WRITE_VERIFY_12 0xae
#define SEARCH_HIGH_12 0xb0
#define SEARCH_EQUAL_12 0xb1
#define SEARCH_LOW_12 0xb2
#define READ_ELEMENT_STATUS 0xb8
#define SEND_VOLUME_TAG 0xb6
#define WRITE_LONG_2 0xea
/*
* Status codes
*/
#define GOOD 0x00
#define CHECK_CONDITION 0x01
#define CONDITION_GOOD 0x02
#define BUSY 0x04
#define INTERMEDIATE_GOOD 0x08
#define INTERMEDIATE_C_GOOD 0x0a
#define RESERVATION_CONFLICT 0x0c
#define COMMAND_TERMINATED 0x11
#define QUEUE_FULL 0x14
#define STATUS_MASK 0x3e
/*
* SENSE KEYS
*/
#define NO_SENSE 0x00
#define RECOVERED_ERROR 0x01
#define NOT_READY 0x02
#define MEDIUM_ERROR 0x03
#define HARDWARE_ERROR 0x04
#define ILLEGAL_REQUEST 0x05
#define UNIT_ATTENTION 0x06
#define DATA_PROTECT 0x07
#define BLANK_CHECK 0x08
#define COPY_ABORTED 0x0a
#define ABORTED_COMMAND 0x0b
#define VOLUME_OVERFLOW 0x0d
#define MISCOMPARE 0x0e
/*
* DEVICE TYPES
*/
#define TYPE_DISK 0x00
#define TYPE_TAPE 0x01
#define TYPE_PROCESSOR 0x03 /* HP scanners use this */
#define TYPE_WORM 0x04 /* Treated as ROM by our system */
#define TYPE_ROM 0x05
#define TYPE_SCANNER 0x06
#define TYPE_MOD 0x07 /* Magneto-optical disk -
* - treated as TYPE_DISK */
#define TYPE_MEDIUM_CHANGER 0x08
#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define TYPE_NO_LUN 0x7f
/*
* standard mode-select header prepended to all mode-select commands
*
* moved here from cdrom.h -- kraxel
*/
struct ccs_modesel_head
{
unsigned char _r1; /* reserved. */
unsigned char medium; /* device-specific medium type. */
unsigned char _r2; /* reserved. */
unsigned char block_desc_length; /* block descriptor length. */
unsigned char density; /* device-specific density code. */
unsigned char number_blocks_hi; /* number of blocks in this block
desc. */
unsigned char number_blocks_med;
unsigned char number_blocks_lo;
unsigned char _r3;
unsigned char block_length_hi; /* block length for blocks in this
desc. */
unsigned char block_length_med;
unsigned char block_length_lo;
};
/*
* MESSAGE CODES
*/
#define COMMAND_COMPLETE 0x00
#define EXTENDED_MESSAGE 0x01
#define EXTENDED_MODIFY_DATA_POINTER 0x00
#define EXTENDED_SDTR 0x01
#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */
#define EXTENDED_WDTR 0x03
#define SAVE_POINTERS 0x02
#define RESTORE_POINTERS 0x03
#define DISCONNECT 0x04
#define INITIATOR_ERROR 0x05
#define ABORT 0x06
#define MESSAGE_REJECT 0x07
#define NOP 0x08
#define MSG_PARITY_ERROR 0x09
#define LINKED_CMD_COMPLETE 0x0a
#define LINKED_FLG_CMD_COMPLETE 0x0b
#define BUS_DEVICE_RESET 0x0c
#define INITIATE_RECOVERY 0x0f /* SCSI-II only */
#define RELEASE_RECOVERY 0x10 /* SCSI-II only */
#define SIMPLE_QUEUE_TAG 0x20
#define HEAD_OF_QUEUE_TAG 0x21
#define ORDERED_QUEUE_TAG 0x22
/*
* Here are some scsi specific ioctl commands which are sometimes useful.
*/
/* These are a few other constants only used by scsi devices. */
#define SCSI_IOCTL_GET_IDLUN 0x5382
/* Used to turn on and off tagged queuing for scsi devices. */
#define SCSI_IOCTL_TAGGED_ENABLE 0x5383
#define SCSI_IOCTL_TAGGED_DISABLE 0x5384
/* Used to obtain the host number of a device. */
#define SCSI_IOCTL_PROBE_HOST 0x5385
/* Used to get the bus number for a device. */
#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
#endif /* scsi/scsi.h */

View File

@ -1,512 +0,0 @@
#ifdef USB_DISK
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
#include <etherboot.h>
#include <pci.h>
#include <timer.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_USB
#include <debug.h>
#define DPRINTF debug
#include "scsi.h"
#include "usb_scsi_low.h"
#ifndef NULL
#define NULL (void *) 0x0
#endif
#include "scsi_cmds.h"
devhandle sgh;
typedef struct sense_data {
uchar code;
uchar sense_key:4;
uchar res1:4;
uchar additional_code;
uchar qualifier;
uchar res2[3];
uchar length;
} __attribute__ ((packed)) sense_data_t;
typedef struct fixed_sense_data {
uchar code:7;
uchar valid:1;
uchar obs1;
uchar sense_key:4;
uchar res1:1;
uchar ili:1;
uchar eom:1;
uchar mark:1;
unsigned int info;
uchar add_len;
} __attribute__ ((packed)) fixed_sense_data_t;
typedef struct additional_fixed_data {
unsigned int info;
uchar code;
uchar qualifier;
uchar fru;
uchar specific[3];
} __attribute__ ((packed)) additional_fixed_data_t;
void PrintSense(uchar *sense, int len)
{
int i;
DPRINTF( "sense data ");
for(i=0;i<len; i++) {
DPRINTF( ":%02x", sense[i]);
}
DPRINTF("\n\n");
if( (sense[0] & 0x7f) >=0x72) {
sense_data_t *sd = (sense_data_t *) sense;
uchar *pos = sense+sizeof(sense_data_t);
uchar remaining = sd->length;
int dlen;
DPRINTF("code = %02x, key = %1x, additional = %02x, qual = %02x\n", sd->code, sd->sense_key, sd->additional_code, sd->qualifier);
while(remaining) {
DPRINTF("type = %02x", pos[0]);
dlen = pos[1];
pos+=2;
remaining -=2;
for(i=0; i<dlen; i++)
DPRINTF( ": %02x", pos[i]);
DPRINTF("\n");
pos+=i;
remaining -=i;
}
} else {
fixed_sense_data_t *fd = (fixed_sense_data_t *) sense;
uchar remaining = fd->add_len;
additional_fixed_data_t *afd;
DPRINTF("code = %02x key = %1x\n", fd->code, fd->sense_key);
if(fd->mark) {
DPRINTF("filemark ");
}
if(fd->eom) {
DPRINTF(" End Of Media ");
}
if(fd->ili) {
DPRINTF("Illegal instruction");
}
DPRINTF("\n");
if(fd->valid) {
DPRINTF( "(valid) ");
}
DPRINTF( "Info: %08x\n", ntohl(fd->info));
afd = (additional_fixed_data_t *) (sense + 8);
// while(remaining) {
if(remaining) {
DPRINTF("command info = %08x\n", ntohl(afd->info));
DPRINTF("code = %02x, qual = %02x, fru = %02x\n", afd->code, afd->qualifier, afd->fru);
DPRINTF("sense key data = %02x:%02x:%02x\n\n", afd->specific[2], afd->specific[1], afd->specific[0]);
afd++;
remaining -= sizeof(additional_fixed_data_t);
}
}
}
typedef struct query_response {
uchar type:5;
uchar qualifier:3;
uchar reserved1:7;
uchar removable:1;
uchar version;
uchar ResponseDataFormat:4; // should == 2
uchar HiSup:1; // report luns cmd supported
uchar NormACA:1;
uchar obsolete:1;
uchar aerc:1;
uchar AdditionalLength; // length of vendor specific data (beyond 96 bytes)
uchar reserved2:7;
uchar sccs:1; // have raid controller
uchar addr16:1; //
uchar obsolete2:2;
uchar MChnger:1; // media changer
uchar MultiP:1; // multi port
uchar vs:1; // ???
uchar EncServ:1; // enclosure service
uchar BQue:1; // basic command queueing
uchar vs2:1;
uchar CmdQue:1; // full command queueing
uchar obsolete4:1;
uchar linked:1;
uchar sync:1;
uchar wbus16:1; //
uchar obsolete3:1;
uchar RelAddr:1; // treletive addressing
char vendor[8];
char product[16];
char revision[4];
char vendor_data[20];
uchar ius:1;
uchar qas:1;
uchar clocking:2; //
uchar reserved3:4;
unsigned short version_desc[8];
char reserved4[21];
} query_response_t;
typedef struct ReadBlockCMD {
uchar cmd;
uchar reladdr:1;
uchar reserved:2;
uchar fua:1; // force unit access flush to media
uchar dpo:1; // direct page out, do not cache
uchar reserved2:3;
unsigned int block_address;
uchar reserved3;
unsigned short block_count;
uchar control;
} __attribute__ ((packed)) ReadBlockCMD_t ;
int ll_read_block(devhandle sgd, char *buffer, int blocknum, int count)
{
int ret;
ReadBlockCMD_t rb;
char sensedat[32];
memset(&rb,0,sizeof(rb));
rb.cmd = READ_10;
rb.block_address = htonl(blocknum);
rb.block_count = htons(count);
ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_FROM_DEV, buffer, count * 512, sensedat, sizeof(sensedat));
if(ret<0) {
DPRINTF("ERROR: ll_read_block( %x, %x, %x, %x) = %d\n", sgd, buffer, blocknum, count, ret);
PrintSense(sensedat, 32);
}
return(ret);
}
int ll_write_block(devhandle sgd, char *buffer, int blocknum, int count)
{
int ret;
ReadBlockCMD_t rb;
char sensedat[32];
memset(&rb,0,sizeof(rb));
rb.cmd = WRITE_10;
rb.block_address = htonl(blocknum);
rb.block_count = htons(count);
ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_TO_DEV, buffer, count * 512, sensedat, sizeof(sensedat));
return(ret);
}
typedef struct ReadLongCMD {
uchar cmd;
uchar reladdr:1;
uchar correct:1;
uchar reserved:5;
unsigned int block_address;
uchar reserved3;
unsigned short length;
uchar control;
} __attribute__ ((packed)) ReadLongCMD_t ;
int ll_read_long(devhandle sgd, char *buffer, int blocknum, int size)
{
int ret;
ReadLongCMD_t rb;
char sensedat[32];
memset(&rb,0,sizeof(rb));
rb.cmd = READ_LONG;
rb.block_address = htonl(blocknum);
rb.length = htons(size);
ret = scsi_command( sgd, (uint8_t *)&rb, sizeof(rb), SG_DXFER_FROM_DEV, buffer, size, sensedat, sizeof(sensedat));
return(ret);
}
unsigned char ReadCapacityCMD[10] = { READ_CAPACITY, 0, 0,0,0,0, 0,0,0, 0};
struct ReadCapacityResponse {
unsigned int block_address;
unsigned int block_length;
};
int get_capacity(devhandle sgd, unsigned long *block_count, unsigned int *blk_len)
{
int ret;
struct ReadCapacityResponse response;
char sensedat[32];
ret = scsi_command(sgd, ReadCapacityCMD, sizeof(ReadCapacityCMD), SG_DXFER_FROM_DEV, (uint8_t *)&response, sizeof(response), sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("ERROR:get capacity: %d\n", ret);
PrintSense(sensedat,32);
}
*block_count = ntohl(response.block_address) +1;
*blk_len = ntohl(response.block_length);
return(ret);
}
#define INQ_REP_LEN 96
unsigned char InquiryCMD[6] = { INQUIRY, 0, 0, 0, INQ_REP_LEN, 0};
int query(devhandle sgd, query_response_t *qr)
{
int ret;
char sensedat[32];
ret = scsi_command(sgd, InquiryCMD, sizeof(InquiryCMD), SG_DXFER_FROM_DEV, (uint8_t *)qr, sizeof(query_response_t), sensedat, sizeof(sensedat) );
if(ret<0){
DPRINTF("query: IOCTL");
}
return(ret);
}
typedef struct lun_list {
unsigned int list_length;
unsigned int reserved;
unsigned long long lun[16];
} lun_list_t;
#define REPORT_LUNS 0xa0
unsigned char ReportLunsCMD[12] = { REPORT_LUNS, 0, 2, 0, 0, 0, 0, 0, 0, 128, 0, 0 };
int ReportLUNS(devhandle sgd, lun_list_t *list)
{
int ret;
char sensedat[32];
memset (list, 0, sizeof(lun_list_t));
ret = scsi_command(sgd, ReportLunsCMD, sizeof(ReportLunsCMD), SG_DXFER_FROM_DEV, (uint8_t *)list, sizeof(lun_list_t), sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("Report Luns: IOCTL");
}
list->list_length = ntohl(list->list_length);
return(ret);
}
typedef struct command_descriptor {
uchar opcode;
uchar reserved;
unsigned short service_action;
uchar reserved2;
uchar action_valid:1;
uchar reserved3:7;
unsigned short cdb_len;
} __attribute__ ((packed)) command_descriptor_t;
typedef struct report_opcodes_result {
unsigned long length;
command_descriptor_t command[256];
} __attribute__ ((packed)) report_opcode_result_t;
#define REPORT_OPCODES 0xa3
typedef struct report_opcodes_cmd {
uchar cmd;
uchar reserved[5];
unsigned int reply_len;
uchar reserved2;
uchar control;
} __attribute__ ((packed)) ReportOpcodesCMD_t;
//ReportOpcodesCMD_t ReportOpcodesCMD = { cmd : REPORT_OPCODES, reply_len: htonl(sizeof(report_opcode_result_t)) };
int ReportOpCodes(devhandle sgd, report_opcode_result_t *list)
{
int ret;
char sensedat[32];
ReportOpcodesCMD_t ReportOpcodesCMD;
memset (list, 0, sizeof(report_opcode_result_t));
ReportOpcodesCMD.cmd = REPORT_OPCODES;
ReportOpcodesCMD.reply_len = htonl( sizeof(report_opcode_result_t));
ret = scsi_command(sgd, (uint8_t *)&ReportOpcodesCMD, sizeof(ReportOpcodesCMD_t), SG_DXFER_FROM_DEV, (uint8_t *)list, sizeof(report_opcode_result_t), sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("Report Luns: IOCTL");
}
list->length = ntohl(list->length);
return(ret);
}
#define READ_ATTRIBUTE 0x8c
#define VOLUME_LIST 2
#define PARTITION_LIST 3
typedef struct read_attribute_cmd {
uchar cmd;
uchar action:5;
uchar res:3;
uchar restricted[3];
uchar volume;
uchar res2;
uchar partition;
ushort attribute;
unsigned int reply_len;
uchar res3;
uchar control;
} __attribute__ ((packed)) ReadAttributeCMD_t;
int CheckVolumes(devhandle sgd)
{
int ret;
uchar reply[4];
uchar sensedat[32];
ReadAttributeCMD_t cmd;
memset(&cmd,0,sizeof(cmd));
cmd.cmd=READ_ATTRIBUTE;
cmd.action = VOLUME_LIST;
cmd.reply_len = htonl(4);
ret = scsi_command(sgd, (uint8_t *)&cmd, sizeof(cmd), SG_DXFER_FROM_DEV, reply, sizeof(reply), sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("Report Volumes: IOCTL");
return(-1);
}
if(! reply[0] && !reply[1])
return(0);
return(reply[3]);
}
int CheckPartitions(devhandle sgd)
{
int ret;
uchar reply[4];
uchar sensedat[32];
ReadAttributeCMD_t cmd;
memset(&cmd,0,sizeof(cmd));
cmd.cmd=READ_ATTRIBUTE;
cmd.action = PARTITION_LIST;
cmd.reply_len = htonl(4);
ret = scsi_command(sgd, (uint8_t *)&cmd, sizeof(cmd), SG_DXFER_FROM_DEV, reply, sizeof(reply), sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("Report PARTITIONVolumes: IOCTL");
return(-1);
}
if(! reply[0] && !reply[1])
return(0);
return(reply[3]);
}
int UnitReady(devhandle sgd)
{
uchar cmd[6];
uchar sensedat[32];
int ret;
memset(cmd,0,sizeof(cmd));
ret = scsi_command(sgd, &cmd, sizeof(cmd), SG_DXFER_FROM_DEV, NULL, 0, sensedat, sizeof(sensedat) );
if(ret<0) {
DPRINTF("UnitReady :");
return(0);
}
return(1);
}
#endif

View File

@ -1,14 +0,0 @@
#ifndef _SCSI_CMDS_H
#define _SCSI_CMDS_H
#define devhandle uint8_t
#define uchar uint8_t
#define ushort uint16_t
void PrintSense(uchar *sense, int len);
int ll_read_block(devhandle sgd, char *buffer, int blocknum, int count);
int get_capacity(devhandle sgd, unsigned long *block_count, unsigned int *blk_len);
int UnitReady(uchar sgd);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,175 +0,0 @@
#ifndef _UHCI_H
#define _UHCI_H
/*
* The link pointer is multi use. Some fields are valid only for some uses.
* In other cases, they must be 0
*
*/
#define MAX_POLLDEV 10
#define MAX_TRANSACTIONS 10
#define MAX_QUEUEHEAD 255
#define MAX_TD 1024
typedef struct link_pointer {
unsigned long terminate:1;
unsigned long queue:1;
unsigned long depth:1;
unsigned long reserved:1;
unsigned long link:28;
} __attribute__((packed)) link_pointer_t;
extern link_pointer_t *frame_list[];
void init_framelist(uchar dev);
#define SETUP_TOKEN 0x2d
#define IN_TOKEN 0x69
#define OUT_TOKEN 0xe1
#define CTRL_RETRIES 3
#define CONTROL_STS_RETRIES 0
// some port features
#define PORT_CONNECTION 0
#define PORT_ENABLE 1
#define PORT_SUSPEND 2
#define PORT_OVER_CURRENT 3
#define PORT_RESET 4
#define PORT_POWER 8
#define PORT_LOW_SPEED 9
#define C_PORT_CONNECTION 16
#define C_PORT_ENABLE 17
#define C_PORT_SUSPEND 18
#define C_PORT_OVER_CURRENT 19
#define C_PORT_RESET 20
// features
#define FEATURE_HALT 0
typedef struct td {
link_pointer_t link;
unsigned long actual:11; // actual length
unsigned long reserved2:5;
// status/error flags
unsigned long res1:1;
unsigned long bitstuff:1;
unsigned long crc:1;
unsigned long nak:1;
unsigned long babble:1;
unsigned long buffer_error:1;
unsigned long stall:1;
unsigned long active:1;
unsigned long interrupt:1; // interrupt on complete
unsigned long isochronous:1;
unsigned long lowspeed:1;
unsigned long retrys:2;
unsigned long detect_short:1;
unsigned long reserved3:2;
unsigned long packet_type:8; // one of in (0x69), out (0xe1) or setup (0x2d)
unsigned long device_addr:7;
unsigned long endpoint:4;
unsigned long data_toggle:1;
unsigned long reserved:1;
unsigned long max_transfer:11; // misnamed. Desired length might be better
void *buffer;
unsigned long data[4]; // free use by driver
} __attribute__((packed)) td_t;
typedef struct queue_head {
link_pointer_t bredth; // depth must = 0
link_pointer_t depth; // depth may vary randomly, ignore
unsigned long int udata[2];
} __attribute__((packed)) queue_head_t;
typedef struct transaction {
queue_head_t *qh;
td_t *td_list;
struct transaction *next;
} transaction_t;
//#####################################################
int wait_head( queue_head_t *head, int count);
extern queue_head_t *free_qh;
extern queue_head_t *queue_heads;
queue_head_t *new_queue_head(void);
void free_queue_head( queue_head_t *qh);
void init_qh(void);
extern td_t *free_td_list;
extern td_t *tds;
void init_td(void);
td_t *new_td(void);
td_t *find_last_td(td_t *td);
void free_td( td_t *td);
link_pointer_t *queue_end( queue_head_t *queue);
void add_td( queue_head_t *head, td_t *td);
extern transaction_t transactions[MAX_TRANSACTIONS];
extern transaction_t *free_transactions;
void init_transactions(void);
void free_transaction( transaction_t *trans );
transaction_t *new_transaction(td_t *td);
transaction_t *add_transaction( transaction_t *trans, td_t *td);
#define USBCMD(x) hc_base[x]
#define USBSTS(x) (hc_base[x] + 0x02)
#define USBINTR(x) (hc_base[x] + 0x04)
#define FRNUM(x) ( hc_base[x] + 0x06)
#define FLBASE(x) ( hc_base[x] + 0x08)
#define SOFMOD(x) ( hc_base[x] + 0x0c)
#define PORTSC1(x) ( hc_base[x] + 0x10)
#define PORTSC2(x) ( hc_base[x] + 0x12)
#define USBCMDRUN 0x01
#define USBCMD_DEBUG 0x20
#define USBSTSHALTED 0x20
void hc_reset(uchar dev);
int hc_stop(void);
int hc_start(uchar dev);
extern queue_head_t *sched_queue[];
void init_sched(uchar dev);
int poll_queue_head( queue_head_t *qh);
int wait_queue_complete( queue_head_t *qh);
extern int num_polls;
extern int (*devpoll[MAX_POLLDEV])(uchar);
extern uchar parm[MAX_POLLDEV];
transaction_t *_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data);
transaction_t *ctrl_msg(uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, uchar *data);
int schedule_transaction( uchar dev, transaction_t *trans);
int wait_transaction( transaction_t *trans);
void unlink_transaction( uchar dev, transaction_t *trans);
int uhci_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data);
int uhci_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex, unsigned short wLength, void *data);
// defined in uhci.c
int uhc_init(struct pci_device *dev);
void uhci_init(void);
void clear_uport_stat(unsigned short port);
int poll_u_root_hub(unsigned short port, uchar controller);
#endif

View File

@ -1,803 +0,0 @@
#ifdef USB_DISK
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
#include <etherboot.h>
#include <pci.h>
#include <timer.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_USB
#include <debug.h>
#define DPRINTF debug
#include "usb.h"
#include "uhci.h"
#include "ohci.h"
#include "debug_x.h"
#define ALLOCATE 1
int usec_offset=0;
int num_controllers=0;
uint32_t hc_base[MAX_CONTROLLERS];
uint8_t hc_type[MAX_CONTROLLERS];
void hci_init(void)
{
int i;
struct pci_device *dev;
uint8_t prog_if;
for(i=0;i<MAX_CONTROLLERS; i++) {
hc_type[i] = 0xff;
}
/* Find a PCI_SERIAL_USB class device */
i=0;
num_controllers = 0;
while(num_controllers<MAX_CONTROLLERS) {
dev = pci_find_device(-1, -1, 0x0c03, -1, i);
if(!dev) break;
prog_if = ((dev->class>>8) & 0xff);
if(prog_if == 0x00 ) { // UHCI
hc_type[num_controllers] = prog_if;
uhc_init(dev);
}
else if(prog_if == 0x10) { // OHCI
hc_type[num_controllers] = prog_if;
ohc_init(dev);
}
#if 0
else if(prog_if == 0x20) { // EHCI
hc_type[num_controllers] = prog_if;
ehc_init(dev);
}
#endif
i++;
}
// From now should not change num_controllers any more
uhci_init();
ohci_init();
}
int next_usb_dev;
usbdev_t usb_device[MAX_USB_DEV];
void init_devices(void)
{
memset(usb_device,0,sizeof(usb_device));
usb_device[0].max_packet[0] = 8;
next_usb_dev=2; // 0 for all controller root hub, use MAX_CONTROLLERS instead???
// do we need have one for every controller ?? or just use hc_base and hc_type instead
// For example 0 --> controller 1 root hub
// 1 --> controller 2 root hub
// 2 --> controller 3 root hub....
}
inline int set_address( uchar address)
{
int ret;
ret = usb_control_msg(0, 0, SET_ADDRESS, address, 0, 0, NULL);
return(ret);
}
inline int clear_stall(uchar device, uchar endpoint)
{
int ret;
ret = usb_control_msg(device, CONTROL_ENDPOINT, CLEAR_FEATURE, FEATURE_HALT, endpoint, 0, NULL);
if(hc_type[device]==0x00) {
usb_device[device].toggle[endpoint]=0;
}
else if(hc_type[device]==0x10) {
usb_settoggle(&usb_device[device], endpoint & 0xf, ((endpoint & 0x80)>>7)^1, 0);
}
return(ret);
}
inline int device_reset(uchar device) {
return usb_control_msg(device, 0x21, 0xff, 0, 0, 0, NULL);
}
///////////////////////////////////////////////////////////////////////////////////////
//
// String Descriptors
//
//////////////////////////////////////////////////////////////////////////////////////
#define STRING_DESCRIPTOR 0x0300
int get_string( uchar addr, uchar string, int len, uchar *buffer)
{
int ret;
int i,j;
int real_len;
ushort lang;
if(!string) {
strcpy(buffer, "unknown");
return(0);
}
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, 0, 4, buffer);
real_len = buffer[0];
if(real_len>len)
real_len = len;
lang = buffer[2] | buffer[3]<<8;
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, lang, real_len, buffer);
// de-unicode it!
for(i=0, j=2; j<real_len; i++, j+=2)
buffer[i] = buffer[j];
buffer[i]=0;
real_len/=2;
return(real_len);
}
int get_string2( uchar addr, uchar string, ushort lang, int len, uchar *buffer)
{
int ret;
int i,j;
int real_len;
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, lang, len, buffer);
real_len = buffer[0];
if(real_len>len)
real_len = len;
if(real_len<=4) {
strcpy(buffer, "USB");
real_len = 3;
buffer[real_len] = 0;
} else {
// de-unicode it!
for(i=0, j=2; j<real_len; i++, j+=2)
buffer[i] = buffer[j];
buffer[i]=0;
real_len/=2;
}
return(real_len);
}
ushort get_lang( uchar addr, uchar string, int len, uchar *buffer)
{
int ret;
int i,j;
int real_len;
ushort lang;
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, STRING_DESCRIPTOR | string, 0, 4, buffer);
lang = buffer[2] | buffer[3]<<8;
return lang;
}
///////////////////////////////////////////////////////////////////////////////////////
//
// HUB functions. This will be moved to it's own module soonishly
//
///////////////////////////////////////////////////////////////////////////////////////
typedef struct port_charge {
ushort c_port_connection:1;
ushort c_port_enable:1;
ushort c_port_suspend:1;
ushort c_port_over_current:1;
ushort c_port_reset:1;
ushort reserved:11;
} port_change_t;
typedef struct port_status {
ushort port_connection:1;
ushort port_enable:1;
ushort port_suspend:1;
ushort port_over_current:1;
ushort port_reset:1;
ushort reserved:3;
ushort port_power:1;
ushort port_lowspeed:1;
ushort port_highspeed:1;
ushort port_test:1;
ushort port_indicator:1;
} __attribute__ ((packed)) portstatus_t;
typedef struct portstat {
portstatus_t stat;
port_change_t change;
} __attribute__ ((packed)) portstat_t;
int hub_port_reset( uchar addr, uchar port)
{
int ret;
int tries=100;
portstat_t status;
ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_RESET, port, 0, NULL); // reset port
while(tries--) {
udelay(10000);
ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, port, 4, &status);
if(!status.change.c_port_reset)
continue;
ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, C_PORT_RESET, port, 0, NULL); // clear status
return(0);
}
DPRINTF("hub_port_reset(%x, %x) failed,\n", addr, port);
dump_hex((uint8_t *)&status, 4, "status=");
return(-1);
}
int hub_port_resume( uchar addr, uchar port)
{
int ret;
int tries=100;
portstat_t status;
ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, PORT_SUSPEND, port, 0, NULL); // reset port
while(tries--) {
udelay(10000);
ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, port, 4, &status);
if(!status.change.c_port_suspend)
continue;
ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, C_PORT_SUSPEND, port, 0, NULL); // clear status
return(0);
}
return(-1);
}
int poll_hub(uchar addr)
{
int i;
int ret;
uchar devaddr=0;
hub_descriptor_t *desc;
portstat_t status;
DPRINTF("Poll hub (%x)\n", addr);
desc = usb_device[addr].private;
for(i=1; i<= desc->bNbrPorts; i++) {
ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, i, 4, &status);
// DPRINTF("Get status for port %u returns: %d\n", i, ret);
// dump_hex(&status, 4, "status=");
if(status.change.c_port_connection) {
ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, i, 0, NULL); // clear status
if(status.stat.port_connection) {
udelay(desc->bPwrOn2PwrGood * 20000);
hub_port_resume(addr, i);
ret = hub_port_reset(addr,i);
udelay(10);
ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_ENABLE, i, 0, NULL); // enable port
// ret = usb_control_msg(addr, 0xa3, GET_STATUS, 0x0, i, 4, &status);
// DPRINTF("*****Get status again for port %u returns: %d\n", i, ret);
// dump_hex(&status, 4, "status=");
devaddr = configure_device(i, usb_device[addr].controller, status.stat.port_lowspeed);
// configure
} else {
ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_SUSPEND, i, 0, NULL); // suspend port
ret = usb_control_msg(addr, 0x23, CLEAR_FEATURE, PORT_ENABLE, i, 0, NULL); // disable port
DPRINTF("Hub %d, Port %04x disconnected\n", addr, i);
// deconfigure
}
}
}
return(devaddr);
}
int usb_hub_init( uchar addr)
{
int i;
int ret;
hub_descriptor_t *desc;
desc = allot(sizeof(hub_descriptor_t));
memset(desc, 0 , sizeof(hub_descriptor_t));
DPRINTF("hub init (%d)\n", addr);
ret = usb_control_msg(addr, 0xa0, GET_DESCRIPTOR, 0x2900, 0, 8, desc);
ret = usb_control_msg(addr, 0xa0, GET_DESCRIPTOR, 0x2900, 0, desc->bLength, desc);
usb_device[addr].private = desc;
for(i=1; i<=desc->bNbrPorts; i++)
ret = usb_control_msg(addr, 0x23, SET_FEATURE, PORT_POWER, i, 0, NULL); // power port
// register hub to be polled
devpoll[num_polls] = poll_hub;
parm[num_polls++] = addr;
return(0);
}
extern void ohci_dump_x(uchar controller);
// will set up whatever device is answering at address 0.
int configure_device(uint32_t port, uchar controller, unsigned int lowspeed)
{
device_descriptor_t *desc;
config_descriptor_t *conf;
interface_descriptor_t *iface;
endpoint_descriptor_t *epd;
int ret;
int i;
int addr = next_usb_dev++;
uchar buffer[512];
uchar string[255];
ushort lang;
uchar x[2];
desc = (device_descriptor_t *) buffer;
memset( &usb_device[addr], 0, sizeof(usbdev_t));
printf("New USB device, setting address %d\n", addr);
if(lowspeed) {
usb_device[addr].lowspeed = usb_device[0].lowspeed = 1;
DPRINTF("LOWSPEED\n");
} else
usb_device[addr].lowspeed = usb_device[0].lowspeed = 0;
usb_device[0].port = usb_device[addr].port = port;
usb_device[0].controller = usb_device[addr].controller = controller;
usb_device[addr].toggle2[0]=0;
usb_device[addr].toggle2[1]=0;
// hc_clear_stat();
ret = set_address(addr);
if(ret<0) {
DPRINTF("configure_device: set_address failed!\n");
next_usb_dev--;
return(-1);
}
mdelay(10); /* Let the SET_ADDRESS settle */
usb_device[addr].max_packet[0] = 8;
DPRINTF("Fetching device descriptor length\n");
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x100, 0, 8, desc);
usb_device[addr].max_packet[0] = desc->max_packet;
DPRINTF("Fetching device descriptor\n");
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x100, 0, desc->bLength, desc);
if(ret < desc->bLength)
return(-1);
DPRINTF("Fetching config descriptor length\n");
conf = (config_descriptor_t *) (buffer + sizeof(device_descriptor_t));
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x200, 0, 8, conf);
DPRINTF("Fetching config descriptor\n");
ret = usb_control_msg(addr, 0x80, GET_DESCRIPTOR, 0x200, 0, conf->wTotalLength, conf);
if(ret < conf->wTotalLength)
return(-1);
iface = (interface_descriptor_t *) (buffer + sizeof(device_descriptor_t) + conf->bLength);
epd = (endpoint_descriptor_t *) (buffer + conf->bLength + iface->bLength + sizeof(device_descriptor_t));
DPRINTF("device:\n");
dump_device_descriptor( desc, "");
DPRINTF("config:\n");
dump_config_descriptor( (uchar *)conf, "");
DPRINTF("Selecting Configuration number %x:\n", conf->bConfigurationValue);
ret = usb_control_msg(addr, 0, SET_CONFIGURATION, conf->bConfigurationValue, 0, 0, NULL);
// mdelay(20);
#if 0
usb_control_msg(addr, 0x80, GET_CONFIGURATION, 0, 0, 1 , x);
DPRINTF("Configuration number = %x\n", x[0]);
usb_control_msg(addr, 0x80, GET_STATUS, 0, addr, 2, x);
DPRINTF("status = %x %x\n", x[0], x[1]);
usb_control_msg(addr, 0x81, GET_STATUS, 0, 0, 2, x);
DPRINTF("status = %x %x\n", x[0], x[1]);
#endif
for(i=0; i<iface->bNumEndpoints;i++) {
if(!epd[i].bEndpointAddress) {
usb_device[addr].max_packet[ 1 ] = epd[i].wMaxPacketSize & 0x3ff;
} else {
usb_device[addr].max_packet[ epd[i].bEndpointAddress & 0x7f ] = epd[i].wMaxPacketSize & 0x3ff;
}
if( (epd[i].bmAttributes & 0x03) == 0x01) // interrupt
usb_device[addr].interrupt = epd[i].bEndpointAddress;
if( (epd[i].bmAttributes & 0x03) == 0x02) { // bulk
#if 0
DPRINTF("clear stall on ep=%x\n", epd[i].bEndpointAddress);
clear_stall(addr, epd[i].bEndpointAddress); // to reset data toggle
udelay(10);
#endif
#if 0
usb_control_msg(addr, 0x82, GET_STATUS, 0, epd[i].bEndpointAddress, 2, x);
DPRINTF("status = %x %x\n", x[0], x[1]);
#endif
if(epd[i].bEndpointAddress & 0x80){ //in
usb_device[addr].bulk_in = epd[i].bEndpointAddress;
}
else { //out
usb_device[addr].bulk_out = epd[i].bEndpointAddress;
}
}
}
// determine device class
if(desc->Class) {
usb_device[addr].class = desc->Class;
usb_device[addr].subclass = desc->SubClass;
usb_device[addr].protocol = desc->protocol;
} else {
usb_device[addr].class = iface->bInterfaceClass;
usb_device[addr].subclass = iface->bInterfaceSubClass;
usb_device[addr].protocol = iface->bInterfaceProtocol;
}
printf("%02x:%02x:%02x\n", usb_device[addr].class, usb_device[addr].subclass, usb_device[addr].protocol);
#if 0
get_string(addr, desc->iManufacturor, sizeof(string), string);
printf("Manufacturor: %s\n", string);
get_string(addr, desc->iProduct, sizeof(string), string);
printf("Product: %s\n", string);
get_string(addr, desc->iSerial, sizeof(string), string);
printf("Serial: %s\n", string);
#else
lang = get_lang(addr, 0, sizeof(string), string);
get_string2(addr, desc->iManufacturor, lang, sizeof(string), string);
printf("Manufacturor: %s\n", string);
get_string2(addr, desc->iProduct, lang,sizeof(string), string);
printf("Product: %s\n", string);
get_string2(addr, desc->iSerial, lang, sizeof(string), string);
printf("Serial: %s\n", string);
#endif
switch( usb_device[addr].class) {
case 0x09: // hub
usb_hub_init(addr);
break;
default:
break;
}
DPRINTF("DEVICE CONFIGURED\n");
return(addr);
}
int num_polls=0;
int (*devpoll[MAX_POLLDEV])(uchar);
uchar parm[MAX_POLLDEV];
int poll_usb()
{
int addr;
int found=0;
int i;
int j;
for(i=0; i<num_controllers; i++) {
debug("poll_usb1 i=%d\t", i);
// if addr >0, should probably see what was attached!
if(hc_type[i]==0x00) {
addr = poll_u_root_hub(PORTSC1(i), i);
if(addr && !found)
found=addr;
addr = poll_u_root_hub(PORTSC2(i), i);
if(addr && !found)
found=addr;
}
else if(hc_type[i]==0x10) {
int NDP;
NDP = readl(&ohci_regs->roothub.a) & 0xff;
ohci_regs = (ohci_regs_t *)hc_base[i];
for(j=0;j<NDP;j++) {
addr = poll_o_root_hub((uint32_t)&ohci_regs->roothub.portstatus[j], i);
if(addr && !found)
found=addr;
}
}
}
// now poll registered drivers (such as the hub driver
for(i=0;i<num_polls; i++) {
debug("poll_usb2 i=%d\t", i);
addr = devpoll[i](parm[i]);
if(addr && !found)
found=addr;
}
return(found);
}
int usb_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data)
{
uint8_t hc_num = usb_device[devnum].controller;
if(ep&0x80) {
ep = usb_device[devnum].bulk_in;
} else {
ep = usb_device[devnum].bulk_out;
}
if(hc_type[hc_num] == 0x00) { //UHCI
return uhci_bulk_transfer(devnum, ep, len, data);
}
else if( hc_type[hc_num] == 0x10 ) { //OHCI
return ohci_bulk_transfer(devnum, ep, len, data);
}
#if 0
else if (hc_type[hc_num] == 0x20 ) { //EHCI
return ehci_bulk_transfer(devnum, ep, len, data);
}
#endif
return 0;
}
int usb_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex,
unsigned short wLength, void *data)
{
uint8_t hc_num = usb_device[devnum].controller;
if(hc_type[hc_num] == 0x00) { //UHCI
return uhci_control_msg(devnum, request_type, request, wValue, wIndex, wLength, data);
}
else if( hc_type[hc_num] == 0x10 ) { //OHCI
return ohci_control_msg(devnum, request_type, request, wValue, wIndex, wLength, data);
}
#if 0
else if (hc_type[hc_num] == 0x20 ) { //EHCI
return ehci_control_msg(devnum, request_type, request, wValue, wIndex, wLength, data);
}
#endif
return 0;
}
struct urb *usb_alloc_urb(int controller)
{
struct urb *urb;
ohci_t *ohci = NULL;
#if URB_PRE_ALLOCATE!=1
urb = (struct urb *)allot2(sizeof(struct urb),0xff);
if (!urb) {
printf("usb_alloc_urb: allot2 failed");
return NULL;
}
#else
if(hc_type[controller] == 0x10) { //OHCI
ohci = &_ohci_x[controller];
urb = ohci->urb;
} else {
urb = NULL;
}
#endif
memset(urb, 0, sizeof(*urb));
return urb;
}
/**
* usb_free_urb - frees the memory used by a urb
* @urb: pointer to the urb to free
*
* If an urb is created with a call to usb_create_urb() it should be
* cleaned up with a call to usb_free_urb() when the driver is finished
* with it.
*/
void usb_free_urb(struct urb* urb)
{
#if URB_PRE_ALLOCATE!=1
if (urb)
forget2(urb);
#endif
}
void usb_wait_urb_done(struct urb* urb, int timeout)
{
usbdev_t *usb_dev = urb->dev;
if(hc_type[usb_dev->controller]==0x10) {
ohci_wait_urb_done(urb, timeout);
}
}
int usb_submit_urb(struct urb *urb)
{
if (urb && urb->dev) {
#if 0
if(hc_type[urb->dev->controller] == 0x00) {
return uhci_submit_urb(urb);
} else
#endif
if(hc_type[urb->dev->controller] == 0x10) {
return ohci_submit_urb(urb);
}
#if 0
else if(hc_type[urb->dev->controller] == 0x20) {
return ohci_submit_urb(urb);
}
#endif
return 0;
}
else
return -ENODEV;
}
// Starts urb and waits for completion or timeout
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{
int status;
status = usb_submit_urb(urb);
//for OHCI We will check the BLF and CLF, because HC after processing all td list, it will clear the BLF and CLF
usb_wait_urb_done(urb, timeout);
//Add by LYH to call complete function
if(urb->complete!=0) urb->complete(urb);
if (actual_length)
*actual_length = urb->actual_length;
usb_free_urb(urb);
return status;
}
// returns status (negative) or length (positive)
int usb_internal_control_msg(struct usbdev *usb_dev, unsigned int pipe,
struct usb_ctrlrequest *cmd, void *data, int len, int timeout, usb_complete_t complete)
{
struct urb *urb;
int retv;
int length;
urb = usb_alloc_urb(usb_dev->controller);
if (!urb)
return -ENOMEM;
FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
complete,0);
retv = usb_start_wait_urb(urb, timeout, &length);
if (retv < 0)
return retv;
else
return length;
}
int usb_control_msg_x(struct usbdev *dev, unsigned int pipe, u8 request, u8 requesttype,
u16 value, u16 index, void *data, u16 size, int timeout, usb_complete_t complete)
{
struct usb_ctrlrequest *dr;
int ret;
int controller = dev->controller;
ohci_t *ohci;
#if URB_PRE_ALLOCATE!=1
dr = allot2(sizeof(struct usb_ctrlrequest), 0xf);
if (!dr) {
printf("usb_control_msg_x: dr allocate no MEM\n");
return -ENOMEM;
}
#else
if(hc_type[controller] == 0x10) { //OHCI
ohci = &_ohci_x[controller];
dr = ohci->dr;
} else {
dr = NULL;
}
#endif
dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16p(&value);
dr->wIndex = cpu_to_le16p(&index);
dr->wLength = cpu_to_le16p(&size);
ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout, complete);
#if URB_PRE_ALLOCATE!=1
forget2(dr);
#endif
return ret;
}
int usb_bulk_msg_x(struct usbdev *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout, usb_complete_t complete)
{
struct urb *urb;
if (len < 0)
return -EINVAL;
urb=usb_alloc_urb(usb_dev->controller);
if (!urb)
return -ENOMEM;
FILL_BULK_URB(urb, usb_dev, pipe, data, len,
complete, 0);
return usb_start_wait_urb(urb,timeout,actual_length);
}
#endif

View File

@ -1,435 +0,0 @@
#ifndef _USB_H
#define _USB_H
#define URB_PRE_ALLOCATE 1
#define u32 uint32_t
#define u16 uint16_t
#define u8 uint8_t
#define uchar uint8_t
#define ushort uint16_t
#define EBUSY 1
#define ENOMEM 12
#define ENODEV 19
#define EINVAL 22
#define EINPROGRESS 115
#define LINK_ADDR(x) ( virt_to_bus(x) >> 4)
#define MEM_ADDR(x) (void *) ( bus_to_virt( ((unsigned int) (x)) <<4) )
#define MAX_CONTROLLERS 4
extern int num_controllers;
extern uint32_t hc_base[];
extern uint8_t hc_type[];
// Some control message bmRequestType defines
#define CTRL_DEVICE 0
#define CONTROL_INTERFACE 1
#define CONTROL_ENDPOINT 2
#define CONTROL_OTHER 3
#define CONTROL_RECIPIENT_MASK 0x1f
#define CONTROL_TYPE_STD 0
#define CONTROL_TYPE_CLASS 0x20
#define CONTROL_CLASS_VENDOR 0x40
#define CONTROL_CLASS_MASK 0x60
#define CONTROL_OUT 0
#define CONTROL_IN 0x80
#define CONTROL_DIR_MASK 0x80
// bRequest values
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
#define SYNC_FRAME 12
// descriptor types
#define DEVICE_DESC 1
#define CONFIGURATION_DESC 2
#define STRING_DESC 3
#define INTERFACE_DESC 4
#define ENDPOINT_DESC 5
#define OTHERSPEED_DESC 7
#define POWER_DESC 8
typedef struct device_descriptor {
uchar bLength;
uchar type;
uchar bcdVersion[2];
uchar Class;
uchar SubClass;
uchar protocol;
uchar max_packet;
unsigned short idVendor;
unsigned short idProduct;
uchar bcdDevice[2];
uchar iManufacturor;
uchar iProduct;
uchar iSerial;
uchar bNumConfig;
} __attribute__((packed)) device_descriptor_t;
#define GET_DESCRIPTOR 6
typedef struct config_descriptor {
uchar bLength;
uchar type;
unsigned short wTotalLength;
uchar bNumInterfaces;
uchar bConfigurationValue;
uchar iConfiguration;
uchar bmAttributes;
uchar bMaxPower;
} __attribute__((packed)) config_descriptor_t;
typedef struct interface_descriptor {
uchar bLength;
uchar type;
uchar bInterfaceNumber;
uchar bAlternateSetting;
uchar bNumEndpoints;
uchar bInterfaceClass;
uchar bInterfaceSubClass;
uchar bInterfaceProtocol;
uchar iInterface;
} __attribute__((packed)) interface_descriptor_t;
typedef struct endpoint_descriptor {
uchar bLength;
uchar type;
uchar bEndpointAddress;
uchar bmAttributes;
unsigned short wMaxPacketSize;
uchar bInterval;
} __attribute__((packed)) endpoint_descriptor_t;
typedef struct ctrl_msg {
uchar bmRequestType;
uchar bRequest;
unsigned short wValue;
unsigned short wIndex;
unsigned short wLength;
} __attribute__((packed)) ctrl_msg_t;
// Some descriptors for hubs, will be moved later
typedef struct hub_descriptor {
uchar bLength;
uchar type;
uchar bNbrPorts;
ushort wHubCharacteristics;
uchar bPwrOn2PwrGood;
uchar bHubCntrCurrent;
uchar DeviceRemovable; // assume bNbrPorts <=8
uchar PortPwrCntrMask;
} __attribute__((packed)) hub_descriptor_t;
#define MAX_USB_DEV 127
#define MAX_EP 8
typedef struct usbdev {
uint32_t port;
uchar address;
uchar controller;
uchar class;
uchar subclass;
uchar protocol;
uchar bulk_in;
uchar bulk_out;
uchar interrupt;
uchar lowspeed;
uint32_t toggle2[2]; //For OHCI
uint32_t halted[2];
uchar toggle[MAX_EP]; //for UHCI
unsigned short max_packet[MAX_EP];
void *private;
} usbdev_t;
// I will use urb as transaction for OHCI to remember the td and ed
struct urb;
typedef void (*usb_complete_t)(struct urb *);
struct urb
{
#if 0
spinlock_t lock; // lock for the URB
#endif
void *hcpriv; // private data for host controller
#if 0
struct list_head urb_list; // list pointer to all active urbs
struct urb *next; // pointer to next URB
#endif
struct usbdev *dev; // pointer to associated USB device
unsigned int pipe; // pipe information
int status; // returned status
unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc.
void *transfer_buffer; // associated data buffer
void *transfer_dma; // dma addr for transfer_buffer
int transfer_buffer_length; // data buffer length
int actual_length; // actual data buffer length
int bandwidth; // bandwidth for this transfer request (INT or ISO)
unsigned char *setup_packet; // setup packet (control only)
void * setup_dma; // dma addr for setup_packet
//
int start_frame; // start frame (iso/irq only)
int number_of_packets; // number of packets in this request (iso)
int interval; // polling interval (irq only)
int error_count; // number of errors in this transfer (iso only)
int timeout; // timeout (in jiffies)
//
void *context; // context for completion routine
usb_complete_t complete; // pointer to completion routine
//
#if 0
struct iso_packet_descriptor iso_frame_desc[0];
#endif
};
typedef struct urb urb_t;
/*
* urb->transfer_flags:
*/
#define USB_DISABLE_SPD 0x0001
#define URB_SHORT_NOT_OK USB_DISABLE_SPD
#define USB_ISO_ASAP 0x0002
#define USB_ASYNC_UNLINK 0x0008
#define USB_QUEUE_BULK 0x0010
#define USB_NO_FSBR 0x0020
#define USB_ZERO_PACKET 0x0040 // Finish bulk OUTs always with zero length packet
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
/* ... less overhead for QUEUE_BULK */
#define USB_TIMEOUT_KILLED 0x1000 // only set by HCD!
struct usb_ctrlrequest {
u8 bRequestType;
u8 bRequest;
u16 wValue;
u16 wIndex;
u16 wLength;
} __attribute__ ((packed));
/*
* USB-status codes:
* USB_ST* maps to -E* and should go away in the future
*/
#define USB_ST_NOERROR 0
#define USB_ST_CRC (-EILSEQ)
#define USB_ST_BITSTUFF (-EPROTO)
#define USB_ST_NORESPONSE (-ETIMEDOUT) /* device not responding/handshaking */
#define USB_ST_DATAOVERRUN (-EOVERFLOW)
#define USB_ST_DATAUNDERRUN (-EREMOTEIO)
#define USB_ST_BUFFEROVERRUN (-ECOMM)
#define USB_ST_BUFFERUNDERRUN (-ENOSR)
#define USB_ST_INTERNALERROR (-EPROTO) /* unknown error */
#define USB_ST_SHORT_PACKET (-EREMOTEIO)
#define USB_ST_PARTIAL_ERROR (-EXDEV) /* ISO transfer only partially completed */
#define USB_ST_URB_KILLED (-ENOENT) /* URB canceled by user */
#define USB_ST_URB_PENDING (-EINPROGRESS)
#define USB_ST_REMOVED (-ENODEV) /* device not existing or removed */
#define USB_ST_TIMEOUT (-ETIMEDOUT) /* communication timed out, also in urb->status**/
#define USB_ST_NOTSUPPORTED (-ENOSYS)
#define USB_ST_BANDWIDTH_ERROR (-ENOSPC) /* too much bandwidth used */
#define USB_ST_URB_INVALID_ERROR (-EINVAL) /* invalid value/transfer type */
#define USB_ST_URB_REQUEST_ERROR (-ENXIO) /* invalid endpoint */
#define USB_ST_STALL (-EPIPE) /* pipe stalled, also in urb->status*/
/**
* FILL_CONTROL_URB - macro to help initialize a control urb
* @URB: pointer to the urb to initialize.
* @DEV: pointer to the struct usb_device for this urb.
* @PIPE: the endpoint pipe
* @SETUP_PACKET: pointer to the setup_packet buffer
* @TRANSFER_BUFFER: pointer to the transfer buffer
* @BUFFER_LENGTH: length of the transfer buffer
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
* Initializes a control urb with the proper information needed to submit
* it to a device. This macro is depreciated, the usb_fill_control_urb()
* function should be used instead.
*/
#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
(URB)->dev=DEV;\
(URB)->pipe=PIPE;\
(URB)->setup_packet=SETUP_PACKET;\
(URB)->transfer_buffer=TRANSFER_BUFFER;\
(URB)->transfer_buffer_length=BUFFER_LENGTH;\
(URB)->complete=COMPLETE;\
(URB)->context=CONTEXT;\
} while (0)
/**
* FILL_BULK_URB - macro to help initialize a bulk urb
* @URB: pointer to the urb to initialize.
* @DEV: pointer to the struct usb_device for this urb.
* @PIPE: the endpoint pipe
* @TRANSFER_BUFFER: pointer to the transfer buffer
* @BUFFER_LENGTH: length of the transfer buffer
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
* Initializes a bulk urb with the proper information needed to submit it
* to a device. This macro is depreciated, the usb_fill_bulk_urb()
* function should be used instead.
*/
#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
(URB)->dev=DEV;\
(URB)->pipe=PIPE;\
(URB)->transfer_buffer=TRANSFER_BUFFER;\
(URB)->transfer_buffer_length=BUFFER_LENGTH;\
(URB)->complete=COMPLETE;\
(URB)->context=CONTEXT;\
} while (0)
/*
* USB directions
*/
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
/*
* USB Packet IDs (PIDs)
*/
#define USB_PID_UNDEF_0 0xf0
#define USB_PID_OUT 0xe1
#define USB_PID_ACK 0xd2
#define USB_PID_DATA0 0xc3
#define USB_PID_PING 0xb4 /* USB 2.0 */
#define USB_PID_SOF 0xa5
#define USB_PID_NYET 0x96 /* USB 2.0 */
#define USB_PID_DATA2 0x87 /* USB 2.0 */
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
#define USB_PID_IN 0x69
#define USB_PID_NAK 0x5a
#define USB_PID_DATA1 0x4b
#define USB_PID_PREAMBLE 0x3c /* Token mode */
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
#define USB_PID_SETUP 0x2d
#define USB_PID_STALL 0x1e
#define USB_PID_MDATA 0x0f /* USB 2.0 */
#define PIPE_ISOCHRONOUS 0
#define PIPE_INTERRUPT 1
#define PIPE_CONTROL 2
#define PIPE_BULK 3
#define usb_maxpacket(dev, pipe, out) ((dev)->max_packet[usb_pipeendpoint(pipe)])
#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
#define usb_pipeslow(pipe) (((pipe) >> 26) & 1)
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
#define PIPE_DEVEP_MASK 0x0007ff00
/* The D0/D1 toggle bits */
#define usb_gettoggle(dev, ep, out) (((dev)->toggle2[out] >> (ep)) & 1)
#define usb_dotoggle(dev, ep, out) ((dev)->toggle2[out] ^= (1 << (ep)))
static inline void usb_settoggle(struct usbdev *dev,
unsigned int ep,
unsigned int out,
int bit)
{
dev->toggle2[out] &= ~(1 << ep);
dev->toggle2[out] |= bit << ep;
}
/* Endpoint halt control/status */
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
static inline unsigned int __create_pipe(usbdev_t *dev, unsigned int endpoint)
{
return (dev->address << 8) | (endpoint << 15) |
((dev->lowspeed == 1) << 26);
}
static inline unsigned int __default_pipe(struct usbdev *dev)
{
return ((dev->lowspeed == 1) << 26);
}
/* Create various pipes... */
#define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
#define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#if 0
#define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
#define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#endif
#define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#if 0
#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#endif
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
extern int next_usb_dev;
usbdev_t usb_device[MAX_USB_DEV];
void init_devices(void);
void hci_init(void);
int hc_init(struct pci_device *dev);
inline int set_address(uchar address);
inline int clear_stall(uchar device, uchar endpoint);
int poll_usb();
int configure_device(uint32_t port, uchar controller, unsigned int lowspeed);
int usb_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data);
int usb_control_msg( uchar devnum, uchar request_type, uchar request, unsigned short wValue, unsigned short wIndex,
unsigned short wLength, void *data);
int usb_control_msg_x(struct usbdev *dev, unsigned int pipe, u8 request, u8 requesttype,
u16 value, u16 index, void *data, u16 size, int timeout, usb_complete_t complete);
int usb_bulk_msg_x(struct usbdev *usb_dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout, usb_complete_t complete);
#endif

View File

@ -1,172 +0,0 @@
#ifdef USB_DISK
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
#include <etherboot.h>
#include <pci.h>
#include <timer.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_USB
#include <debug.h>
#define DPRINTF debug
#define uchar uint8_t
//#include "debug_x.h"
#include "usb_scsi_low.h"
int usb_bulk_transfer( uchar devnum, uchar ep, unsigned int len, uchar *data);
#define SG_DXFER_FROM_DEV -3
#define SG_DXFER_TO_DEV -2
#define REQUEST_SENSE 0x03
#define CBW_SIG 0x43425355
typedef struct usb_cbw {
unsigned int signature;
unsigned int tag;
unsigned int transfer_len; // this is exclusive of cbw and csw
uchar res1:7;
uchar direction:1; // 1 = device to host (read)
uchar lun:4;
uchar res:4;
uchar cbw_len:5; // the length of the SCSI command
uchar res3:3;
uchar scsi_cmd[16];
} __attribute__ ((packed)) usb_cbw_t;
#define CSW_SIG 0x53425355
typedef struct usb_csw {
unsigned int signature;
unsigned int tag;
unsigned int residue;
uchar status;
} __attribute__ ((packed)) usb_csw_t;
int scsi_command( uchar device, unsigned char *cmd, int cmd_len, int direction, unsigned char *data, int data_len, char *sense_data, int sense_len)
{
usb_cbw_t cbw;
usb_csw_t csw;
int ret;
memset(&cbw,0,sizeof(usb_cbw_t));
memset(&csw,0,sizeof(usb_csw_t));
cbw.signature = CBW_SIG;
cbw.tag = 777;
memcpy(cbw.scsi_cmd, cmd, cmd_len);
cbw.cbw_len = cmd_len;
if(direction == SG_DXFER_FROM_DEV)
cbw.direction=1;
cbw.transfer_len = data_len;
ret = usb_bulk_transfer(device, 2, sizeof(cbw), (uchar *) &cbw);
if(ret<0){
DPRINTF("ERROR:Bulk write:\n");
}
if(data_len) {
if(cbw.direction) {
DPRINTF("scsi_command reading %d bytes\n", data_len);
ret = usb_bulk_transfer(device, 0x81, data_len, data);
DPRINTF("scsi_command read %d bytes\n", ret);
if(ret<0 || ret <data_len) {
DPRINTF("ERROR:Bulk read data ret = %d\n", ret);
}
} else {
// DPRINTF("scsi_command writing %u bytes\n", data_len);
ret = usb_bulk_transfer(device, 0x2, data_len, data);
// DPRINTF("scsi_command wrote %u bytes\n", ret);
if(ret<0) {
DPRINTF("ERROR:Bulk write data\n");
}
}
}
// DPRINTF("scsi_command fetching csw\n");
ret = usb_bulk_transfer(device, 0x81, sizeof(csw), (uchar *) &csw);
// DPRINTF("scsi_command csw is %d bytes\n", ret);
if(ret<0 || ret < sizeof(csw)) {
DPRINTF("ERROR: Bulk read CSW ret = %d\n", ret);
return(-1);
}
if(csw.status) {
DPRINTF("CSW: residue = %08x, status = %02x\n", csw.residue, csw.status);
DPRINTF("Getting sense data\n");
request_sense( device, sense_data, sense_len);
return(-csw.status);
}
return(data_len - csw.residue);
}
int request_sense( uchar device, char *sense_data, int len)
{
usb_cbw_t cbw;
usb_csw_t csw;
int ret;
memset(&cbw,0,sizeof(usb_cbw_t));
memset(&csw,0,sizeof(usb_csw_t));
cbw.signature = CBW_SIG;
cbw.tag = 666;
cbw.scsi_cmd[0] = REQUEST_SENSE;
cbw.scsi_cmd[4] = len;
cbw.cbw_len = 6;
cbw.direction=1;
cbw.transfer_len = len;
ret = usb_bulk_transfer(device, 2, sizeof(usb_cbw_t), (uchar *) &cbw);
if(ret<0 || ret < sizeof(usb_cbw_t)) {
DPRINTF("ERROR: sense Bulk write ret = %d\n", ret);
}
ret = usb_bulk_transfer(device, 0x81, len, sense_data);
if(ret<0 || ret < len) {
DPRINTF("ERROR: sense Bulk read data ret = %d\n", ret);
}
ret = usb_bulk_transfer(device, 0x81, sizeof(usb_csw_t), (uchar *) &csw);
if(ret<0 || ret < sizeof(usb_csw_t)) {
DPRINTF("ERROR: sense Bulk read CSW ret = %d\n", ret);
}
return(-csw.status);
}
#endif

View File

@ -1,10 +0,0 @@
#ifndef _USB_SCSI_LOW_H
#define _USB_SCSI_LOW_H
#define SG_DXFER_FROM_DEV -3
#define SG_DXFER_TO_DEV -2
int scsi_command( unsigned char device, unsigned char *cmd, int cmd_len, int direction, unsigned char *data, int data_len, char *sense_data, int sense_len);
int request_sense( unsigned char device, char *sense_data, int len);
#endif

View File

@ -1,163 +0,0 @@
#ifdef USB_DISK
/*******************************************************************************
*
*
* Copyright 2003 Steven James <pyro@linuxlabs.com> and
* LinuxLabs http://www.linuxlabs.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
******************************************************************************/
#include <etherboot.h>
#include <pci.h>
#include <timer.h>
#include <lib.h>
#define DEBUG_THIS DEBUG_USB
#include <debug.h>
#define DPRINTF debug
#include "usb.h"
#include "scsi_cmds.h"
struct usbdisk_info_t {
struct controller *ctrl;
uint16_t heads;
uint16_t cylinders;
uint16_t sectors_per_track;
uint8_t model_number[41];
uint8_t slave;
sector_t sectors;
int address_mode;
#define ADDRESS_MODE_CHS 0
#define ADDRESS_MODE_LBA 1
#define ADDRESS_MODE_LBA48 2
#define ADDRESS_MODE_PACKET 3
uint32_t hw_sector_size;
unsigned drive_exists : 1;
unsigned slave_absent : 1;
unsigned removable : 1;
unsigned char usb_device_address;
};
struct usbdisk_info_t usbdisk_info;
#define TEST 0
#if TEST==1
#include "usb_scsi_low.h"
typedef struct partition_entry {
uchar boot_flag;
uchar chs[7];
unsigned int lba_start;
unsigned int lba_len;
} __attribute__ ((packed)) partition_entry_t;
typedef struct partition {
char loader[446];
partition_entry_t entry[4];
char sig[2];
} __attribute__ ((packed)) partition_t;
#endif
int usb_probe(int drive)
{
struct usbdisk_info_t *info = &usbdisk_info;
#if TEST==1
partition_t part;
unsigned char sense_data[32];
#endif
int i,res;
int error_count=100;
printf("LinuxLabs USB bootloader\n");
// outb( 0x30, 0x70); // reset primary boot
// outb( 0xff, 0x71);
init_devices();
hci_init();
info->usb_device_address = 0;
// find first usb device
while(error_count && (res = poll_usb())) // keep polling usb until no more devices are enumerated
if(res<0)
if(!--error_count)
printf("There is a USB device, but it won't init! This is a bad thing.\n");
for(i=0; i< next_usb_dev ; i++) {
if(usb_device[i].class == 0x08 && usb_device[i].subclass == 0x06 && usb_device[i].protocol == 0x50) {
printf("Found USB block device %d\n", i);
if(drive==0) {
info->usb_device_address = i;
break;
}
drive--;
}
}
if(info->usb_device_address == 0) return -1;
UnitReady(info->usb_device_address);
#if TEST==1
//Test
printf("Requesting initial sense data\n");
request_sense( info->usb_device_address, sense_data, 32);
PrintSense(sense_data, 32);
res = ll_read_block(info->usb_device_address, (uint8_t *)&part, 0, 1);
printf("ll_read_block returns %d\n", res);
res=-1;
debug("part address (phy) = %x, (virt) = %x\n", (uint32_t) virt_to_phys(&part), (uint32_t)&part);
for(i=0; i<4; i++) {
printf("%d: boot=%02x, start=%08x length=%08x\n",i, part.entry[i].boot_flag, part.entry[i].lba_start, part.entry[i]
.lba_len);
}
#endif
return 0;
}
int usb_read(int drive, sector_t sector, void *buffer)
{
struct usbdisk_info_t *info = &usbdisk_info;
int result;
int blocknum = sector;
int i;
// printf("sector= %d\t", blocknum);
result = ll_read_block(info->usb_device_address, buffer,blocknum, 1);
#if 0
for(i=0;i<128;i++) {
if((i%4)==0) printf("\n %08x:",i*4);
printf(" %08x ",(uint32_t)*((uint32_t *)buffer+i));
}
#endif
if(result!=512) return -1;
return 0;
}
#endif