From a47eec26c8e5b269852fde63b9e3767ed76c1f47 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 08:13:00 -0700 Subject: gpllib: Add disk library This library features read and write operations, as well as geometry detection. It will prevent duplicating code between several modules (e.g. hdt and chain.c32). Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/geom.h | 309 ++++++++++++++++++++++++++++++++++++++++++ com32/gplinclude/disk/read.h | 6 + com32/gplinclude/disk/util.h | 9 ++ com32/gplinclude/disk/write.h | 11 ++ com32/gpllib/Makefile | 3 +- com32/gpllib/disk/ata.c | 59 ++++++++ com32/gpllib/disk/geom.c | 250 ++++++++++++++++++++++++++++++++++ com32/gpllib/disk/read.c | 89 ++++++++++++ com32/gpllib/disk/util.c | 151 +++++++++++++++++++++ com32/gpllib/disk/write.c | 107 +++++++++++++++ 10 files changed, 993 insertions(+), 1 deletion(-) create mode 100644 com32/gplinclude/disk/geom.h create mode 100644 com32/gplinclude/disk/read.h create mode 100644 com32/gplinclude/disk/util.h create mode 100644 com32/gplinclude/disk/write.h create mode 100644 com32/gpllib/disk/ata.c create mode 100644 com32/gpllib/disk/geom.c create mode 100644 com32/gpllib/disk/read.c create mode 100644 com32/gpllib/disk/util.c create mode 100644 com32/gpllib/disk/write.c diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h new file mode 100644 index 00000000..4dda88bf --- /dev/null +++ b/com32/gplinclude/disk/geom.h @@ -0,0 +1,309 @@ +#ifndef _GEOM_H_ +#define _GEOM_H_ + +#include + +#define SECTOR 512 /* bytes/sector */ + +/* + * Disk parameters + */ +struct driveinfo { + int disk; + int ebios; /* EBIOS supported on this disk */ + int edd_version; /* EBIOS major version */ + int edd_functionality_subset; + int cbios; /* CHS geometry is valid */ + int heads; + int sectors; + int sectors_per_track; + int bytes_per_sector; + int cylinder; + int type; /* Drive type (AT/PS2 floppies only) */ + int drives; /* Number of drives */ + char host_bus_type[5]; + char interface_type[8]; +}; + +struct ebios_dapa { + uint16_t len; + uint16_t count; + uint16_t off; + uint16_t seg; + uint64_t lba; +}; + +/** + * INT 13 Extensions + * + * Note: if the size is less than 30 on call, the final DWORD will not be + * returned by a v2.x implementation; similarly for the Device Path info + **/ +struct device_parameter { + uint16_t len; /* size of returned data */ + /** + * Bitfields for IBM/MS INT 13 Extensions information flags: + * Bit(s) Description (Table 00274) + * 0 DMA boundary errors handled transparently + * 1 cylinder/head/sectors-per-track information is valid + * 2 removable drive + * 3 write with verify supported + * 4 drive has change-line support (required if drive >= 80h is removable) + * 5 drive can be locked (required if drive >= 80h is removable) + * 6 CHS information set to maximum supported values, not current media + * 15-7 reserved (0) + **/ + uint16_t info; /* information flags */ + uint32_t cylinders; /* number of physical cylinders on drive */ + uint32_t heads; /* number of physical heads on drive */ + uint32_t sectors_per_track; /* number of physical sectors per track */ + uint64_t sectors; /* total number of sectors on drive */ + uint16_t bytes_per_sector; /* bytes per sector */ + /* --- v2.0+ --- */ + uint32_t dpte_pointer; /* EDD configuration parameters, FFFFh:FFFFh if not available */ + /* --- v3.0 --- */ + uint16_t device_path_information; /* signature BEDDh to indicate presence of Device Path info */ + uint8_t device_path_length; /* length of Device Path information, including signature and this byte (24h for v3.0) */ + uint8_t device_path_reserved; /* reserved (0) */ + uint16_t device_path_reserved_2; /* reserved (0) */ + uint8_t host_bus_type[4]; /* ASCIZ name of host bus ("ISA" or "PCI") */ + uint8_t interface_type[8]; /* ASCIZ name of interface type + * "ATA" + * "ATAPI" + * "SCSI" + * "USB" + * "1394" IEEE 1394 (FireWire) + * "FIBRE" Fibre Channel + */ + /** + * Format of EDD v3.0 Interface Path: + * Offset Size Description (Table 00275) + * ---ISA--- + * 00h WORD 16-bit base address + * 02h 6 BYTEs reserved (0) + * ---PCI--- + * 00h BYTE PCI bus number + * 01h BYTE PCI device number + * 02h BYTE PCI function number + * 03h 5 BYTEs reserved (0) + **/ + union { + struct { + uint16_t base_address; + uint16_t reserved1; + uint32_t reserved2; + } __attribute__ ((packed)) isa; + struct { + uint8_t bus; + uint8_t slot; + uint8_t function; + uint8_t channel; + uint32_t reserved; + } __attribute__ ((packed)) pci; + /* pcix is same as pci */ + struct { + uint64_t reserved; + } __attribute__ ((packed)) ibnd; + struct { + uint64_t reserved; + } __attribute__ ((packed)) xprs; + struct { + uint64_t reserved; + } __attribute__ ((packed)) htpt; + struct { + uint64_t reserved; + } __attribute__ ((packed)) unknown; + } interface_path; + /** + * Format of EDD v3.0 Device Path: + * Offset Size Description (Table 00276) + * ---ATA--- + * 00h BYTE flag: 00h = master, 01h = slave + * 01h 7 BYTEs reserved (0) + * ---ATAPI--- + * 00h BYTE flag: 00h = master, 01h = slave + * 01h BYTE logical unit number + * 02h 6 BYTEs reserved (0) + * ---SCSI--- + * 00h BYTE logical unit number + * 01h 7 BYTEs reserved (0) + * ---USB--- + * 00h BYTE to be determined + * 01h 7 BYTEs reserved (0) + * ---IEEE1394--- + * 00h QWORD 64-bit FireWire General Unique Identifier (GUID) + * ---FibreChannel--- + * 00h QWORD Word Wide Number (WWN) + **/ + union { + struct { + uint8_t device; + uint8_t reserved1; + uint16_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) ata; + struct { + uint8_t device; + uint8_t lun; + uint8_t reserved1; + uint8_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) atapi; + struct { + uint16_t id; + uint64_t lun; + uint16_t reserved1; + uint32_t reserved2; + } __attribute__ ((packed)) scsi; + struct { + uint64_t serial_number; + uint64_t reserved; + } __attribute__ ((packed)) usb; + struct { + uint64_t eui; + uint64_t reserved; + } __attribute__ ((packed)) i1394; + struct { + uint64_t wwid; + uint64_t lun; + } __attribute__ ((packed)) fibre; + struct { + uint64_t identity_tag; + uint64_t reserved; + } __attribute__ ((packed)) i2o; + struct { + uint32_t array_number; + uint32_t reserved1; + uint64_t reserved2; + } __attribute__ ((packed)) raid; + struct { + uint8_t device; + uint8_t reserved1; + uint16_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) sata; + struct { + uint64_t reserved1; + uint64_t reserved2; + } __attribute__ ((packed)) unknown; + } device_path; + uint8_t reserved; /* reserved (0) */ + uint8_t cheksum; /* checksum of bytes 1Eh-40h (two's complement of sum, which makes + * the 8-bit sum of bytes 1Eh-41h equal 00h) */ +} __attribute__ ((packed)); + +/** + * Format of Phoenix Enhanced Disk Drive Spec translated drive parameter table: + * Offset Size Description (Table 00277) + * 00h WORD number of cylinders + * 02h BYTE number of heads + * 03h BYTE A0h (signature indicating translated table) + * 04h BYTE number of physical sectors per track + * 05h WORD starting write precompensation cylinder number + * 07h BYTE reserved + * 08h BYTE control byte (see #03198 at INT 41"DISK 0") + * 09h WORD number of physical cylinders + * 0Bh BYTE number of physical heads + * 0Ch WORD cylinder number of landing zone + * 0Eh BYTE number of logical sectors per track + * 0Fh BYTE checksum + * Program: the Phoenix Enhanced Disk Drive Specification is an addition to the + * IBM/MS INT 13 extensions + * + * Format of Phoenix Enhanced Disk Drive Spec Fixed Disk Parameter Table: + * Offset Size Description (Table 00278) + * 00h WORD physical I/O port base address + * 02h WORD disk-drive control port address + * 04h BYTE drive flags (see #00279) + * 05h BYTE proprietary information + * bits 7-4 reserved (0) + * bits 3-0: Phoenix proprietary (used by BIOS) + * 06h BYTE IRQ for drive (bits 3-0; bits 7-4 reserved and must be 0) + * 07h BYTE sector count for multi-sector transfers + * 08h BYTE DMA control + * bits 7-4: DMA type (0-2) as per ATA-2 specification + * bits 3-0: DMA channel + * 09h BYTE programmed I/O control + * bits 7-4: reserved (0) + * bits 3-0: PIO type (1-4) as per ATA-2 specification + * 0Ah WORD drive options (see #00280) + * 0Ch 2 BYTEs reserved (0) + * 0Eh BYTE extension revision level (high nybble=major, low nybble=minor) + * (currently 10h for v1.0 and 11h for v1.1-3.0) + * 0Fh BYTE 2's complement checksum of bytes 00h-0Eh + * 8-bit sum of all bytes 00h-0Fh should equal 00h + * SeeAlso: #00277 + * + * Bitfields for Phoenix Enhanced Disk Drive Spec drive flags: + * Bit(s) Description (Table 00279) + * 7 reserved (1) + * 6 LBA enabled + * 5 reserved (1) + * 4 drive is slave + * 3-0 reserved (0) + * SeeAlso: #00278,#00280 + * + * Bitfields for Phoenix Enhanced Disk Drive Spec drive options: + * Bit(s) Description (Table 00280) + * 0 fast PIO enabled + * 1 fast DMA access enabled + * 2 block PIO (multi-sector transfers) enabled + * 3 CHS translation enabled + * 4 LBA translation enabled + * 5 removable media + * 6 ATAPI device (CD-ROM) + * 7 32-bit transfer mode + * ---v1.1+ --- + * 8 ATAPI device uses DRQ to signal readiness for packet command + * (must be 0 if bit 6 is 0) + * 10-9 translation type (must be 00 if bit 3 is 0) + * 00 Phoenix bit-shifting translation + * 01 LBA-assisted translation + * 10 reserved + * 11 proprietary translation + * ---v3.0--- + * 11 Ultra DMA access enabled + * 15-12 reserved + **/ + +/* + * Values for diskette drive type: + * 01h 360K + * 02h 1.2M + * 03h 720K + * 04h 1.44M + * 05h ??? + * reportedly an obscure drive type shipped on some IBM machines, + * 2.88M on some machines (at least AMI 486 BIOS) + * 06h 2.88M + * 10h ATAPI Removable Media Device + */ +enum diskette_drive_types { + DISKETTE_360K = 1, + DISKETTE_1_2M = 2, + DISKETTE_720K = 3, + DISKETTE_1_44M = 4, + DISKETTE_2_88M = 6, + DISKETTE_ATAPI = 10, +}; + +/** + * chs_to_lba - compute lba value from cylinder, head and sector number + **/ +static inline int chs_to_lba(const struct driveinfo* drive_info, + const unsigned int cylinder, const unsigned int head, + const unsigned int sector) +{ + return (sector - 1) + (head * drive_info->sectors_per_track) + + (cylinder * (drive_info->heads + 1) * drive_info->sectors_per_track); +} + +void lba_to_chs(const struct driveinfo* drive_info, const int lba, + unsigned int* cylinder, unsigned int* head, + unsigned int* sector); +int get_drive_parameters(struct driveinfo *drive_info); + +#endif /* _GEOM_H */ diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h new file mode 100644 index 00000000..f8000a41 --- /dev/null +++ b/com32/gplinclude/disk/read.h @@ -0,0 +1,6 @@ +#ifndef _READ_H_ +#define _READ_H_ +void *dev_read(int drive, unsigned int lba, int sectors); +void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, + const int sectors); +#endif /* _READ_H */ diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h new file mode 100644 index 00000000..5a76e0c4 --- /dev/null +++ b/com32/gplinclude/disk/util.h @@ -0,0 +1,9 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include + +int int13_retry(const com32sys_t *inreg, com32sys_t *outreg); +void get_error(const int, char**); + +#endif /* _UTIL_H_ */ diff --git a/com32/gplinclude/disk/write.h b/com32/gplinclude/disk/write.h new file mode 100644 index 00000000..89ca8736 --- /dev/null +++ b/com32/gplinclude/disk/write.h @@ -0,0 +1,11 @@ +#ifndef _WRITE_H_ +#define _WRITE_H_ +int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, + const void *data, const int size); +int write_verify_sector(struct driveinfo* drive_info, + const unsigned int lba, + const void *data); +int write_verify_sectors(struct driveinfo* drive_info, + const unsigned int lba, + const void *data, const int size); +#endif diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 8e47d93f..4448b3a4 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -10,7 +10,8 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ - dmi/dmi_ipmi.o cpuid.o vpd/vpd.o + dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o \ + disk/util.o vpd/vpd.o BINDIR = /usr/bin LIBDIR = /usr/lib diff --git a/com32/gpllib/disk/ata.c b/com32/gpllib/disk/ata.c new file mode 100644 index 00000000..f1716ffa --- /dev/null +++ b/com32/gpllib/disk/ata.c @@ -0,0 +1,59 @@ +/** + * ata_id_string - Convert IDENTIFY DEVICE page into string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an even number. + * + * The strings in the IDENTIFY DEVICE page are broken up into + * 16-bit chunks. Run through the string, and output each + * 8-bit chunk linearly, regardless of platform. + * + * LOCKING: + * caller. + */ +void ata_id_string(const uint16_t * id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned int c; + + while (len > 0) { + c = id[ofs] >> 8; + *s = c; + s++; + + c = id[ofs] & 0xff; + *s = c; + s++; + + ofs++; + len -= 2; + } +} + +/** + * ata_id_c_string - Convert IDENTIFY DEVICE page into C string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an odd number. + * + * This function is identical to ata_id_string except that it + * trims trailing spaces and terminates the resulting string with + * null. @len must be actual maximum length (even number) + 1. + * + * LOCKING: + * caller. + */ +void ata_id_c_string(const uint16_t * id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned char *p; + + ata_id_string(id, s, ofs, len - 1); + + p = s + strnlen(s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c new file mode 100644 index 00000000..870b8d5b --- /dev/null +++ b/com32/gpllib/disk/geom.c @@ -0,0 +1,250 @@ +#include +#include +#include +#include + +#include + +/** + * lba_to_chs - split given lba into cylinders/heads/sectors + **/ +void lba_to_chs(const struct driveinfo* drive_info, const int lba, + unsigned int* cylinder, unsigned int* head, + unsigned int* sector) +{ + unsigned int track; + + *cylinder = (lba % drive_info->sectors_per_track) + 1; + track = lba / drive_info->sectors_per_track; + *head = track % drive_info->heads; + *sector = track / drive_info->heads; +} + +/** + * detect_extensions - detect if we can use extensions + * + * INT 13 - IBM/MS INT 13 Extensions - INSTALLATION CHECK + * AH = 41h + * BX = 55AAh + * DL = drive (80h-FFh) + * + * Return: CF set on error (extensions not supported) + * AH = 01h (invalid function) + * CF clear if successful + * BX = AA55h if installed + * AH = major version of extensions + * 01h = 1.x + * 20h = 2.0 / EDD-1.0 + * 21h = 2.1 / EDD-1.1 + * 30h = EDD-3.0 + * AL = internal use + * CX = API subset support bitmap (see #00271) + * DH = extension version (v2.0+ ??? -- not present in 1.x) + * + * Note: the Phoenix Enhanced Disk Drive Specification v1.0 uses version 2.0 of + * the INT 13 Extensions API + * + * Bitfields for IBM/MS INT 13 Extensions API support bitmap: + * Bit(s) Description (Table 00271) + * 0 extended disk access functions (AH=42h-44h,47h,48h) supported + * 1 removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) + * supported + * 2 enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported + * extended drive parameter table is valid (see #00273,#00278) + * 3-15 reserved (0) + **/ +static void detect_extensions(struct driveinfo* drive_info) +{ + com32sys_t getebios, ebios; + + memset(&getebios, 0, sizeof(com32sys_t)); + memset(&ebios, 0, sizeof(com32sys_t)); + + getebios.eax.w[0] = 0x4100; + getebios.ebx.w[0] = 0x55aa; + getebios.edx.b[0] = drive_info->disk; + getebios.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &getebios, &ebios); + + if ( !(ebios.eflags.l & EFLAGS_CF) && + ebios.ebx.w[0] == 0xaa55 ) { + drive_info->ebios = 1; + drive_info->edd_version = ebios.eax.b[1]; + drive_info->edd_functionality_subset = ebios.ecx.w[0]; + } +} + +/** + * get_drive_parameters_with_extensions - retrieve disk parameters via AH=48h + * + * INT 13 - IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS + * AH = 48h + * DL = drive (80h-FFh) + * DS:SI -> buffer for drive parameters + * Return: CF clear if successful + * AH = 00h + * DS:SI buffer filled + * CF set on error + * AH = error code (see #00234) + * BUG: several different Compaq BIOSes incorrectly report high-numbered + * drives (such as 90h, B0h, D0h, and F0h) as present, giving them the + * same geometry as drive 80h; as a workaround, scan through disk + * numbers, stopping as soon as the number of valid drives encountered + * equals the value in 0040h:0075h + **/ +static int get_drive_parameters_with_extensions(struct driveinfo* drive_info) +{ + com32sys_t inreg, outreg; + struct device_parameter dp; + + memset(&inreg, 0, sizeof(com32sys_t)); + memset(&outreg, 0, sizeof(com32sys_t)); + memset(&dp, 0, sizeof(struct device_parameter)); + + inreg.esi.w[0] = OFFS(__com32.cs_bounce); + inreg.ds = SEG(__com32.cs_bounce); + inreg.eax.w[0] = 0x4800; + inreg.edx.b[0] = drive_info->disk; + + __intcall(0x13, &inreg, &outreg); + + /* Saving bounce buffer before anything corrupts it */ + memcpy(&dp, __com32.cs_bounce, sizeof(struct device_parameter)); + + /* CF set on error */ + if ( outreg.eflags.l & EFLAGS_CF ) + return outreg.eax.b[1]; + + /* Override values found without extensions */ + drive_info->cylinder = dp.cylinders; + drive_info->heads = dp.heads; + drive_info->sectors = dp.sectors; + drive_info->bytes_per_sector = dp.bytes_per_sector; + + /* The rest of the functions is EDD v3.0+ only */ + if (drive_info->edd_version < 0x30) + return 0; + + /* "ISA" or "PCI" */ + strncpy(drive_info->host_bus_type, (char *) dp.host_bus_type, + sizeof drive_info->host_bus_type); + + strncpy(drive_info->interface_type, (char *) dp.interface_type, + sizeof drive_info->interface_type); + + if ( drive_info->sectors > 0 ) + drive_info->cbios = 1; /* Valid geometry */ + + return 0; +} + +/** + * get_drive_parameters_without_extensions - retrieve drive parameters via AH=08h + * + * INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI) + * AH = 08h + * DL = drive (bit 7 set for hard disk) + * + * Return: CF set on error + * AH = status (07h) (see #00234) + * CF clear if successful + * AH = 00h + * AL = 00h on at least some BIOSes + * BL = drive type (AT/PS2 floppies only) (see #00242) + * CH = low eight bits of maximum cylinder number + * CL = maximum sector number (bits 5-0) + * high two bits of maximum cylinder number (bits 7-6) + * DH = maximum head number + * DL = number of drives + * ES:DI -> drive parameter table (floppies only) + * + * Notes: + * - may return successful even though specified drive is greater than the + * number of attached drives of that type (floppy/hard); check DL to + * ensure validity + * - for systems predating the IBM AT, this call is only valid for hard + * disks, as it is implemented by the hard disk BIOS rather than the + * ROM BIOS + * - Toshiba laptops with HardRAM return DL=02h when called with DL=80h, + * but fail on DL=81h. The BIOS data at 40h:75h correctly reports 01h. + * may indicate only two drives present even if more are attached; to + * ensure a correct count, one can use AH=15h to scan through possible + * drives + * - for BIOSes which reserve the last cylinder for testing purposes, the + * cylinder count is automatically decremented + * on PS/1s with IBM ROM DOS 4, nonexistent drives return CF clear, + * BX=CX=0000h, and ES:DI = 0000h:0000h + * - the PC-Tools PCFORMAT program requires that AL=00h before it will + * proceed with the formatting + * + * BUG: several different Compaq BIOSes incorrectly report high-numbered + * drives (such as 90h, B0h, D0h, and F0h) as present, giving them the + * same geometry as drive 80h; as a workaround, scan through disk + * numbers, stopping as soon as the number of valid drives encountered + * equals the value in 0040h:0075h + * + * SeeAlso: AH=06h"Adaptec",AH=13h"SyQuest",AH=48h,AH=15h,INT 1E + * SeeAlso: INT 41"HARD DISK 0" + **/ +static int get_drive_parameters_without_extensions(struct driveinfo* drive_info) +{ + com32sys_t getparm, parm; + + memset(&getparm, 0, sizeof(com32sys_t)); + memset(&parm, 0, sizeof(com32sys_t)); + + getparm.eax.b[1] = 0x08; + getparm.edx.b[0] = drive_info->disk; + + __intcall(0x13, &getparm, &parm); + + /* CF set on error */ + if ( parm.eflags.l & EFLAGS_CF ) + return parm.eax.b[1]; + + /* DL contains the maximum drive number but it starts at 0! */ + drive_info->drives = parm.edx.b[0] + 1; + + // XXX broken + /* Drive specified greater than the bumber of attached drives */ + //if (drive_info->disk > drive_info->drives) + // return -1; + + drive_info->type = parm.ebx.b[0]; + + /* DH contains the maximum head number but it starts at 0! */ + drive_info->heads = parm.edx.b[1] + 1; + + /* Maximum sector number (bits 5-0) per track */ + drive_info->sectors_per_track = parm.ecx.b[0] & 0x3f; + + /* + * Maximum cylinder number: + * CH = low eight bits of maximum cylinder number + * CL = high two bits of maximum cylinder number (bits 7-6) + */ + drive_info->cylinder = parm.ecx.b[1] + + ((parm.ecx.b[0] & 0x40) * 256 + + (parm.ecx.b[0] & 0x80) * 512); + + if ( drive_info->sectors_per_track > 0 ) + drive_info->cbios = 1; /* Valid geometry */ + + return 0; +} + +/** + * get_drive_parameters - retrieve drive parameters + * @drive_info: driveinfo structure to fill + **/ +int get_drive_parameters(struct driveinfo *drive_info) +{ + detect_extensions(drive_info); + + if (drive_info->ebios) { + get_drive_parameters_without_extensions(drive_info); + return get_drive_parameters_with_extensions(drive_info); + } else + return get_drive_parameters_without_extensions(drive_info); +} diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c new file mode 100644 index 00000000..0e0be8ec --- /dev/null +++ b/com32/gpllib/disk/read.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include + +/** + * dev_read - read from a drive + * @drive: Drive number + * @lba: Position to start reading from + * @sectors: Number of sectors to read + * + * High-level routine to read from a hard drive. + **/ +void *dev_read(int drive, unsigned int lba, int sectors) +{ + struct driveinfo drive_info; + drive_info.disk = drive; + + return read_sectors(&drive_info, lba, sectors); +} + +/** + * read_sectors - read several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to read + * @sectors: Number of sectors to read + * + * Return a pointer to a malloc'ed buffer containing the data. + **/ +void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, + const int sectors) +{ + com32sys_t inreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; + void *data; + + if (get_drive_parameters(drive_info)) + return NULL; + + memset(&inreg, 0, sizeof inreg); + + if (drive_info->ebios) { + dapa->len = sizeof(*dapa); + dapa->count = sectors; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = drive_info->disk; + inreg.eax.b[1] = 0x42; /* Extended read */ + } else { + unsigned int c, h, s; + + if (!drive_info->cbios) { + /* We failed to get the geometry */ + if (lba) + return NULL; /* Can only read MBR */ + + s = 1; h = 0; c = 0; + } else + lba_to_chs(drive_info, lba, &s, &h, &c); + + if ( s > 63 || h > 256 || c > 1023 ) + return NULL; + + inreg.eax.w[0] = 0x0201; /* Read one sector */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = drive_info->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + /* Perform the read */ + if (int13_retry(&inreg, NULL)) + return NULL; /* Give up */ + + data = malloc(sectors * SECTOR); + if (data) + memcpy(data, buf, sectors * SECTOR); + + return data; +} diff --git a/com32/gpllib/disk/util.c b/com32/gpllib/disk/util.c new file mode 100644 index 00000000..7da8351d --- /dev/null +++ b/com32/gpllib/disk/util.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include + +#define MAX_NB_RETRIES 6 + +/** + * int13_retry - int13h with error handling + * @inreg: int13h function parameters + * @outreg: output registers + * + * Call int 13h, but with retry on failure. Especially floppies need this. + **/ +int int13_retry(const com32sys_t *inreg, com32sys_t *outreg) +{ + int retry = MAX_NB_RETRIES; /* Number of retries */ + com32sys_t tmpregs; + + if ( !outreg ) outreg = &tmpregs; + + while ( retry-- ) { + __intcall(0x13, inreg, outreg); + if ( !(outreg->eflags.l & EFLAGS_CF) ) + return 0; /* CF=0 => OK */ + } + + /* If we get here: error */ + return -1; +} + +/** + * get_error - decode a disk error status + * @status: Error code + * @buffer_ptr: Pointer to set to the error message + * + * A buffer will be allocated to contain the error message. + * @buffer_ptr will point to it. The caller will need to free it. + **/ +void get_error(int status, char** buffer_ptr) +{ + int buffer_size = (80 * sizeof(char)); + char* buffer = malloc(buffer_size); + *buffer_ptr = buffer; + + switch (status) { + case 0x0: + strncpy(buffer, "successful completion", buffer_size); + break; + case 0x01: + strncpy(buffer, "invalid function in AH or invalid parameter", buffer_size); + break; + case 0x02: + strncpy(buffer, "address mark not found", buffer_size); + break; + case 0x03: + strncpy(buffer, "disk write-protected", buffer_size); + break; + case 0x04: + strncpy(buffer, "sector not found/read error", buffer_size); + break; + case 0x05: + strncpy(buffer, "reset failed (hard disk)", buffer_size); + //strncpy(buffer, "data did not verify correctly (TI Professional PC)", buffer_size); + break; + case 0x06: + strncpy(buffer, "disk changed (floppy)", buffer_size); + break; + case 0x07: + strncpy(buffer, "drive parameter activity failed (hard disk)", buffer_size); + break; + case 0x08: + strncpy(buffer, "DMA overrun", buffer_size); + break; + case 0x09: + strncpy(buffer, "data boundary error (attempted DMA across 64K boundary or >80h sectors)", buffer_size); + break; + case 0x0A: + strncpy(buffer, "bad sector detected (hard disk)", buffer_size); + break; + case 0x0B: + strncpy(buffer, "bad track detected (hard disk)", buffer_size); + break; + case 0x0C: + strncpy(buffer, "unsupported track or invalid media", buffer_size); + break; + case 0x0D: + strncpy(buffer, "invalid number of sectors on format (PS/2 hard disk)", buffer_size); + break; + case 0x0E: + strncpy(buffer, "control data address mark detected (hard disk)", buffer_size); + break; + case 0x0F: + strncpy(buffer, "DMA arbitration level out of range (hard disk)", buffer_size); + break; + case 0x10: + strncpy(buffer, "uncorrectable CRC or ECC error on read", buffer_size); + break; + case 0x11: + strncpy(buffer, "data ECC corrected (hard disk)", buffer_size); + break; + case 0x20: + strncpy(buffer, "controller failure", buffer_size); + break; + case 0x31: + strncpy(buffer, "no media in drive (IBM/MS INT 13 extensions)", buffer_size); + break; + case 0x32: + strncpy(buffer, "incorrect drive type stored in CMOS (Compaq)", buffer_size); + break; + case 0x40: + strncpy(buffer, "seek failed", buffer_size); + break; + case 0x80: + strncpy(buffer, "timeout (not ready)", buffer_size); + break; + case 0xAA: + strncpy(buffer, "drive not ready (hard disk)", buffer_size); + break; + case 0xB0: + strncpy(buffer, "volume not locked in drive (INT 13 extensions)", buffer_size); + break; + case 0xB1: + strncpy(buffer, "volume locked in drive (INT 13 extensions)", buffer_size); + break; + case 0xB2: + strncpy(buffer, "volume not removable (INT 13 extensions)", buffer_size); + break; + case 0xB3: + strncpy(buffer, "volume in use (INT 13 extensions)", buffer_size); + break; + case 0xB4: + strncpy(buffer, "lock count exceeded (INT 13 extensions)", buffer_size); + break; + case 0xB5: + strncpy(buffer, "valid eject request failed (INT 13 extensions)", buffer_size); + break; + case 0xBB: + strncpy(buffer, "undefined error (hard disk)", buffer_size); + break; + case 0xCC: + strncpy(buffer, "write fault (hard disk)", buffer_size); + break; + case 0xE0: + strncpy(buffer, "status register error (hard disk)", buffer_size); + break; + case 0xFF: + strncpy(buffer, "sense operation failed (hard disk)", buffer_size); + break; + } +} diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c new file mode 100644 index 00000000..4b1ed702 --- /dev/null +++ b/com32/gpllib/disk/write.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + * write_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + * @size: Size of the buffer (number of sectors) + **/ +int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, + const void *data, const int size) +{ + com32sys_t inreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + size; + + memcpy(buf, data, size); + memset(&inreg, 0, sizeof inreg); + + if ( drive_info->ebios ) { + dapa->len = sizeof(*dapa); + dapa->count = size; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = drive_info->disk; + inreg.eax.w[0] = 0x4300; /* Extended write */ + } else { + unsigned int c, h, s; + + if ( !drive_info->cbios ) { + /* We failed to get the geometry */ + + if ( lba ) + return -1; /* Can only write MBR */ + + s = 1; h = 0; c = 0; + } else + lba_to_chs(drive_info, lba, &s, &h, &c); + + if ( s > 63 || h > 256 || c > 1023 ) + return -1; + + inreg.eax.w[0] = 0x0301; /* Write one sector */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = drive_info->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + /* Perform the write */ + if (int13_retry(&inreg, NULL)) + return -1; + else + return 0; +} + +/** + * write_verify_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + **/ +int write_verify_sector(struct driveinfo* drive_info, + const unsigned int lba, + const void *data) +{ + return write_verify_sectors(drive_info, lba, data, SECTOR); +} + +/** + * write_verify_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + * @size: Size of the buffer (number of sectors) + **/ +int write_verify_sectors(struct driveinfo* drive_info, + const unsigned int lba, + const void *data, const int size) +{ + char *rb; + int rv; + + rv = write_sectors(drive_info, lba, data, size); + if (rv) + return rv; /* Write failure */ + + rb = read_sectors(drive_info, lba, size); + if (!rb) + return -1; /* Readback failure */ + + rv = memcmp(data, rb, SECTOR); + free(rb); + return rv ? -1 : 0; +} -- cgit v1.2.1 From f04655c919826f5aa6711dca97143866f2e6cc0e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 08:20:09 -0700 Subject: hdt: Add disk mode (CLI) The disk mode features drives autodetection (geometry). Generic geometry code from hdt-ata.c has been replaced by the new disk gpllib. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-ata.c | 247 +---------------------------------------------- com32/hdt/hdt-ata.h | 50 +--------- com32/hdt/hdt-cli-disk.c | 71 ++++++++++++++ com32/hdt/hdt-cli.c | 7 ++ com32/hdt/hdt-cli.h | 8 +- com32/hdt/hdt-common.c | 35 ++++--- com32/hdt/hdt-common.h | 15 ++- 7 files changed, 126 insertions(+), 307 deletions(-) create mode 100644 com32/hdt/hdt-cli-disk.c diff --git a/com32/hdt/hdt-ata.c b/com32/hdt/hdt-ata.c index e0d6015c..9ba17ba8 100644 --- a/com32/hdt/hdt-ata.c +++ b/com32/hdt/hdt-ata.c @@ -30,252 +30,9 @@ #include #include #include -#include +#include +#include #include "com32io.h" #include "hdt-common.h" #include "hdt-ata.h" - -#ifdef ATA -/** - * ata_id_string - Convert IDENTIFY DEVICE page into string - * @id: IDENTIFY DEVICE results we will examine - * @s: string into which data is output - * @ofs: offset into identify device page - * @len: length of string to return. must be an even number. - * - * The strings in the IDENTIFY DEVICE page are broken up into - * 16-bit chunks. Run through the string, and output each - * 8-bit chunk linearly, regardless of platform. - * - * LOCKING: - * caller. - */ -void ata_id_string(const uint16_t * id, unsigned char *s, - unsigned int ofs, unsigned int len) -{ - unsigned int c; - - while (len > 0) { - c = id[ofs] >> 8; - *s = c; - s++; - - c = id[ofs] & 0xff; - *s = c; - s++; - - ofs++; - len -= 2; - } -} - -/** - * ata_id_c_string - Convert IDENTIFY DEVICE page into C string - * @id: IDENTIFY DEVICE results we will examine - * @s: string into which data is output - * @ofs: offset into identify device page - * @len: length of string to return. must be an odd number. - * - * This function is identical to ata_id_string except that it - * trims trailing spaces and terminates the resulting string with - * null. @len must be actual maximum length (even number) + 1. - * - * LOCKING: - * caller. - */ -void ata_id_c_string(const uint16_t * id, unsigned char *s, - unsigned int ofs, unsigned int len) -{ - unsigned char *p; - - //WARN_ON(!(len & 1)); - - ata_id_string(id, s, ofs, len - 1); - - p = s + strnlen(s, len - 1); - while (p > s && p[-1] == ' ') - p--; - *p = '\0'; -} -#endif - -/** - * Call int 13h, but with retry on failure. Especially floppies need this. - */ -int int13_retry(const com32sys_t * inreg, com32sys_t * outreg) -{ - int retry = 6; /* Number of retries */ - com32sys_t tmpregs; - - if (!outreg) - outreg = &tmpregs; - - while (retry--) { - __intcall(0x13, inreg, outreg); - if (!(outreg->eflags.l & EFLAGS_CF)) - return 0; /* CF=0, OK */ - } - - return -1; /* Error */ -} - -/* Display CPU registers for debugging purposes */ -void printregs(const com32sys_t * r) -{ - printf("eflags = %08x ds = %04x es = %04x fs = %04x gs = %04x\n" - "eax = %08x ebx = %08x ecx = %08x edx = %08x\n" - "ebp = %08x esi = %08x edi = %08x esp = %08x\n", - r->eflags.l, r->ds, r->es, r->fs, r->gs, - r->eax.l, r->ebx.l, r->ecx.l, r->edx.l, - r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l); -} - -/* Try to get information for a given disk */ -int get_disk_params(int disk, struct diskinfo *disk_info) -{ - static com32sys_t getparm, parm, getebios, ebios, inreg, outreg; - struct device_parameter dp; -#ifdef ATA - struct ata_identify_device aid; -#endif - - memset(&(disk_info[disk]), 0, sizeof(struct diskinfo)); - - disk_info[disk].disk = disk; - disk_info[disk].ebios = disk_info[disk].cbios = 0; - - /* Sending int 13h func 41h to query EBIOS information */ - memset(&getebios, 0, sizeof(com32sys_t)); - memset(&ebios, 0, sizeof(com32sys_t)); - - /* Get EBIOS support */ - getebios.eax.w[0] = 0x4100; - getebios.ebx.w[0] = 0x55aa; - getebios.edx.b[0] = disk; - getebios.eflags.b[0] = 0x3; /* CF set */ - - __intcall(0x13, &getebios, &ebios); - - /* Detecting EDD support */ - if (!(ebios.eflags.l & EFLAGS_CF) && - ebios.ebx.w[0] == 0xaa55 && (ebios.ecx.b[0] & 1)) { - disk_info[disk].ebios = 1; - switch (ebios.eax.b[1]) { - case 32: - strlcpy(disk_info[disk].edd_version, "1.0", 3); - break; - case 33: - strlcpy(disk_info[disk].edd_version, "1.1", 3); - break; - case 48: - strlcpy(disk_info[disk].edd_version, "3.0", 3); - break; - default: - strlcpy(disk_info[disk].edd_version, "0", 1); - break; - } - } - /* Get disk parameters -- really only useful for - * hard disks, but if we have a partitioned floppy - * it's actually our best chance... - */ - memset(&getparm, 0, sizeof(com32sys_t)); - memset(&parm, 0, sizeof(com32sys_t)); - getparm.eax.b[1] = 0x08; - getparm.edx.b[0] = disk; - - __intcall(0x13, &getparm, &parm); - - if (parm.eflags.l & EFLAGS_CF) - return disk_info[disk].ebios ? 0 : -1; - - disk_info[disk].heads = parm.edx.b[1] + 1; - disk_info[disk].sectors_per_track = parm.ecx.b[0] & 0x3f; - if (disk_info[disk].sectors_per_track == 0) { - disk_info[disk].sectors_per_track = 1; - } else { - disk_info[disk].cbios = 1; /* Valid geometry */ - } - - /* If geometry isn't valid, no need to try to get more info about the drive*/ - /* Looks like in can confuse some optical drives */ - if (disk_info[disk].cbios != 1) return 0; - -/* FIXME: memset to 0 make it fails - * memset(__com32.cs_bounce, 0, sizeof(struct device_pairameter)); */ - memset(&dp, 0, sizeof(struct device_parameter)); - memset(&inreg, 0, sizeof(com32sys_t)); - - /* Requesting Extended Read Drive Parameters via int13h func 48h */ - inreg.esi.w[0] = OFFS(__com32.cs_bounce); - inreg.ds = SEG(__com32.cs_bounce); - inreg.eax.w[0] = 0x4800; - inreg.edx.b[0] = disk; - - __intcall(0x13, &inreg, &outreg); - - /* Saving bounce buffer before anything corrupt it */ - memcpy(&dp, __com32.cs_bounce, sizeof(struct device_parameter)); - - if (outreg.eflags.l & EFLAGS_CF) { - more_printf("Disk 0x%X doesn't supports EDD 3.0\n", disk); - return -1; - } - - /* Copying result to the disk_info structure - * host_bus_type, interface_type, sectors & cylinders */ - snprintf(disk_info[disk].host_bus_type, - sizeof disk_info[disk].host_bus_type, "%c%c%c%c", - dp.host_bus_type[0], dp.host_bus_type[1], dp.host_bus_type[2], - dp.host_bus_type[3]); - snprintf(disk_info[disk].interface_type, - sizeof disk_info[disk].interface_type, "%c%c%c%c%c%c%c%c", - dp.interface_type[0], dp.interface_type[1], - dp.interface_type[2], dp.interface_type[3], - dp.interface_type[4], dp.interface_type[5], - dp.interface_type[6], dp.interface_type[7]); - disk_info[disk].sectors = dp.sectors; - disk_info[disk].cylinders = dp.cylinders; - - /*FIXME: we have to find a way to grab the model & fw - * We do put dummy data until we found a solution */ - snprintf(disk_info[disk].aid.model, sizeof disk_info[disk].aid.model, - "0x%X", disk); - snprintf(disk_info[disk].aid.fw_rev, sizeof disk_info[disk].aid.fw_rev, - "%s", "N/A"); - snprintf(disk_info[disk].aid.serial_no, - sizeof disk_info[disk].aid.serial_no, "%s", "N/A"); - - /* Useless stuff before I figure how to send ata packets */ -#ifdef ATA - memset(__com32.cs_bounce, 0, sizeof(struct device_parameter)); - memset(&aid, 0, sizeof(struct ata_identify_device)); - memset(&inreg, 0, sizeof inreg); - inreg.ebx.w[0] = OFFS(__com32.cs_bounce + 1024); - inreg.es = SEG(__com32.cs_bounce + 1024); - inreg.eax.w[0] = 0x2500; - inreg.edx.b[0] = disk; - - __intcall(0x13, &inreg, &outreg); - - memcpy(&aid, __com32.cs_bounce, sizeof(struct ata_identify_device)); - - if (outreg.eflags.l & EFLAGS_CF) { - more_printf("Disk 0x%X: Failed to Identify Device\n", disk); - //FIXME - return 0; - } -// ata_id_c_string(aid, disk_info[disk].fwrev, ATA_ID_FW_REV, sizeof(disk_info[disk].fwrev)); -// ata_id_c_string(aid, disk_info[disk].model, ATA_ID_PROD, sizeof(disk_info[disk].model)); - - char buff[sizeof(struct ata_identify_device)]; - memcpy(buff, &aid, sizeof(struct ata_identify_device)); - for (int j = 0; j < sizeof(struct ata_identify_device); j++) - more_printf("model=|%c|\n", buff[j]); - more_printf("Disk 0x%X : %s %s %s\n", disk, aid.model, aid.fw_rev, - aid.serial_no); -#endif - - return 0; -} diff --git a/com32/hdt/hdt-ata.h b/com32/hdt/hdt-ata.h index fee4d598..a9550837 100644 --- a/com32/hdt/hdt-ata.h +++ b/com32/hdt/hdt-ata.h @@ -30,6 +30,7 @@ #define DEFINE_HDT_ATA_H #include +#include #include "hdt.h" struct ata_identify_device { @@ -50,58 +51,13 @@ struct ata_identify_device { unsigned short words088_255[168]; } ATTR_PACKED; -struct diskinfo { - int disk; - int ebios; /* EBIOS supported on this disk */ - int cbios; /* CHS geometry is valid */ - int heads; - int sectors_per_track; - int sectors; - int cylinders; - char edd_version[4]; +struct ata_driveinfo { struct ata_identify_device aid; /* IDENTIFY xxx DEVICE data */ char host_bus_type[5]; char interface_type[9]; char interface_port; } ATTR_PACKED; -/* - * Get a disk block and return a malloc'd buffer. - * Uses the disk number and information from disk_info. - */ -struct ebios_dapa { - uint16_t len; - uint16_t count; - uint16_t off; - uint16_t seg; - uint64_t lba; -}; - -// BYTE=8 -// WORD=16 -// DWORD=32 -// QWORD=64 -struct device_parameter { - uint16_t len; - uint16_t info; - uint32_t cylinders; - uint32_t heads; - uint32_t sectors_per_track; - uint64_t sectors; - uint16_t bytes_per_sector; - uint32_t dpte_pointer; - uint16_t device_path_information; - uint8_t device_path_lenght; - uint8_t device_path_reserved; - uint16_t device_path_reserved_2; - uint8_t host_bus_type[4]; - uint8_t interface_type[8]; - uint64_t interace_path; - uint64_t device_path[2]; - uint8_t reserved; - uint8_t cheksum; -} ATTR_PACKED; - /* Useless stuff until I manage how to send ata packets */ #ifdef ATA enum { @@ -114,9 +70,7 @@ void ata_id_c_string(const uint16_t * id, unsigned char *s, unsigned int ofs, unsigned int len); void ata_id_string(const uint16_t * id, unsigned char *s, unsigned int ofs, unsigned int len); -int int13_retry(const com32sys_t * inreg, com32sys_t * outreg); void printregs(const com32sys_t * r); #endif -int get_disk_params(int disk, struct diskinfo *disk_info); #endif diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c new file mode 100644 index 00000000..6d9c3f06 --- /dev/null +++ b/com32/hdt/hdt-cli-disk.c @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_disk(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + int i = -1; + + detect_disks(hardware); + + for (int drive = 0x80; drive < 0xff; drive++) { + i++; + if (!hardware->disk_info[i].cbios) + continue; /* Invalid geometry */ + struct driveinfo *d = &hardware->disk_info[i]; + more_printf + ("DISK 0x%X:\n\ts/t=%d, sectors=%d, cylinders=%d, heads=%d, b/s=%d\n" + "\tBus type: %s, Interface type: %s\n\tEDD=%X (ebios=%d, cbios=%d)\n", + d->disk, d->sectors_per_track, d->sectors, d->cylinder, d->heads, + d->bytes_per_sector, d->host_bus_type, d->interface_type, + d->edd_version, d->ebios, d->cbios); + } +} + +struct cli_module_descr disk_show_modules = { + .modules = NULL, + .default_callback = main_show_disk, +}; + +struct cli_mode_descr disk_mode = { + .mode = DISK_MODE, + .name = CLI_DISK, + .default_modules = NULL, + .show_modules = &disk_show_modules, + .set_modules = NULL, +}; diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 3fd7ce41..21c7142d 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -43,6 +43,7 @@ struct cli_mode_descr *list_modes[] = { &cpu_mode, &pci_mode, &vesa_mode, + &disk_mode, }; /* @@ -177,6 +178,12 @@ void set_mode(cli_mode_t mode, struct s_hardware* hardware) snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_DMI); break; + case DISK_MODE: + detect_disks(hardware); + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", + CLI_DISK); + break; default: /* Invalid mode */ more_printf("Unknown mode, please choose among:\n"); diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 0b15fe97..07193bfe 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -64,6 +64,7 @@ #define CLI_COMMANDS "commands" #define CLI_DMI "dmi" #define CLI_CPU "cpu" +#define CLI_DISK "disk" #define CLI_SHOW_LIST "list" #define CLI_IRQ "irq" #define CLI_MODES "modes" @@ -79,6 +80,7 @@ typedef enum { KERNEL_MODE, SYSLINUX_MODE, VESA_MODE, + DISK_MODE, } cli_mode_t; #define PROMPT_SIZE 32 @@ -128,7 +130,7 @@ struct cli_alias { }; /* List of implemented modes */ -#define MAX_MODES 8 +#define MAX_MODES 9 struct cli_mode_descr *list_modes[MAX_MODES]; struct cli_mode_descr hdt_mode; struct cli_mode_descr dmi_mode; @@ -138,6 +140,7 @@ struct cli_mode_descr kernel_mode; struct cli_mode_descr cpu_mode; struct cli_mode_descr pci_mode; struct cli_mode_descr vesa_mode; +struct cli_mode_descr disk_mode; /* cli helpers */ void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found); @@ -173,6 +176,9 @@ void cli_detect_pci(struct s_hardware *hardware); // CPU STUFF void main_show_cpu(int argc, char **argv, struct s_hardware *hardware); +// DISK STUFF +void main_show_disk(int argc, char **argv, struct s_hardware *hardware); + // PXE STUFF void main_show_pxe(int argc, char **argv, struct s_hardware *hardware); diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index d02533ce..0328fa96 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -34,6 +34,7 @@ #include "../lib/sys/vesa/vesa.h" #include "hdt-common.h" #include "lib-ansi.h" +#include void detect_parameters(const int argc, const char *argv[], struct s_hardware *hardware) @@ -195,18 +196,28 @@ int detect_vesa(struct s_hardware *hardware) { /* Try to detect disks from port 0x80 to 0xff */ void detect_disks(struct s_hardware *hardware) { - hardware->disk_detection = true; - for (int drive = 0x80; drive < 0xff; drive++) { - if (get_disk_params(drive, hardware->disk_info) != 0) - continue; - struct diskinfo *d = &hardware->disk_info[drive]; - hardware->disks_count++; - more_printf - (" DISK 0x%X: %s : %s %s: sectors=%d, s/t=%d head=%d : EDD=%s\n", - drive, d->aid.model, d->host_bus_type, d->interface_type, - d->sectors, d->sectors_per_track, d->heads, - d->edd_version); - } + int i = -1; + int err; + char *error_msg; + + if (hardware->disk_detection) + return; + + hardware->disk_detection = true; + for (int drive = 0x80; drive < 0xff; drive++) { + i++; + hardware->disk_info[i].disk = drive; + err = get_drive_parameters(&hardware->disk_info[i]); + /* Do not show errors when a disk is not found (0x01) */ + if (err && err != 0x01) { + get_error(err, &error_msg); + more_printf("Error 0x%Xh while reading disk 0x%X:\n\t%s\n", + err, drive, error_msg); + free(error_msg); + } + hardware->disks_count++; + } + free(error_msg); } int detect_pxe(struct s_hardware *hardware) diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h index 43347b4a..7fe0e21c 100644 --- a/com32/hdt/hdt-common.h +++ b/com32/hdt/hdt-common.h @@ -32,6 +32,8 @@ #include #include "sys/pci.h" +#include + #include "cpuid.h" #include "dmi/dmi.h" #include "hdt-ata.h" @@ -54,6 +56,17 @@ extern int display_line_nb; display_line_nb++; \ } while (0); +/* Display CPU registers for debugging purposes */ +static inline void printregs(const com32sys_t * r) +{ + printf("eflags = %08x ds = %04x es = %04x fs = %04x gs = %04x\n" + "eax = %08x ebx = %08x ecx = %08x edx = %08x\n" + "ebp = %08x esi = %08x edi = %08x esp = %08x\n", + r->eflags.l, r->ds, r->es, r->fs, r->gs, + r->eax.l, r->ebx.l, r->ecx.l, r->edx.l, + r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l); +} + struct s_pxe { uint16_t vendor_id; uint16_t product_id; @@ -95,7 +108,7 @@ struct s_hardware { s_dmi dmi; /* DMI table */ s_cpu cpu; /* CPU information */ struct pci_domain *pci_domain; /* PCI Devices */ - struct diskinfo disk_info[256]; /* Disk Information */ + struct driveinfo disk_info[256]; /* Disk Information */ int disks_count; /* Number of detected disks */ struct s_pxe pxe; struct s_vesa vesa; -- cgit v1.2.1 From 3ff657d37c92d9fec9e9842216dfee3f5c21a6c3 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 08:26:34 -0700 Subject: hdt: Refactor disk menu Make the disk menu use the new disk library. Misc.: remove firmware, serial number and model information as they aren't detected yet. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 51 +++++++++++++---------------------------------- com32/hdt/hdt-menu.c | 3 ++- com32/hdt/hdt-menu.h | 4 ++-- 3 files changed, 18 insertions(+), 40 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 02f12f75..0498be7e 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -30,26 +30,15 @@ /* Compute the disk submenu */ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, - struct diskinfo *d, int disk_number) + struct driveinfo *d, int disk_number) { char buffer[MENULEN + 1]; char statbuffer[STATLEN + 1]; - /* No need to add no existing devices */ - if (strlen(d[disk_number].aid.model) <= 0) - return -1; - - snprintf(buffer, sizeof buffer, " Disk <%d> ", nb_sub_disk_menu); + snprintf(buffer, sizeof buffer, " Disk <0x%X> ", d[disk_number].disk); menu[nb_sub_disk_menu].menu = add_menu(buffer, -1); menu[nb_sub_disk_menu].items_count = 0; - snprintf(buffer, sizeof buffer, "Model : %s", - d[disk_number].aid.model); - snprintf(statbuffer, sizeof statbuffer, "Model: %s", - d[disk_number].aid.model); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - /* Compute device size */ char previous_unit[3], unit[3]; //GB int previous_size, size = d[disk_number].sectors / 2; // Converting to bytes @@ -80,20 +69,6 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Firmware Rev.: %s", - d[disk_number].aid.fw_rev); - snprintf(statbuffer, sizeof statbuffer, "Firmware Revision: %s", - d[disk_number].aid.fw_rev); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - - snprintf(buffer, sizeof buffer, "Serial Number: %s", - d[disk_number].aid.serial_no); - snprintf(statbuffer, sizeof statbuffer, "Serial Number: %s", - d[disk_number].aid.serial_no); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Interface : %s", d[disk_number].interface_type); snprintf(statbuffer, sizeof statbuffer, "Interface: %s", @@ -123,9 +98,9 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Cylinders : %d", - d[disk_number].cylinders); + d[disk_number].cylinder); snprintf(statbuffer, sizeof statbuffer, "Cylinders: %d", - d[disk_number].cylinders); + d[disk_number].cylinder); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; @@ -136,8 +111,8 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Port : 0x%X", disk_number); - snprintf(statbuffer, sizeof statbuffer, "Port: 0x%X", disk_number); + snprintf(buffer, sizeof buffer, "Port : 0x%X", d[disk_number].disk); + snprintf(statbuffer, sizeof statbuffer, "Port: 0x%X", d[disk_number].disk); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; @@ -152,7 +127,7 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, } /* Compute the Disks menu */ -void compute_disks(struct s_hdt_menu *menu, struct diskinfo *disk_info, struct s_hardware *hardware) +void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct s_hardware *hardware) { char buffer[MENULEN + 1]; int nb_sub_disk_menu = 0; @@ -161,17 +136,19 @@ void compute_disks(struct s_hdt_menu *menu, struct diskinfo *disk_info, struct s menu->disk_menu.items_count = 0; if (hardware->disks_count == 0) return; - for (int i = 0; i < 0xff; i++) { - if (compute_disk_module + for (int i = 0; i < hardware->disks_count; i++) { + if (!hardware->disk_info[i].cbios) + continue; /* Invalid geometry */ + compute_disk_module ((struct s_my_menu*) &(menu->disk_sub_menu), nb_sub_disk_menu, disk_info, - i) == 0) - nb_sub_disk_menu++; + i); + nb_sub_disk_menu++; } menu->disk_menu.menu = add_menu(" Disks ", -1); for (int i = 0; i < nb_sub_disk_menu; i++) { - snprintf(buffer, sizeof buffer, " Disk <%d> ", i); + snprintf(buffer, sizeof buffer, " Disk <%d> ", i+1); add_item(buffer, "Disk", OPT_SUBMENU, NULL, menu->disk_sub_menu[i].menu); menu->disk_menu.items_count++; diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index b531bc78..f7c1ba6f 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -286,8 +286,9 @@ void detect_hardware(struct s_hardware *hardware) printf("CPU: Detecting\n"); cpu_detect(hardware); - printf("DISKS: Detecting\n"); + printf("DISKS: Detecting..."); detect_disks(hardware); + printf("done (%d disks found).\n", hardware->disks_count); printf("DMI: Detecting Table\n"); if (detect_dmi(hardware) == -ENODMITABLE) { diff --git a/com32/hdt/hdt-menu.h b/com32/hdt/hdt-menu.h index 91809e2d..7b681007 100644 --- a/com32/hdt/hdt-menu.h +++ b/com32/hdt/hdt-menu.h @@ -91,8 +91,8 @@ void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware); // Disk Stuff int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, - struct diskinfo *d, int disk_number); -void compute_disks(struct s_hdt_menu *menu, struct diskinfo *disk_info, struct s_hardware *hardware); + struct driveinfo *d, int disk_number); +void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct s_hardware *hardware); // DMI Stuff void compute_motherboard(struct s_my_menu *menu, s_dmi * dmi); -- cgit v1.2.1 From 8fe215fbe966605735bee43f6c1fa639a96683da Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 08:39:08 -0700 Subject: hdt: Add `show disk' in hdt mode (CLI) It is now possible to see disks from hdt mode, via the `show disk' command. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-hdt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index b8c36ba1..82138458 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -284,6 +284,10 @@ struct cli_callback_descr list_hdt_show_modules[] = { .name = CLI_CPU, .exec = main_show_cpu, }, + { + .name = CLI_DISK, + .exec = main_show_disk, + }, { .name = CLI_PXE, .exec = main_show_pxe, -- cgit v1.2.1 From b3a2e8e00fc68898d000a15acd2a68ed0dc83c33 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 12:16:38 -0700 Subject: hdt: Remove inappropriate free() Impact: fix crash This extra free() is not needed, as the error buffer is already freed in the loop. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index d4f7cb21..84939844 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -263,7 +263,6 @@ void detect_disks(struct s_hardware *hardware) } hardware->disks_count++; } - free(error_msg); } int detect_pxe(struct s_hardware *hardware) -- cgit v1.2.1 From bb89cd3859a0a35d1237f26bf9290f2c9c7ea807 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 12:19:53 -0700 Subject: hdt: Fix EDD format (menu) The EDD version is more meaningful if displayed using an hexadecimal format: 01h = 1.x 20h = 2.0 / EDD-1.0 21h = 2.1 / EDD-1.1 30h = EDD-3.0 Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 0498be7e..30b13b80 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -116,9 +116,9 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "EDD Version : %s", + snprintf(buffer, sizeof buffer, "EDD Version : %X", d[disk_number].edd_version); - snprintf(statbuffer, sizeof statbuffer, "EDD Version: %s", + snprintf(statbuffer, sizeof statbuffer, "EDD Version: %X", d[disk_number].edd_version); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; -- cgit v1.2.1 From 4d684ab2b23ca677f8f3903bc9c8414ed2d12864 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 12:25:09 -0700 Subject: hdt: Remove misguiding printf() (disks) When detecting disks, we iterate through all ports. The number of disks scanned will always be 127, no matter how many are actually plugged in. Remove extra printf() when scanning. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index bac3d21f..5cfe8eda 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -293,9 +293,8 @@ void detect_hardware(struct s_hardware *hardware) printf("CPU: Detecting\n"); cpu_detect(hardware); - printf("DISKS: Detecting..."); + printf("DISKS: Detecting"); detect_disks(hardware); - printf("done (%d disks found).\n", hardware->disks_count); printf("DMI: Detecting Table\n"); if (detect_dmi(hardware) == -ENODMITABLE) { -- cgit v1.2.1 From 1608b94e6f4bc23f8f51598c3cdbb6e961a09ab8 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 12:27:51 -0700 Subject: hdt: Fix typo in device_parameter struct cheksum should read checksum. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/geom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h index 4dda88bf..54257aea 100644 --- a/com32/gplinclude/disk/geom.h +++ b/com32/gplinclude/disk/geom.h @@ -191,7 +191,7 @@ struct device_parameter { } __attribute__ ((packed)) unknown; } device_path; uint8_t reserved; /* reserved (0) */ - uint8_t cheksum; /* checksum of bytes 1Eh-40h (two's complement of sum, which makes + uint8_t checksum; /* checksum of bytes 1Eh-40h (two's complement of sum, which makes * the 8-bit sum of bytes 1Eh-41h equal 00h) */ } __attribute__ ((packed)); -- cgit v1.2.1 From 62edfe42a1863f69db0c486f705fec17519641c3 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 17:11:59 -0700 Subject: gpllib: Don't clobber legacy C/H/S parameters with EDD ones Impact: driveinfo structure change, new disk.c32 module Adapt driveinfo structure to store both legacy and EDD parameters. Change utility functions to use EDD when available (C/H/S being a fallback). Add a new disk.c32 module to test the disk library. It will print information (geometry) about every detected drive. Misc.: refactoring, set ES:DI to 0:0 when querying legacy C/H/S Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/geom.h | 53 ++++++++++++---------- com32/gpllib/disk/geom.c | 106 ++++++++++++++++++++----------------------- com32/modules/Makefile | 2 +- com32/modules/disk.c | 63 +++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 82 deletions(-) create mode 100644 com32/modules/disk.c diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h index 54257aea..f0c5b6dd 100644 --- a/com32/gplinclude/disk/geom.h +++ b/com32/gplinclude/disk/geom.h @@ -5,26 +5,6 @@ #define SECTOR 512 /* bytes/sector */ -/* - * Disk parameters - */ -struct driveinfo { - int disk; - int ebios; /* EBIOS supported on this disk */ - int edd_version; /* EBIOS major version */ - int edd_functionality_subset; - int cbios; /* CHS geometry is valid */ - int heads; - int sectors; - int sectors_per_track; - int bytes_per_sector; - int cylinder; - int type; /* Drive type (AT/PS2 floppies only) */ - int drives; /* Number of drives */ - char host_bus_type[5]; - char interface_type[8]; -}; - struct ebios_dapa { uint16_t len; uint16_t count; @@ -39,7 +19,7 @@ struct ebios_dapa { * Note: if the size is less than 30 on call, the final DWORD will not be * returned by a v2.x implementation; similarly for the Device Path info **/ -struct device_parameter { +struct edd_device_parameters { uint16_t len; /* size of returned data */ /** * Bitfields for IBM/MS INT 13 Extensions information flags: @@ -195,6 +175,25 @@ struct device_parameter { * the 8-bit sum of bytes 1Eh-41h equal 00h) */ } __attribute__ ((packed)); +/* + * Disk parameters + */ +struct driveinfo { + int disk; /* Disk port (0x80 - 0xff) */ + /* Legacy C/H/S */ + int cbios; /* CHS geometry is valid */ + int legacy_max_head; + int legacy_max_cylinder; + int legacy_sectors_per_track; + int legacy_max_drive; + int legacy_type; /* Drive type (AT/PS2 floppies only) */ + /* EDD support */ + int ebios; /* EBIOS supported on this disk */ + int edd_version; /* EBIOS major version */ + int edd_functionality_subset; + struct edd_device_parameters edd_params;/* EDD parameters */ +}; + /** * Format of Phoenix Enhanced Disk Drive Spec translated drive parameter table: * Offset Size Description (Table 00277) @@ -297,8 +296,16 @@ static inline int chs_to_lba(const struct driveinfo* drive_info, const unsigned int cylinder, const unsigned int head, const unsigned int sector) { - return (sector - 1) + (head * drive_info->sectors_per_track) + - (cylinder * (drive_info->heads + 1) * drive_info->sectors_per_track); + /* Use EDD, if valid */ + if (drive_info->edd_params.sectors_per_track > 0 && + drive_info->edd_params.heads > 0) + return (sector - 1) + (head * drive_info->edd_params.sectors_per_track) + + (cylinder * (drive_info->edd_params.heads) * + drive_info->edd_params.sectors_per_track); + else if (drive_info->cbios) + return (sector - 1) + (head * drive_info->legacy_sectors_per_track) + + (cylinder * (drive_info->legacy_max_head + 1) * + drive_info->legacy_sectors_per_track); } void lba_to_chs(const struct driveinfo* drive_info, const int lba, diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 870b8d5b..7bbb698d 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -14,10 +14,19 @@ void lba_to_chs(const struct driveinfo* drive_info, const int lba, { unsigned int track; - *cylinder = (lba % drive_info->sectors_per_track) + 1; - track = lba / drive_info->sectors_per_track; - *head = track % drive_info->heads; - *sector = track / drive_info->heads; + /* Use EDD, if valid */ + if (drive_info->edd_params.sectors_per_track > 0 && + drive_info->edd_params.heads > 0) { + *cylinder = (lba % drive_info->edd_params.sectors_per_track) + 1; + track = lba / drive_info->edd_params.sectors_per_track; + *head = track % drive_info->edd_params.heads; + *sector = track / drive_info->edd_params.heads; + } else if (drive_info->cbios) { + *cylinder = (lba % drive_info->legacy_sectors_per_track) + 1; + track = lba / drive_info->legacy_sectors_per_track; + *head = track % (drive_info->legacy_max_head + 1); + *sector = track / (drive_info->legacy_max_head + 1); + } } /** @@ -53,17 +62,17 @@ void lba_to_chs(const struct driveinfo* drive_info, const int lba, * extended drive parameter table is valid (see #00273,#00278) * 3-15 reserved (0) **/ -static void detect_extensions(struct driveinfo* drive_info) +static int detect_extensions(struct driveinfo* drive_info) { com32sys_t getebios, ebios; - memset(&getebios, 0, sizeof(com32sys_t)); - memset(&ebios, 0, sizeof(com32sys_t)); + memset(&getebios, 0, sizeof getebios); + memset(&ebios, 0, sizeof ebios); - getebios.eax.w[0] = 0x4100; + getebios.eflags.b[0] = 0x3; /* CF set */ getebios.ebx.w[0] = 0x55aa; getebios.edx.b[0] = drive_info->disk; - getebios.eflags.b[0] = 0x3; /* CF set */ + getebios.eax.b[1] = 0x41; __intcall(0x13, &getebios, &ebios); @@ -72,7 +81,9 @@ static void detect_extensions(struct driveinfo* drive_info) drive_info->ebios = 1; drive_info->edd_version = ebios.eax.b[1]; drive_info->edd_functionality_subset = ebios.ecx.w[0]; - } + return 0; + } else + return -1; /* Drive does not exist? */ } /** @@ -96,45 +107,22 @@ static void detect_extensions(struct driveinfo* drive_info) static int get_drive_parameters_with_extensions(struct driveinfo* drive_info) { com32sys_t inreg, outreg; - struct device_parameter dp; + struct device_parameter *dp = __com32.cs_bounce; - memset(&inreg, 0, sizeof(com32sys_t)); - memset(&outreg, 0, sizeof(com32sys_t)); - memset(&dp, 0, sizeof(struct device_parameter)); + memset(&inreg, 0, sizeof inreg); - inreg.esi.w[0] = OFFS(__com32.cs_bounce); - inreg.ds = SEG(__com32.cs_bounce); - inreg.eax.w[0] = 0x4800; + inreg.esi.w[0] = OFFS(dp); + inreg.ds = SEG(dp); inreg.edx.b[0] = drive_info->disk; + inreg.eax.b[1] = 0x48; __intcall(0x13, &inreg, &outreg); - /* Saving bounce buffer before anything corrupts it */ - memcpy(&dp, __com32.cs_bounce, sizeof(struct device_parameter)); - /* CF set on error */ if ( outreg.eflags.l & EFLAGS_CF ) return outreg.eax.b[1]; - /* Override values found without extensions */ - drive_info->cylinder = dp.cylinders; - drive_info->heads = dp.heads; - drive_info->sectors = dp.sectors; - drive_info->bytes_per_sector = dp.bytes_per_sector; - - /* The rest of the functions is EDD v3.0+ only */ - if (drive_info->edd_version < 0x30) - return 0; - - /* "ISA" or "PCI" */ - strncpy(drive_info->host_bus_type, (char *) dp.host_bus_type, - sizeof drive_info->host_bus_type); - - strncpy(drive_info->interface_type, (char *) dp.interface_type, - sizeof drive_info->interface_type); - - if ( drive_info->sectors > 0 ) - drive_info->cbios = 1; /* Valid geometry */ + memcpy(&drive_info->edd_params, dp, sizeof drive_info->edd_params); return 0; } @@ -191,11 +179,14 @@ static int get_drive_parameters_without_extensions(struct driveinfo* drive_info) { com32sys_t getparm, parm; - memset(&getparm, 0, sizeof(com32sys_t)); - memset(&parm, 0, sizeof(com32sys_t)); + memset(&getparm, 0, sizeof getparm); + memset(&parm, 0, sizeof parm); - getparm.eax.b[1] = 0x08; + /* Ralf Brown recommends setting ES:DI to 0:0 */ + getparm.esi.w[0] = 0; + getparm.ds = 0; getparm.edx.b[0] = drive_info->disk; + getparm.eax.b[1] = 0x08; __intcall(0x13, &getparm, &parm); @@ -203,32 +194,31 @@ static int get_drive_parameters_without_extensions(struct driveinfo* drive_info) if ( parm.eflags.l & EFLAGS_CF ) return parm.eax.b[1]; - /* DL contains the maximum drive number but it starts at 0! */ - drive_info->drives = parm.edx.b[0] + 1; + /* DL contains the maximum drive number (it starts at 0) */ + drive_info->legacy_max_drive = parm.edx.b[0]; // XXX broken /* Drive specified greater than the bumber of attached drives */ //if (drive_info->disk > drive_info->drives) // return -1; - drive_info->type = parm.ebx.b[0]; + drive_info->legacy_type = parm.ebx.b[0]; - /* DH contains the maximum head number but it starts at 0! */ - drive_info->heads = parm.edx.b[1] + 1; + /* DH contains the maximum head number (it starts at 0) */ + drive_info->legacy_max_head = parm.edx.b[1]; /* Maximum sector number (bits 5-0) per track */ - drive_info->sectors_per_track = parm.ecx.b[0] & 0x3f; + drive_info->legacy_sectors_per_track = parm.ecx.b[0] & 0x3f; /* * Maximum cylinder number: * CH = low eight bits of maximum cylinder number * CL = high two bits of maximum cylinder number (bits 7-6) */ - drive_info->cylinder = parm.ecx.b[1] + - ((parm.ecx.b[0] & 0x40) * 256 + - (parm.ecx.b[0] & 0x80) * 512); + drive_info->legacy_max_cylinder = parm.ecx.b[1] + + ((parm.ecx.b[0] & 0xc0) << 2); - if ( drive_info->sectors_per_track > 0 ) + if ( drive_info->legacy_sectors_per_track > 0 ) drive_info->cbios = 1; /* Valid geometry */ return 0; @@ -240,11 +230,11 @@ static int get_drive_parameters_without_extensions(struct driveinfo* drive_info) **/ int get_drive_parameters(struct driveinfo *drive_info) { - detect_extensions(drive_info); + if (detect_extensions(drive_info)) + return -1; - if (drive_info->ebios) { - get_drive_parameters_without_extensions(drive_info); - return get_drive_parameters_with_extensions(drive_info); - } else - return get_drive_parameters_without_extensions(drive_info); + if (drive_info->ebios) + get_drive_parameters_with_extensions(drive_info); + + return get_drive_parameters_without_extensions(drive_info); } diff --git a/com32/modules/Makefile b/com32/modules/Makefile index ba76268f..76604214 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -19,7 +19,7 @@ topdir = ../.. include ../MCONFIG MODULES = chain.c32 config.c32 ethersel.c32 mboot.c32 dmitest.c32 \ - cpuidtest.c32 \ + cpuidtest.c32 disk.c32 \ pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \ sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \ vpdtest.c32 diff --git a/com32/modules/disk.c b/com32/modules/disk.c new file mode 100644 index 00000000..84d737fb --- /dev/null +++ b/com32/modules/disk.c @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * 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, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include + +int main(int argc __attribute__ (( unused )), + char *argv[] __attribute__ (( unused ))) +{ + char* error_buffer; + int err; + struct driveinfo drive; + struct driveinfo *d = &drive; + + openconsole(&dev_null_r, &dev_stdcon_w); + + for (int disk = 0x80; disk < 0xff; disk++) { + memset(d, 0, sizeof(struct driveinfo)); + d->disk = disk; + err = get_drive_parameters(d); + + /* Do not print output when drive does not exists */ + if (err == -1) + continue; + + if (err) { + get_error(err, &error_buffer); + printf("Error 0x%Xh while reading disk 0x%X:\n %s\n", + err, d->disk, error_buffer); + free(error_buffer); + continue; + } + + printf("DISK 0x%X:\n", d->disk); + printf(" C/H/S: %d heads, %d cylinders\n", + d->legacy_max_head + 1, d->legacy_max_cylinder + 1); + printf(" %d sectors/track, %d drives\n", + d->legacy_sectors_per_track, d->legacy_max_drive); + printf(" EDD: ebios=%d, EDD version: %X\n", + d->ebios, d->edd_version); + printf(" %d heads, %d cylinders\n", + (int) d->edd_params.heads, (int) d->edd_params.cylinders); + printf(" %d sectors, %d bytes/sector, %d sectors/track\n", + (int) d->edd_params.sectors, (int) d->edd_params.bytes_per_sector, + (int) d->edd_params.sectors_per_track); + printf(" Host bus: %s, Interface type: %s\n\n", + d->edd_params.host_bus_type, d->edd_params.interface_type); + } + return 0; +} -- cgit v1.2.1 From a1d3996b00a34089500253ca20ff87d79a41a7dc Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 18:25:44 -0700 Subject: hdt: Adapt disk CLI/menu to new struct devinfo The struct devinfo has slightly changed. Reflect the changes in hdt. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 21 +++++++++++++++------ com32/hdt/hdt-common.c | 8 ++++++-- com32/hdt/hdt-menu-disk.c | 26 +++++++++++++------------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 6d9c3f06..a035b58c 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -48,12 +48,21 @@ void main_show_disk(int argc __unused, char **argv __unused, if (!hardware->disk_info[i].cbios) continue; /* Invalid geometry */ struct driveinfo *d = &hardware->disk_info[i]; - more_printf - ("DISK 0x%X:\n\ts/t=%d, sectors=%d, cylinders=%d, heads=%d, b/s=%d\n" - "\tBus type: %s, Interface type: %s\n\tEDD=%X (ebios=%d, cbios=%d)\n", - d->disk, d->sectors_per_track, d->sectors, d->cylinder, d->heads, - d->bytes_per_sector, d->host_bus_type, d->interface_type, - d->edd_version, d->ebios, d->cbios); + + more_printf("DISK 0x%X:\n", d->disk); + more_printf(" C/H/S: %d heads, %d cylinders\n", + d->legacy_max_head + 1, d->legacy_max_cylinder + 1); + more_printf(" %d sectors/track, %d drives\n", + d->legacy_sectors_per_track, d->legacy_max_drive); + more_printf(" EDD: ebios=%d, EDD version: %X\n", + d->ebios, d->edd_version); + more_printf(" %d heads, %d cylinders\n", + (int) d->edd_params.heads, (int) d->edd_params.cylinders); + more_printf(" %d sectors, %d bytes/sector, %d sectors/track\n", + (int) d->edd_params.sectors, (int) d->edd_params.bytes_per_sector, + (int) d->edd_params.sectors_per_track); + more_printf(" Host bus: %s, Interface type: %s\n\n", + d->edd_params.host_bus_type, d->edd_params.interface_type); } } diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 84939844..7be72557 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -254,8 +254,12 @@ void detect_disks(struct s_hardware *hardware) i++; hardware->disk_info[i].disk = drive; err = get_drive_parameters(&hardware->disk_info[i]); - /* Do not show errors when a disk is not found (0x01) */ - if (err && err != 0x01) { + + /* Do not print output when drive does not exists */ + if (err == -1) + continue; + + if (err) { get_error(err, &error_msg); more_printf("Error 0x%Xh while reading disk 0x%X:\n\t%s\n", err, drive, error_msg); diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 30b13b80..dc2d9a4c 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -41,7 +41,7 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, /* Compute device size */ char previous_unit[3], unit[3]; //GB - int previous_size, size = d[disk_number].sectors / 2; // Converting to bytes + int previous_size, size = d[disk_number].edd_params.sectors / 2; // Converting to bytes strlcpy(unit, "KB", 2); strlcpy(previous_unit, unit, 2); previous_size = size; @@ -70,44 +70,44 @@ int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Interface : %s", - d[disk_number].interface_type); + d[disk_number].edd_params.interface_type); snprintf(statbuffer, sizeof statbuffer, "Interface: %s", - d[disk_number].interface_type); + d[disk_number].edd_params.interface_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Host Bus : %s", - d[disk_number].host_bus_type); + d[disk_number].edd_params.host_bus_type); snprintf(statbuffer, sizeof statbuffer, "Host Bus Type: %s", - d[disk_number].host_bus_type); + d[disk_number].edd_params.host_bus_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Sectors : %d", - d[disk_number].sectors); + (int) d[disk_number].edd_params.sectors); snprintf(statbuffer, sizeof statbuffer, "Sectors: %d", - d[disk_number].sectors); + (int) d[disk_number].edd_params.sectors); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Heads : %d", - d[disk_number].heads); + d[disk_number].legacy_max_head + 1); snprintf(statbuffer, sizeof statbuffer, "Heads: %d", - d[disk_number].heads); + d[disk_number].legacy_max_head + 1); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Cylinders : %d", - d[disk_number].cylinder); + d[disk_number].legacy_max_cylinder + 1); snprintf(statbuffer, sizeof statbuffer, "Cylinders: %d", - d[disk_number].cylinder); + d[disk_number].legacy_max_cylinder + 1); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Sectors/Track: %d", - d[disk_number].sectors_per_track); + d[disk_number].legacy_sectors_per_track); snprintf(statbuffer, sizeof statbuffer, "Sectors per Track: %d", - d[disk_number].sectors_per_track); + d[disk_number].legacy_sectors_per_track); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; -- cgit v1.2.1 From d48c9f289d527656480199e844103a9907ebc4c5 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 18:26:39 -0700 Subject: disk.c32: Fix indentation Impact: none Fix indentation for the loop ending curly brace. Signed-off-by: Pierre-Alexandre Meyer --- com32/modules/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/modules/disk.c b/com32/modules/disk.c index 84d737fb..e94a36bf 100644 --- a/com32/modules/disk.c +++ b/com32/modules/disk.c @@ -58,6 +58,6 @@ int main(int argc __attribute__ (( unused )), (int) d->edd_params.sectors_per_track); printf(" Host bus: %s, Interface type: %s\n\n", d->edd_params.host_bus_type, d->edd_params.interface_type); - } + } return 0; } -- cgit v1.2.1 From 8f67b34b0b99fbae6264dc0a34331d557e674b86 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 21:06:39 -0700 Subject: gpllib: Add read_mbr helper (disk) Impact: disk API extension read_mbr takes a drive number and returns a pointer to a malloced buffer containing its mbr. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/read.h | 1 + com32/gpllib/disk/read.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h index f8000a41..79c79524 100644 --- a/com32/gplinclude/disk/read.h +++ b/com32/gplinclude/disk/read.h @@ -1,5 +1,6 @@ #ifndef _READ_H_ #define _READ_H_ +void *read_mbr(int drive); void *dev_read(int drive, unsigned int lba, int sectors); void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, const int sectors); diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index 0e0be8ec..1db60fdd 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -5,6 +5,17 @@ #include #include +/** + **/ +void *read_mbr(int drive) +{ + struct driveinfo drive_info; + drive_info.disk = drive; + + /* MBR: lba = 0, 1 sector */ + return read_sectors(&drive_info, 0, 1); +} + /** * dev_read - read from a drive * @drive: Drive number @@ -37,7 +48,7 @@ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; void *data; - if (get_drive_parameters(drive_info)) + if (get_drive_parameters(drive_info) == -1) return NULL; memset(&inreg, 0, sizeof inreg); @@ -59,14 +70,14 @@ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, if (!drive_info->cbios) { /* We failed to get the geometry */ if (lba) - return NULL; /* Can only read MBR */ + return NULL; /* Can only read MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); if ( s > 63 || h > 256 || c > 1023 ) - return NULL; + return NULL; inreg.eax.w[0] = 0x0201; /* Read one sector */ inreg.ecx.b[1] = c & 0xff; -- cgit v1.2.1 From cdddfb9f7db5fc1d28fbdd3229823bb912c49c4d Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 21:09:21 -0700 Subject: gpllib: Add partition table structure (disk) Impact: disk API extension Add part_entry structure to describe DOS partition tables. The new get_label call translates a label id to a meaningful string describing the partition. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/util.h | 16 +++ com32/gpllib/Makefile | 2 +- com32/gpllib/disk/labels.c | 244 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 com32/gpllib/disk/labels.c diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h index 5a76e0c4..b6cb1850 100644 --- a/com32/gplinclude/disk/util.h +++ b/com32/gplinclude/disk/util.h @@ -3,7 +3,23 @@ #include +#define PARTITION_TABLES_OFFSET 0x1be +/* A DOS partition table entry */ +struct part_entry { + uint8_t active_flag; /* 0x80 if "active" */ + uint8_t start_head; + uint8_t start_sect; + uint8_t start_cyl; + uint8_t ostype; + uint8_t end_head; + uint8_t end_sect; + uint8_t end_cyl; + uint32_t start_lba; + uint32_t length; +} __attribute__((packed)); + int int13_retry(const com32sys_t *inreg, com32sys_t *outreg); void get_error(const int, char**); +void get_label(int label, char** buffer_label); #endif /* _UTIL_H_ */ diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 4448b3a4..39df17b4 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -11,7 +11,7 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o \ - disk/util.o vpd/vpd.o + disk/util.o disk/labels.o vpd/vpd.o BINDIR = /usr/bin LIBDIR = /usr/lib diff --git a/com32/gpllib/disk/labels.c b/com32/gpllib/disk/labels.c new file mode 100644 index 00000000..0f3a0cc1 --- /dev/null +++ b/com32/gpllib/disk/labels.c @@ -0,0 +1,244 @@ +#include +#include + +void get_label(int label, char** buffer_label) +{ + int buffer_size = (80 * sizeof(char)); + char* buffer = malloc(buffer_size); + *buffer_label = buffer; + + switch (label) { + case 0x01: strncpy(buffer, "DOS 12-bit fat", buffer_size); break; + case 0x02: strncpy(buffer, "XENIX root", buffer_size); break; + case 0x03: strncpy(buffer, "XENIX /usr", buffer_size); break; + case 0x04: strncpy(buffer, "DOS 3.0+ 16-bit FAT (up to 32M)", buffer_size); break; + case 0x05: strncpy(buffer, "DOS 3.3+ Extended Partition", buffer_size); break; + case 0x06: strncpy(buffer, "DOS 3.31+ 16-bit FAT (over 32M)", buffer_size); break; + case 0x07: strncpy(buffer, "OS/2 IFS (e.g., HPFS)", buffer_size); break; + //case 0x07: strncpy(buffer, "Advanced Unix", buffer_size); break; + //case 0x07: strncpy(buffer, "Windows NT NTFS", buffer_size); break; + //case 0x07: strncpy(buffer, "QNX2.x (pre-1988)", buffer_size); break; + case 0x08: strncpy(buffer, "OS/2 (v1.0-1.3 only)", buffer_size); break; + //case 0x08: strncpy(buffer, "AIX boot partition", buffer_size); break; + //case 0x08: strncpy(buffer, "SplitDrive", buffer_size); break; + //case 0x08: strncpy(buffer, "DELL partition spanning multiple drives", buffer_size); break; + //case 0x08: strncpy(buffer, "Commodore DOS", buffer_size); break; + //case 0x08: strncpy(buffer, "QNX 1.x and 2.x ("qny")", buffer_size); break; + case 0x09: strncpy(buffer, "AIX data partition", buffer_size); break; + //case 0x09: strncpy(buffer, "Coherent filesystem", buffer_size); break; + //case 0x09: strncpy(buffer, "QNX 1.x and 2.x ("qnz")", buffer_size); break; + case 0x0a: strncpy(buffer, "OS/2 Boot Manager", buffer_size); break; + //case 0x0a: strncpy(buffer, "Coherent swap partition", buffer_size); break; + //case 0x0a: strncpy(buffer, "OPUS", buffer_size); break; + case 0x0b: strncpy(buffer, "WIN95 OSR2 32-bit FAT", buffer_size); break; + case 0x0c: strncpy(buffer, "WIN95 OSR2 32-bit FAT, LBA-mapped", buffer_size); break; + case 0x0e: strncpy(buffer, "WIN95: DOS 16-bit FAT, LBA-mapped", buffer_size); break; + case 0x0f: strncpy(buffer, "WIN95: Extended partition, LBA-mapped", buffer_size); break; + case 0x10: strncpy(buffer, "OPUS (?)", buffer_size); break; + case 0x11: strncpy(buffer, "Hidden DOS 12-bit FAT", buffer_size); break; + case 0x12: strncpy(buffer, "Compaq config partition", buffer_size); break; + case 0x14: strncpy(buffer, "Hidden DOS 16-bit FAT <32M", buffer_size); break; + case 0x16: strncpy(buffer, "Hidden DOS 16-bit FAT >=32M", buffer_size); break; + case 0x17: strncpy(buffer, "Hidden IFS (e.g., HPFS)", buffer_size); break; + case 0x18: strncpy(buffer, "AST SmartSleep Partition", buffer_size); break; + case 0x19: strncpy(buffer, "Unused (Claimed for Willowtech Photon COS)", buffer_size); break; + case 0x1b: strncpy(buffer, "Hidden WIN95 OSR2 32-bit FAT", buffer_size); break; + case 0x1c: strncpy(buffer, "Hidden WIN95 OSR2 32-bit FAT, LBA-mapped", buffer_size); break; + case 0x1e: strncpy(buffer, "Hidden WIN95 16-bit FAT, LBA-mapped", buffer_size); break; + case 0x20: strncpy(buffer, "Unused", buffer_size); break; + case 0x21: strncpy(buffer, "Reserved", buffer_size); break; + //case 0x21: strncpy(buffer, "Unused", buffer_size); break; + case 0x22: strncpy(buffer, "Unused", buffer_size); break; + case 0x23: strncpy(buffer, "Reserved", buffer_size); break; + case 0x24: strncpy(buffer, "NEC DOS 3.x", buffer_size); break; + case 0x26: strncpy(buffer, "Reserved", buffer_size); break; + case 0x31: strncpy(buffer, "Reserved", buffer_size); break; + case 0x32: strncpy(buffer, "NOS", buffer_size); break; + case 0x33: strncpy(buffer, "Reserved", buffer_size); break; + case 0x34: strncpy(buffer, "Reserved", buffer_size); break; + case 0x35: strncpy(buffer, "JFS on OS/2 or eCS", buffer_size); break; + case 0x36: strncpy(buffer, "Reserved", buffer_size); break; + case 0x38: strncpy(buffer, "THEOS ver 3.2 2gb partition", buffer_size); break; + case 0x39: strncpy(buffer, "Plan 9 partition", buffer_size); break; + //case 0x39: strncpy(buffer, "THEOS ver 4 spanned partition", buffer_size); break; + case 0x3a: strncpy(buffer, "THEOS ver 4 4gb partition", buffer_size); break; + case 0x3b: strncpy(buffer, "THEOS ver 4 extended partition", buffer_size); break; + case 0x3c: strncpy(buffer, "PartitionMagic recovery partition", buffer_size); break; + case 0x3d: strncpy(buffer, "Hidden NetWare", buffer_size); break; + case 0x40: strncpy(buffer, "Venix 80286", buffer_size); break; + case 0x41: strncpy(buffer, "Linux/MINIX (sharing disk with DRDOS)", buffer_size); break; + //case 0x41: strncpy(buffer, "Personal RISC Boot", buffer_size); break; + //case 0x41: strncpy(buffer, "PPC PReP (Power PC Reference Platform) Boot", buffer_size); break; + case 0x42: strncpy(buffer, "Linux swap (sharing disk with DRDOS)", buffer_size); break; + //case 0x42: strncpy(buffer, "SFS (Secure Filesystem)", buffer_size); break; + //case 0x42: strncpy(buffer, "Windows 2000 marker", buffer_size); break; + case 0x43: strncpy(buffer, "Linux native (sharing disk with DRDOS)", buffer_size); break; + case 0x44: strncpy(buffer, "GoBack partition", buffer_size); break; + case 0x45: strncpy(buffer, "Boot-US boot manager", buffer_size); break; + //case 0x45: strncpy(buffer, "Priam", buffer_size); break; + //case 0x45: strncpy(buffer, "EUMEL/Elan", buffer_size); break; + case 0x46: strncpy(buffer, "EUMEL/Elan", buffer_size); break; + case 0x47: strncpy(buffer, "EUMEL/Elan", buffer_size); break; + case 0x48: strncpy(buffer, "EUMEL/Elan", buffer_size); break; + case 0x4a: strncpy(buffer, "AdaOS Aquila (Default)", buffer_size); break; + //case 0x4a: strncpy(buffer, "ALFS/THIN lightweight filesystem for DOS", buffer_size); break; + case 0x4c: strncpy(buffer, "Oberon partition", buffer_size); break; + case 0x4d: strncpy(buffer, "QNX4.x", buffer_size); break; + case 0x4e: strncpy(buffer, "QNX4.x 2nd part", buffer_size); break; + case 0x4f: strncpy(buffer, "QNX4.x 3rd part", buffer_size); break; + //case 0x4f: strncpy(buffer, "Oberon partition", buffer_size); break; + case 0x50: strncpy(buffer, "OnTrack Disk Manager (older versions) RO", buffer_size); break; + //case 0x50: strncpy(buffer, "Lynx RTOS", buffer_size); break; + //case 0x50: strncpy(buffer, "Native Oberon (alt)", buffer_size); break; + case 0x51: strncpy(buffer, "OnTrack Disk Manager RW (DM6 Aux1)", buffer_size); break; + //case 0x51: strncpy(buffer, "Novell", buffer_size); break; + case 0x52: strncpy(buffer, "CP/M", buffer_size); break; + //case 0x52: strncpy(buffer, "Microport SysV/AT", buffer_size); break; + case 0x53: strncpy(buffer, "Disk Manager 6.0 Aux3", buffer_size); break; + case 0x54: strncpy(buffer, "Disk Manager 6.0 Dynamic Drive Overlay", buffer_size); break; + case 0x55: strncpy(buffer, "EZ-Drive", buffer_size); break; + case 0x56: strncpy(buffer, "Golden Bow VFeature Partitioned Volume.", buffer_size); break; + //case 0x56: strncpy(buffer, "DM converted to EZ-BIOS", buffer_size); break; + case 0x57: strncpy(buffer, "DrivePro", buffer_size); break; + //case 0x57: strncpy(buffer, "VNDI Partition", buffer_size); break; + case 0x5c: strncpy(buffer, "Priam EDisk", buffer_size); break; + case 0x61: strncpy(buffer, "SpeedStor", buffer_size); break; + case 0x63: strncpy(buffer, "Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd", buffer_size); break; + case 0x64: strncpy(buffer, "PC-ARMOUR protected partition", buffer_size); break; + //case 0x64: strncpy(buffer, "Novell Netware 286, 2.xx", buffer_size); break; + case 0x65: strncpy(buffer, "Novell Netware 386, 3.xx or 4.xx", buffer_size); break; + case 0x66: strncpy(buffer, "Novell Netware SMS Partition", buffer_size); break; + case 0x67: strncpy(buffer, "Novell", buffer_size); break; + case 0x68: strncpy(buffer, "Novell", buffer_size); break; + case 0x69: strncpy(buffer, "Novell Netware 5+, Novell Netware NSS Partition", buffer_size); break; + case 0x70: strncpy(buffer, "DiskSecure Multi-Boot", buffer_size); break; + case 0x71: strncpy(buffer, "Reserved", buffer_size); break; + case 0x73: strncpy(buffer, "Reserved", buffer_size); break; + case 0x74: strncpy(buffer, "Reserved", buffer_size); break; + //case 0x74: strncpy(buffer, "Scramdisk partition", buffer_size); break; + case 0x75: strncpy(buffer, "IBM PC/IX", buffer_size); break; + case 0x76: strncpy(buffer, "Reserved", buffer_size); break; + case 0x77: strncpy(buffer, "M2FS/M2CS partition", buffer_size); break; + //case 0x77: strncpy(buffer, "VNDI Partition", buffer_size); break; + case 0x78: strncpy(buffer, "XOSL FS", buffer_size); break; + case 0x7E: strncpy(buffer, " ", buffer_size); break; + case 0x80: strncpy(buffer, "MINIX until 1.4a", buffer_size); break; + case 0x81: strncpy(buffer, "MINIX since 1.4b, early Linux", buffer_size); break; + //case 0x81: strncpy(buffer, "Mitac disk manager", buffer_size); break; + //case 0x82: strncpy(buffer, "Prime", buffer_size); break; + //case 0x82: strncpy(buffer, "Solaris x86", buffer_size); break; + case 0x82: strncpy(buffer, "Linux swap", buffer_size); break; + case 0x83: strncpy(buffer, "Linux native (usually ext2fs)", buffer_size); break; + case 0x84: strncpy(buffer, "OS/2 hidden C: drive", buffer_size); break; + //case 0x84: strncpy(buffer, "Hibernation partition", buffer_size); break; + case 0x85: strncpy(buffer, "Linux extended partition", buffer_size); break; + //case 0x86: strncpy(buffer, "Old Linux RAID partition superblock", buffer_size); break; + case 0x86: strncpy(buffer, "NTFS volume set", buffer_size); break; + case 0x87: strncpy(buffer, "NTFS volume set", buffer_size); break; + case 0x8a: strncpy(buffer, "Linux Kernel Partition (used by AiR-BOOT)", buffer_size); break; + case 0x8b: strncpy(buffer, "Legacy Fault Tolerant FAT32 volume", buffer_size); break; + case 0x8c: strncpy(buffer, "Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h", buffer_size); break; + case 0x8d: strncpy(buffer, "Free FDISK hidden Primary DOS FAT12 partitition", buffer_size); break; + case 0x8e: strncpy(buffer, "Linux Logical Volume Manager partition", buffer_size); break; + case 0x90: strncpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition", buffer_size); break; + case 0x91: strncpy(buffer, "Free FDISK hidden DOS extended partitition", buffer_size); break; + case 0x92: strncpy(buffer, "Free FDISK hidden Primary DOS large FAT16 partitition", buffer_size); break; + case 0x93: strncpy(buffer, "Hidden Linux native partition", buffer_size); break; + //case 0x93: strncpy(buffer, "Amoeba", buffer_size); break; + case 0x94: strncpy(buffer, "Amoeba bad block table", buffer_size); break; + case 0x95: strncpy(buffer, "MIT EXOPC native partitions", buffer_size); break; + case 0x97: strncpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition", buffer_size); break; + case 0x98: strncpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition (LBA)", buffer_size); break; + case 0x99: strncpy(buffer, "DCE376 logical drive", buffer_size); break; + case 0x9a: strncpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition (LBA)", buffer_size); break; + case 0x9b: strncpy(buffer, "Free FDISK hidden DOS extended partitition (LBA)", buffer_size); break; + case 0x9f: strncpy(buffer, "BSD/OS", buffer_size); break; + case 0xa0: strncpy(buffer, "Laptop hibernation partition", buffer_size); break; + case 0xa1: strncpy(buffer, "Laptop hibernation partition", buffer_size); break; + //case 0xa1: strncpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size); break; + case 0xa3: strncpy(buffer, "Reserved", buffer_size); break; + case 0xa4: strncpy(buffer, "Reserved", buffer_size); break; + case 0xa5: strncpy(buffer, "BSD/386, 386BSD, NetBSD, FreeBSD", buffer_size); break; + case 0xa6: strncpy(buffer, "OpenBSD", buffer_size); break; + case 0xa7: strncpy(buffer, "NEXTSTEP", buffer_size); break; + case 0xa8: strncpy(buffer, "Mac OS-X", buffer_size); break; + case 0xa9: strncpy(buffer, "NetBSD", buffer_size); break; + case 0xaa: strncpy(buffer, "Olivetti Fat 12 1.44Mb Service Partition", buffer_size); break; + case 0xab: strncpy(buffer, "Mac OS-X Boot partition", buffer_size); break; + //case 0xab: strncpy(buffer, "GO! partition", buffer_size); break; + case 0xae: strncpy(buffer, "ShagOS filesystem", buffer_size); break; + case 0xaf: strncpy(buffer, "ShagOS swap partition", buffer_size); break; + case 0xb0: strncpy(buffer, "BootStar Dummy", buffer_size); break; + case 0xb1: strncpy(buffer, "Reserved", buffer_size); break; + case 0xb3: strncpy(buffer, "Reserved", buffer_size); break; + case 0xb4: strncpy(buffer, "Reserved", buffer_size); break; + case 0xb6: strncpy(buffer, "Reserved", buffer_size); break; + case 0xb7: strncpy(buffer, "BSDI BSD/386 filesystem", buffer_size); break; + case 0xb8: strncpy(buffer, "BSDI BSD/386 swap partition", buffer_size); break; + case 0xbb: strncpy(buffer, "Boot Wizard hidden", buffer_size); break; + case 0xbe: strncpy(buffer, "Solaris 8 boot partition", buffer_size); break; + case 0xc0: strncpy(buffer, "CTOS", buffer_size); break; + //case 0xc0: strncpy(buffer, "REAL/32 secure small partition", buffer_size); break; + //case 0xc0: strncpy(buffer, "NTFT Partition", buffer_size); break; + case 0xc1: strncpy(buffer, "DRDOS/secured (FAT-12)", buffer_size); break; + case 0xc2: strncpy(buffer, "Reserved for DR-DOS 7+", buffer_size); break; + //case 0xc2: strncpy(buffer, "Hidden Linux", buffer_size); break; + case 0xc3: strncpy(buffer, "Hidden Linux swap", buffer_size); break; + case 0xc4: strncpy(buffer, "DRDOS/secured (FAT-16, < 32M)", buffer_size); break; + case 0xc5: strncpy(buffer, "DRDOS/secured (extended)", buffer_size); break; + case 0xc6: strncpy(buffer, "DRDOS/secured (FAT-16, >= 32M)", buffer_size); break; + //case 0xc6: strncpy(buffer, "Windows NT corrupted FAT16 volume/stripe set", buffer_size); break; + case 0xc7: strncpy(buffer, "Windows NT corrupted NTFS volume/stripe set", buffer_size); break; + //case 0xc7: strncpy(buffer, "Syrinx boot", buffer_size); break; + case 0xc8: strncpy(buffer, "(See also ID c2.)", buffer_size); break; + case 0xc9: strncpy(buffer, "(See also ID c2.)", buffer_size); break; + case 0xca: strncpy(buffer, "(See also ID c2.)", buffer_size); break; + case 0xcb: strncpy(buffer, "reserved for DRDOS/secured (FAT32)", buffer_size); break; + case 0xcc: strncpy(buffer, "reserved for DRDOS/secured (FAT32, LBA)", buffer_size); break; + case 0xcd: strncpy(buffer, "CTOS Memdump?", buffer_size); break; + case 0xce: strncpy(buffer, "reserved for DRDOS/secured (FAT16, LBA)", buffer_size); break; + case 0xd0: strncpy(buffer, "REAL/32 secure big partition", buffer_size); break; + case 0xd1: strncpy(buffer, "Old Multiuser DOS secured FAT12", buffer_size); break; + case 0xd4: strncpy(buffer, "Old Multiuser DOS secured FAT16 <32M", buffer_size); break; + case 0xd5: strncpy(buffer, "Old Multiuser DOS secured extended partition", buffer_size); break; + case 0xd6: strncpy(buffer, "Old Multiuser DOS secured FAT16 >=32M", buffer_size); break; + case 0xd8: strncpy(buffer, "CP/M-86", buffer_size); break; + case 0xda: strncpy(buffer, "Non-FS Data", buffer_size); break; + case 0xdb: strncpy(buffer, "Digital Research CP/M, Concurrent CP/M, Concurrent DOS", buffer_size); break; + //case 0xdb: strncpy(buffer, "CTOS (Convergent Technologies OS -Unisys)", buffer_size); break; + //case 0xdb: strncpy(buffer, "KDG Telemetry SCPU boot", buffer_size); break; + case 0xdd: strncpy(buffer, "Hidden CTOS Memdump?", buffer_size); break; + case 0xde: strncpy(buffer, "Dell PowerEdge Server utilities (FAT fs)", buffer_size); break; + case 0xdf: strncpy(buffer, "DG/UX virtual disk manager partition", buffer_size); break; + //case 0xdf: strncpy(buffer, "BootIt EMBRM", buffer_size); break; + case 0xe0: strncpy(buffer, "Reserved by STMicroelectronics for a filesystem called ST AVFS.", buffer_size); break; + case 0xe1: strncpy(buffer, "DOS access or SpeedStor 12-bit FAT extended partition", buffer_size); break; + case 0xe3: strncpy(buffer, "DOS R/O or SpeedStor", buffer_size); break; + case 0xe4: strncpy(buffer, "SpeedStor 16-bit FAT extended partition < 1024 cyl.", buffer_size); break; + case 0xe5: strncpy(buffer, "Tandy DOS with logical sectored FAT (According to Powerquest.)", buffer_size); break; + //case 0xe5: strncpy(buffer, "Reserved", buffer_size); break; + case 0xe6: strncpy(buffer, "Reserved", buffer_size); break; + case 0xeb: strncpy(buffer, "BFS (aka BeFS)", buffer_size); break; + case 0xed: strncpy(buffer, "Reserved for Matthias Paul's Sprytix", buffer_size); break; + case 0xee: strncpy(buffer, "Indication that this legacy MBR is followed by an EFI header", buffer_size); break; + case 0xef: strncpy(buffer, "Partition that contains an EFI file system", buffer_size); break; + case 0xf0: strncpy(buffer, "Linux/PA-RISC boot loader", buffer_size); break; + case 0xf1: strncpy(buffer, "SpeedStor", buffer_size); break; + case 0xf2: strncpy(buffer, "DOS 3.3+ secondary partition (Powerquest writes: Unisys DOS with logical sectored FAT.)", buffer_size); break; + case 0xf3: strncpy(buffer, "Reserved (Powerquest writes: Storage Dimensions SpeedStor.)", buffer_size); break; + case 0xf4: strncpy(buffer, "SpeedStor large partition", buffer_size); break; + //case 0xf4: strncpy(buffer, "Prologue single-volume partition", buffer_size); break; + case 0xf5: strncpy(buffer, "Prologue multi-volume partition", buffer_size); break; + case 0xf6: strncpy(buffer, "Reserved (Powerquest writes: Storage Dimensions SpeedStor. )", buffer_size); break; + case 0xfa: strncpy(buffer, "Bochs", buffer_size); break; + case 0xfb: strncpy(buffer, "VMware File System partition", buffer_size); break; + case 0xfc: strncpy(buffer, "VMware Swap partition", buffer_size); break; + case 0xfd: strncpy(buffer, "Linux raid partition with autodetect using persistent superblock (Powerquest writes: Reserved for FreeDOS. )", buffer_size); break; + case 0xfe: strncpy(buffer, "SpeedStor > 1024 cyl.", buffer_size); break; + //case 0xfe: strncpy(buffer, "LANstep", buffer_size); break; + //case 0xfe: strncpy(buffer, "IBM PS/2 IML (Initial Microcode Load) partition, located at the end of the disk.", buffer_size); break; + //case 0xfe: strncpy(buffer, "Windows NT Disk Administrator hidden partition", buffer_size); break; + //case 0xfe: strncpy(buffer, "Linux Logical Volume Manager partition (old)", buffer_size); break; + case 0xff: strncpy(buffer, "Xenix Bad Block Table ", buffer_size); break; + } +} -- cgit v1.2.1 From c66f28e926c0f9ede0976448b2a74489f0aa0bf0 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 19 Apr 2009 21:13:47 -0700 Subject: hdt: Dump partition tables (CLI) Use the new disk API to read mbrs and dump information about detected primary partitions. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index a035b58c..01db50ba 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -32,6 +32,8 @@ #include #include +#include +#include #include "hdt-cli.h" #include "hdt-common.h" @@ -63,6 +65,27 @@ void main_show_disk(int argc __unused, char **argv __unused, (int) d->edd_params.sectors_per_track); more_printf(" Host bus: %s, Interface type: %s\n\n", d->edd_params.host_bus_type, d->edd_params.interface_type); + + char *mbr = read_mbr(d->disk); + if (!mbr) { + more_printf("Unable to read the mbr."); + continue; + } + + more_printf(" # Boot Start End Blocks Id Type\n"); + struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); + for (int i = 0; i < 4; i++) { + char *parttype; + if (ptab[i].ostype) { + get_label(ptab[i].ostype, &parttype); + more_printf(" %d %s %8d %8d %8d %02X %s\n", + i, (ptab[i].active_flag == 0x80) ? " x " : " ", + ptab[i].start_lba, + ptab[i].start_lba + ptab[i].length, ptab[i].length, + ptab[i].ostype, parttype); + free(parttype); + } + } } } -- cgit v1.2.1 From f5e4aea6089b93a52e4cee1bdca33d27721b11e9 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Mon, 20 Apr 2009 15:26:12 -0700 Subject: hdt: Add partitions information in disk menu Show information about valid partitions found (start, end, length, type, ...). Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 167 ++++++++++++++++++++++++++++++++++++---------- com32/hdt/hdt-menu.h | 2 - 2 files changed, 133 insertions(+), 36 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index dc2d9a4c..b54cb739 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -26,103 +26,202 @@ * ----------------------------------------------------------------------- */ +#include +#include +#include +#include #include "hdt-menu.h" +static void humanize_size(char *previous_unit, int *previous_size, char *unit, int *size, int sectors) +{ + *size = sectors / 2; // Converting to bytes + strlcpy(unit, "KB", 2); + strlcpy(previous_unit, unit, 2); + *previous_size = *size; + if (*size > 1000) { + *size = *size / 1000; + strlcpy(unit, "MB", 2); + if (*size > 1000) { + *previous_size = *size; + *size = *size / 1000; + strlcpy(previous_unit, unit, 2); + strlcpy(unit, "GB", 2); + if (*size > 1000) { + *previous_size = *size; + *size = *size / 1000; + strlcpy(previous_unit, unit, 2); + strlcpy(unit, "TB", 2); + } + } + } +} + +static void compute_partition_info(int partnb, + struct part_entry *ptab, + char menu_title_ref[], + char menu_title[]) +{ + char buffer[56]; + char statbuffer[STATLEN]; + int previous_size, size; + char previous_unit[3], unit[3]; // GB + humanize_size(previous_unit, &previous_size, unit, &size, ptab->length); + + add_named_menu(menu_title_ref, menu_title, -1); + set_menu_pos(5, 17); + + snprintf(buffer, sizeof buffer, "Partition # : %d", + partnb); + snprintf(statbuffer, sizeof statbuffer, "Partition #: %d", + partnb); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Bootable : %s", + (ptab->active_flag == 0x80) ? "Yes" : "No"); + snprintf(statbuffer, sizeof statbuffer, "Bootable: %s", + (ptab->active_flag == 0x80) ? "Yes" : "No"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Start : %d", + ptab->start_lba); + snprintf(statbuffer, sizeof statbuffer, "Start: %d", + ptab->start_lba); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "End : %d", + ptab->start_lba + ptab->length); + snprintf(statbuffer, sizeof statbuffer, "End: %d", + ptab->start_lba + ptab->length); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Length : %d (%d %s)", + ptab->length, size, unit); + snprintf(statbuffer, sizeof statbuffer, "Length: %d (%d %s)", + ptab->length, size, unit); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Id : %X", + ptab->ostype); + snprintf(statbuffer, sizeof statbuffer, "Id: %X", + ptab->ostype); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + char *parttype; + get_label(ptab->ostype, &parttype); + snprintf(buffer, sizeof buffer, "Type : %s", + parttype); + snprintf(statbuffer, sizeof statbuffer, "Type: %s", + parttype); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + free(parttype); +} + /* Compute the disk submenu */ -int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, - struct driveinfo *d, int disk_number) +static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, + struct driveinfo *d, int disk_number) { char buffer[MENULEN + 1]; char statbuffer[STATLEN + 1]; + char *mbr = NULL; snprintf(buffer, sizeof buffer, " Disk <0x%X> ", d[disk_number].disk); menu[nb_sub_disk_menu].menu = add_menu(buffer, -1); menu[nb_sub_disk_menu].items_count = 0; - /* Compute device size */ - char previous_unit[3], unit[3]; //GB - int previous_size, size = d[disk_number].edd_params.sectors / 2; // Converting to bytes - strlcpy(unit, "KB", 2); - strlcpy(previous_unit, unit, 2); - previous_size = size; - if (size > 1000) { - size = size / 1000; - strlcpy(unit, "MB", 2); - if (size > 1000) { - previous_size = size; - size = size / 1000; - strlcpy(previous_unit, unit, 2); - strlcpy(unit, "GB", 2); - if (size > 1000) { - previous_size = size; - size = size / 1000; - strlcpy(previous_unit, unit, 2); - strlcpy(unit, "TB", 2); - } - } - } + int previous_size, size; + char previous_unit[3], unit[3]; // GB + humanize_size(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); - snprintf(buffer, sizeof buffer, "Size : %d %s (%d %s)", size, + snprintf(buffer, sizeof buffer, "Size : %d %s (%d %s)", size, unit, previous_size, previous_unit); snprintf(statbuffer, sizeof statbuffer, "Size: %d %s (%d %s)", size, unit, previous_size, previous_unit); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Interface : %s", + snprintf(buffer, sizeof buffer, "Interface : %s", d[disk_number].edd_params.interface_type); snprintf(statbuffer, sizeof statbuffer, "Interface: %s", d[disk_number].edd_params.interface_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Host Bus : %s", + snprintf(buffer, sizeof buffer, "Host Bus : %s", d[disk_number].edd_params.host_bus_type); snprintf(statbuffer, sizeof statbuffer, "Host Bus Type: %s", d[disk_number].edd_params.host_bus_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Sectors : %d", + snprintf(buffer, sizeof buffer, "Sectors : %d", (int) d[disk_number].edd_params.sectors); snprintf(statbuffer, sizeof statbuffer, "Sectors: %d", (int) d[disk_number].edd_params.sectors); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Heads : %d", + snprintf(buffer, sizeof buffer, "Heads : %d", d[disk_number].legacy_max_head + 1); snprintf(statbuffer, sizeof statbuffer, "Heads: %d", d[disk_number].legacy_max_head + 1); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Cylinders : %d", + snprintf(buffer, sizeof buffer, "Cylinders : %d", d[disk_number].legacy_max_cylinder + 1); snprintf(statbuffer, sizeof statbuffer, "Cylinders: %d", d[disk_number].legacy_max_cylinder + 1); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Sectors/Track: %d", + snprintf(buffer, sizeof buffer, "Sectors/Track : %d", d[disk_number].legacy_sectors_per_track); snprintf(statbuffer, sizeof statbuffer, "Sectors per Track: %d", d[disk_number].legacy_sectors_per_track); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Port : 0x%X", d[disk_number].disk); - snprintf(statbuffer, sizeof statbuffer, "Port: 0x%X", d[disk_number].disk); + snprintf(buffer, sizeof buffer, "Drive number : 0x%X", d[disk_number].disk); + snprintf(statbuffer, sizeof statbuffer, "Drive number: 0x%X", d[disk_number].disk); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "EDD Version : %X", + snprintf(buffer, sizeof buffer, "EDD Version : %X", d[disk_number].edd_version); snprintf(statbuffer, sizeof statbuffer, "EDD Version: %X", d[disk_number].edd_version); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; + add_sep(); + + /* Compute disk partitions menus */ + mbr = read_mbr(d[disk_number].disk); + if (mbr) { + struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); + char menu_title[MENULEN + 1]; + char menu_title_ref[MENULEN + 1]; + /* The calls to add_item need to be done first to draw the main submenu first */ + int submenu_done = 0; +submenu_disk: + for (int i = 0; i < 4; i++) { + if (ptab[i].ostype) { + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", d[disk_number].disk, i); + snprintf(menu_title, sizeof menu_title, "Disk <%X>, Partition %d", d[disk_number].disk, i); + if (!submenu_done) + add_item(menu_title, "Partition information (start, end, length, type, ...)", + OPT_SUBMENU, menu_title_ref, 0); + else + compute_partition_info(i, &ptab[i], menu_title_ref, menu_title); + } + /* Now, draw the sub sub menus */ + if (i == 3 && !submenu_done) { + submenu_done = 1; + goto submenu_disk; + } + } + } + return 0; } diff --git a/com32/hdt/hdt-menu.h b/com32/hdt/hdt-menu.h index 04d6b580..1cd2c129 100644 --- a/com32/hdt/hdt-menu.h +++ b/com32/hdt/hdt-menu.h @@ -91,8 +91,6 @@ int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware); // Disk Stuff -int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, - struct driveinfo *d, int disk_number); void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct s_hardware *hardware); // DMI Stuff -- cgit v1.2.1 From c2853e856c694259d0e93509db6d99d6bd0bfc8f Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Mon, 20 Apr 2009 17:19:26 -0700 Subject: hdt: Process extended partitions (CLI) Print information about extended partitions in the CLI. Note: the offsets reported are the offsets found in the EBR. We may want to adjust it with the offset in the MBR. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/read.c | 2 ++ com32/hdt/hdt-cli-disk.c | 82 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index 1db60fdd..92b2563f 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -6,6 +6,8 @@ #include /** + * read_mbr - return a pointer to a malloced buffer containing the mbr + * @drive: Drive number **/ void *read_mbr(int drive) { diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 01db50ba..c71ea510 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -38,6 +38,75 @@ #include "hdt-cli.h" #include "hdt-common.h" +static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, int start); + +/** + * show_partition_information - print information about a partition + * @ptab: part_entry describing the partition + * @i: Partition number (UI purposes only) + * + * Note on offsets (from hpa, see chain.c32): + * + * To make things extra confusing: data partition offsets are relative to where + * the data partition record is stored, whereas extended partition offsets + * are relative to the beginning of the extended partition all the way back + * at the MBR... but still not absolute! + **/ +static void show_partition_information(struct part_entry *ptab, int i) +{ + char *parttype; + get_label(ptab->ostype, &parttype); + more_printf(" %d %s %8d %8d %8d %02X %s\n", + i, (ptab->active_flag == 0x80) ? " x " : " ", + ptab->start_lba, + ptab->start_lba + ptab->length, ptab->length, + ptab->ostype, parttype); + free(parttype); +} + +/** + * process_ebr - print information for partitions contained in an ebr + * @drive_info: driveinfo struct describing the drive + * @ptab_root: part_entry struct describing the root partition (pointing to the ebr) + * @ebr_seen: Number of ebr processed (UI purposes only) + **/ +static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_root, + int ebr_seen) +{ + /* The ebr is located at the first sector of the extended partition */ + char* ebr = read_sectors(drive_info, ptab_root->start_lba, 1); + if (!ebr) { + more_printf("Unable to read the ebr."); + return; + } + + struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); + return process_br(drive_info, ptab_child, ebr_seen); +} + +/** + * process_br - print information for partitions contained in an {m,e}br + * @drive_info: driveinfo struct describing the drive + * @ptab_root: part_entry struct describing the root partition + * (pointing to the {m,e}br) + * @ebr_seen: Number of ebr processed (UI purposes only) + **/ +static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, + int ebr_seen) +{ + for (int i = 0; i < 4; i++) { + if (ptab[i].ostype) { + show_partition_information(&ptab[i], ebr_seen * 4 + i + 1); + + /* 3 types for extended partitions */ + if ( ptab[i].ostype == 0x05 || + ptab[i].ostype == 0x0f || + ptab[i].ostype == 0x85) + process_ebr(drive_info, &ptab[i], ebr_seen + 1); + } + } +} + void main_show_disk(int argc __unused, char **argv __unused, struct s_hardware *hardware) { @@ -74,18 +143,7 @@ void main_show_disk(int argc __unused, char **argv __unused, more_printf(" # Boot Start End Blocks Id Type\n"); struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); - for (int i = 0; i < 4; i++) { - char *parttype; - if (ptab[i].ostype) { - get_label(ptab[i].ostype, &parttype); - more_printf(" %d %s %8d %8d %8d %02X %s\n", - i, (ptab[i].active_flag == 0x80) ? " x " : " ", - ptab[i].start_lba, - ptab[i].start_lba + ptab[i].length, ptab[i].length, - ptab[i].ostype, parttype); - free(parttype); - } - } + process_br(d, ptab, 0); } } -- cgit v1.2.1 From ea5513d344a9c53a967bdb17bbe8c098e414ba70 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Mon, 20 Apr 2009 19:31:13 -0700 Subject: hdt: Use IEC 60027 standard for capacity (CLI) Impact: add hdt-util.c for generic helpers Display size of partitions in kibi, mebi, gibi ot tebibytes. There is no point in displaying the number of sectors in the CLI, a human readable size is more useful. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 12 ++++++++---- com32/hdt/hdt-util.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ com32/hdt/hdt-util.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 com32/hdt/hdt-util.c create mode 100644 com32/hdt/hdt-util.h diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index c71ea510..7cc40a17 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -37,9 +37,9 @@ #include "hdt-cli.h" #include "hdt-common.h" +#include "hdt-util.h" static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, int start); - /** * show_partition_information - print information about a partition * @ptab: part_entry describing the partition @@ -54,12 +54,16 @@ static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, in **/ static void show_partition_information(struct part_entry *ptab, int i) { + char size[8]; char *parttype; + + sectors_to_size(ptab->length, size); get_label(ptab->ostype, &parttype); - more_printf(" %d %s %8d %8d %8d %02X %s\n", + more_printf(" %d %s %8d %8d %s %02X %s\n", i, (ptab->active_flag == 0x80) ? " x " : " ", ptab->start_lba, - ptab->start_lba + ptab->length, ptab->length, + ptab->start_lba + ptab->length, + size, ptab->ostype, parttype); free(parttype); } @@ -141,7 +145,7 @@ void main_show_disk(int argc __unused, char **argv __unused, continue; } - more_printf(" # Boot Start End Blocks Id Type\n"); + more_printf(" # Boot Start End Size Id Type\n"); struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); process_br(d, ptab, 0); } diff --git a/com32/hdt/hdt-util.c b/com32/hdt/hdt-util.c new file mode 100644 index 00000000..a8c1481b --- /dev/null +++ b/com32/hdt/hdt-util.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + */ + +#include +void sectors_to_size(int sectors, char *buffer) +{ + int b = (sectors / 2); + int mib = b >> 10; + int gib = mib >> 10; + int tib = gib >> 10; + + if (tib > 0) + sprintf(buffer, "%3d TiB", tib); + else if (gib > 0) + sprintf(buffer, "%3d GiB", gib); + else if (mib > 0) + sprintf(buffer, "%3d MiB", mib); + else + sprintf(buffer, "%d b", b); +} + + diff --git a/com32/hdt/hdt-util.h b/com32/hdt/hdt-util.h new file mode 100644 index 00000000..4b184457 --- /dev/null +++ b/com32/hdt/hdt-util.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + */ + +#ifndef DEFINE_HDT_UTIL_H +#define DEFINE_HDT_UTIL_H +void sectors_to_size(int, char *); +#endif -- cgit v1.2.1 From 2290905867306b623d69068b2d2312a9bbfcefb2 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Mon, 20 Apr 2009 19:46:45 -0700 Subject: hdt: Add IEC 60027 format for disk size (menu) Impact: move the decimal format code to hdt-util.c Display size in MiB/GiB/TiB as well in the disk menu. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 48 +++++++++++++++-------------------------------- com32/hdt/hdt-util.c | 25 +++++++++++++++++++++++- com32/hdt/hdt-util.h | 1 + 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index b54cb739..a1383deb 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -30,31 +30,9 @@ #include #include #include -#include "hdt-menu.h" -static void humanize_size(char *previous_unit, int *previous_size, char *unit, int *size, int sectors) -{ - *size = sectors / 2; // Converting to bytes - strlcpy(unit, "KB", 2); - strlcpy(previous_unit, unit, 2); - *previous_size = *size; - if (*size > 1000) { - *size = *size / 1000; - strlcpy(unit, "MB", 2); - if (*size > 1000) { - *previous_size = *size; - *size = *size / 1000; - strlcpy(previous_unit, unit, 2); - strlcpy(unit, "GB", 2); - if (*size > 1000) { - *previous_size = *size; - *size = *size / 1000; - strlcpy(previous_unit, unit, 2); - strlcpy(unit, "TB", 2); - } - } - } -} +#include "hdt-menu.h" +#include "hdt-util.h" static void compute_partition_info(int partnb, struct part_entry *ptab, @@ -65,7 +43,9 @@ static void compute_partition_info(int partnb, char statbuffer[STATLEN]; int previous_size, size; char previous_unit[3], unit[3]; // GB - humanize_size(previous_unit, &previous_size, unit, &size, ptab->length); + char size_iec[8]; // GiB + sectors_to_size_dec(previous_unit, &previous_size, unit, &size, ptab->length); + sectors_to_size(ptab->length, size_iec); add_named_menu(menu_title_ref, menu_title, -1); set_menu_pos(5, 17); @@ -94,10 +74,10 @@ static void compute_partition_info(int partnb, ptab->start_lba + ptab->length); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - snprintf(buffer, sizeof buffer, "Length : %d (%d %s)", - ptab->length, size, unit); - snprintf(statbuffer, sizeof statbuffer, "Length: %d (%d %s)", - ptab->length, size, unit); + snprintf(buffer, sizeof buffer, "Length : %s/%d %s (%d)", + size_iec, size, unit, ptab->length); + snprintf(statbuffer, sizeof statbuffer, "Length: %s/%d %s (%d)", + size_iec, size, unit, ptab->length); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); snprintf(buffer, sizeof buffer, "Id : %X", @@ -130,11 +110,13 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, int previous_size, size; char previous_unit[3], unit[3]; // GB - humanize_size(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); + char size_iec[8]; // GiB + sectors_to_size_dec(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); + sectors_to_size(d[disk_number].edd_params.sectors, size_iec); - snprintf(buffer, sizeof buffer, "Size : %d %s (%d %s)", size, - unit, previous_size, previous_unit); - snprintf(statbuffer, sizeof statbuffer, "Size: %d %s (%d %s)", size, + snprintf(buffer, sizeof buffer, "Size : %s/%d %s (%d %s)", size_iec, + size, unit, previous_size, previous_unit); + snprintf(statbuffer, sizeof statbuffer, "Size: %s/%d %s (%d %s)", size_iec, size, unit, previous_size, previous_unit); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; diff --git a/com32/hdt/hdt-util.c b/com32/hdt/hdt-util.c index a8c1481b..7e55ff3c 100644 --- a/com32/hdt/hdt-util.c +++ b/com32/hdt/hdt-util.c @@ -27,6 +27,7 @@ */ #include + void sectors_to_size(int sectors, char *buffer) { int b = (sectors / 2); @@ -44,4 +45,26 @@ void sectors_to_size(int sectors, char *buffer) sprintf(buffer, "%d b", b); } - +void sectors_to_size_dec(char *previous_unit, int *previous_size, char *unit, int *size, int sectors) +{ + *size = sectors / 2; // Converting to bytes + strlcpy(unit, "KB", 2); + strlcpy(previous_unit, unit, 2); + *previous_size = *size; + if (*size > 1000) { + *size = *size / 1000; + strlcpy(unit, "MB", 2); + if (*size > 1000) { + *previous_size = *size; + *size = *size / 1000; + strlcpy(previous_unit, unit, 2); + strlcpy(unit, "GB", 2); + if (*size > 1000) { + *previous_size = *size; + *size = *size / 1000; + strlcpy(previous_unit, unit, 2); + strlcpy(unit, "TB", 2); + } + } + } +} diff --git a/com32/hdt/hdt-util.h b/com32/hdt/hdt-util.h index 4b184457..8c1d6de5 100644 --- a/com32/hdt/hdt-util.h +++ b/com32/hdt/hdt-util.h @@ -29,4 +29,5 @@ #ifndef DEFINE_HDT_UTIL_H #define DEFINE_HDT_UTIL_H void sectors_to_size(int, char *); +void sectors_to_size_dec(char *, int *, char *, int *, int); #endif -- cgit v1.2.1 From 075c25456b7c6f33248e8bcbe7ede17cf5e82781 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 09:48:09 -0700 Subject: gpllib: Add disk/common.h for shared definitions A couple of structures/definitions are shared between several files in the disk library. Add them in disk/common.h Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/common.h | 19 +++++++++++++++++++ com32/gplinclude/disk/geom.h | 10 ---------- com32/gpllib/disk/read.c | 3 ++- com32/gpllib/disk/write.c | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 com32/gplinclude/disk/common.h diff --git a/com32/gplinclude/disk/common.h b/com32/gplinclude/disk/common.h new file mode 100644 index 00000000..6e4f3d61 --- /dev/null +++ b/com32/gplinclude/disk/common.h @@ -0,0 +1,19 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include + +#define SECTOR 512 /* bytes/sector */ + +#undef PAGE_SIZE +#define PAGE_SIZE (1<<12) + +struct ebios_dapa { + uint16_t len; + uint16_t count; + uint16_t off; + uint16_t seg; + uint64_t lba; +}; + +#endif /* _COMMON_H_ */ diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h index f0c5b6dd..30dc86bf 100644 --- a/com32/gplinclude/disk/geom.h +++ b/com32/gplinclude/disk/geom.h @@ -3,16 +3,6 @@ #include -#define SECTOR 512 /* bytes/sector */ - -struct ebios_dapa { - uint16_t len; - uint16_t count; - uint16_t off; - uint16_t seg; - uint64_t lba; -}; - /** * INT 13 Extensions * diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index 92b2563f..de4dee9f 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -2,8 +2,9 @@ #include #include #include -#include #include +#include +#include /** * read_mbr - return a pointer to a malloced buffer containing the mbr diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index 4b1ed702..100f3aab 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -1,9 +1,9 @@ #include #include #include -#include #include #include +#include #include /** -- cgit v1.2.1 From d1890409251949b80c2026557b9b12ca00d55144 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 09:51:28 -0700 Subject: gpllib: Move get_error from disk/util.c to disk/error.c The get_error function is fairly big. It is worth creating a new file for it. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/error.h | 4 ++ com32/gpllib/disk/error.c | 123 ++++++++++++++++++++++++++++++++++++++++++ com32/gpllib/disk/util.c | 121 ----------------------------------------- 3 files changed, 127 insertions(+), 121 deletions(-) create mode 100644 com32/gplinclude/disk/error.h create mode 100644 com32/gpllib/disk/error.c diff --git a/com32/gplinclude/disk/error.h b/com32/gplinclude/disk/error.h new file mode 100644 index 00000000..3a7614e9 --- /dev/null +++ b/com32/gplinclude/disk/error.h @@ -0,0 +1,4 @@ +#ifndef _ERROR_H_ +#define _ERROR_H_ +void get_error(const int, char**); +#endif /* _UTIL_H_ */ diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c new file mode 100644 index 00000000..469609b2 --- /dev/null +++ b/com32/gpllib/disk/error.c @@ -0,0 +1,123 @@ +#include +#include + +/** + * get_error - decode a disk error status + * @status: Error code + * @buffer_ptr: Pointer to set to the error message + * + * A buffer will be allocated to contain the error message. + * @buffer_ptr will point to it. The caller will need to free it. + **/ +void get_error(int status, char** buffer_ptr) +{ + int buffer_size = (80 * sizeof(char)); + char* buffer = malloc(buffer_size); + *buffer_ptr = buffer; + + switch (status) { + case 0x0: + strncpy(buffer, "successful completion", buffer_size); + break; + case 0x01: + strncpy(buffer, "invalid function in AH or invalid parameter", buffer_size); + break; + case 0x02: + strncpy(buffer, "address mark not found", buffer_size); + break; + case 0x03: + strncpy(buffer, "disk write-protected", buffer_size); + break; + case 0x04: + strncpy(buffer, "sector not found/read error", buffer_size); + break; + case 0x05: + strncpy(buffer, "reset failed (hard disk)", buffer_size); + //strncpy(buffer, "data did not verify correctly (TI Professional PC)", buffer_size); + break; + case 0x06: + strncpy(buffer, "disk changed (floppy)", buffer_size); + break; + case 0x07: + strncpy(buffer, "drive parameter activity failed (hard disk)", buffer_size); + break; + case 0x08: + strncpy(buffer, "DMA overrun", buffer_size); + break; + case 0x09: + strncpy(buffer, "data boundary error (attempted DMA across 64K boundary or >80h sectors)", buffer_size); + break; + case 0x0A: + strncpy(buffer, "bad sector detected (hard disk)", buffer_size); + break; + case 0x0B: + strncpy(buffer, "bad track detected (hard disk)", buffer_size); + break; + case 0x0C: + strncpy(buffer, "unsupported track or invalid media", buffer_size); + break; + case 0x0D: + strncpy(buffer, "invalid number of sectors on format (PS/2 hard disk)", buffer_size); + break; + case 0x0E: + strncpy(buffer, "control data address mark detected (hard disk)", buffer_size); + break; + case 0x0F: + strncpy(buffer, "DMA arbitration level out of range (hard disk)", buffer_size); + break; + case 0x10: + strncpy(buffer, "uncorrectable CRC or ECC error on read", buffer_size); + break; + case 0x11: + strncpy(buffer, "data ECC corrected (hard disk)", buffer_size); + break; + case 0x20: + strncpy(buffer, "controller failure", buffer_size); + break; + case 0x31: + strncpy(buffer, "no media in drive (IBM/MS INT 13 extensions)", buffer_size); + break; + case 0x32: + strncpy(buffer, "incorrect drive type stored in CMOS (Compaq)", buffer_size); + break; + case 0x40: + strncpy(buffer, "seek failed", buffer_size); + break; + case 0x80: + strncpy(buffer, "timeout (not ready)", buffer_size); + break; + case 0xAA: + strncpy(buffer, "drive not ready (hard disk)", buffer_size); + break; + case 0xB0: + strncpy(buffer, "volume not locked in drive (INT 13 extensions)", buffer_size); + break; + case 0xB1: + strncpy(buffer, "volume locked in drive (INT 13 extensions)", buffer_size); + break; + case 0xB2: + strncpy(buffer, "volume not removable (INT 13 extensions)", buffer_size); + break; + case 0xB3: + strncpy(buffer, "volume in use (INT 13 extensions)", buffer_size); + break; + case 0xB4: + strncpy(buffer, "lock count exceeded (INT 13 extensions)", buffer_size); + break; + case 0xB5: + strncpy(buffer, "valid eject request failed (INT 13 extensions)", buffer_size); + break; + case 0xBB: + strncpy(buffer, "undefined error (hard disk)", buffer_size); + break; + case 0xCC: + strncpy(buffer, "write fault (hard disk)", buffer_size); + break; + case 0xE0: + strncpy(buffer, "status register error (hard disk)", buffer_size); + break; + case 0xFF: + strncpy(buffer, "sense operation failed (hard disk)", buffer_size); + break; + } +} diff --git a/com32/gpllib/disk/util.c b/com32/gpllib/disk/util.c index 7da8351d..c03ed37b 100644 --- a/com32/gpllib/disk/util.c +++ b/com32/gpllib/disk/util.c @@ -28,124 +28,3 @@ int int13_retry(const com32sys_t *inreg, com32sys_t *outreg) /* If we get here: error */ return -1; } - -/** - * get_error - decode a disk error status - * @status: Error code - * @buffer_ptr: Pointer to set to the error message - * - * A buffer will be allocated to contain the error message. - * @buffer_ptr will point to it. The caller will need to free it. - **/ -void get_error(int status, char** buffer_ptr) -{ - int buffer_size = (80 * sizeof(char)); - char* buffer = malloc(buffer_size); - *buffer_ptr = buffer; - - switch (status) { - case 0x0: - strncpy(buffer, "successful completion", buffer_size); - break; - case 0x01: - strncpy(buffer, "invalid function in AH or invalid parameter", buffer_size); - break; - case 0x02: - strncpy(buffer, "address mark not found", buffer_size); - break; - case 0x03: - strncpy(buffer, "disk write-protected", buffer_size); - break; - case 0x04: - strncpy(buffer, "sector not found/read error", buffer_size); - break; - case 0x05: - strncpy(buffer, "reset failed (hard disk)", buffer_size); - //strncpy(buffer, "data did not verify correctly (TI Professional PC)", buffer_size); - break; - case 0x06: - strncpy(buffer, "disk changed (floppy)", buffer_size); - break; - case 0x07: - strncpy(buffer, "drive parameter activity failed (hard disk)", buffer_size); - break; - case 0x08: - strncpy(buffer, "DMA overrun", buffer_size); - break; - case 0x09: - strncpy(buffer, "data boundary error (attempted DMA across 64K boundary or >80h sectors)", buffer_size); - break; - case 0x0A: - strncpy(buffer, "bad sector detected (hard disk)", buffer_size); - break; - case 0x0B: - strncpy(buffer, "bad track detected (hard disk)", buffer_size); - break; - case 0x0C: - strncpy(buffer, "unsupported track or invalid media", buffer_size); - break; - case 0x0D: - strncpy(buffer, "invalid number of sectors on format (PS/2 hard disk)", buffer_size); - break; - case 0x0E: - strncpy(buffer, "control data address mark detected (hard disk)", buffer_size); - break; - case 0x0F: - strncpy(buffer, "DMA arbitration level out of range (hard disk)", buffer_size); - break; - case 0x10: - strncpy(buffer, "uncorrectable CRC or ECC error on read", buffer_size); - break; - case 0x11: - strncpy(buffer, "data ECC corrected (hard disk)", buffer_size); - break; - case 0x20: - strncpy(buffer, "controller failure", buffer_size); - break; - case 0x31: - strncpy(buffer, "no media in drive (IBM/MS INT 13 extensions)", buffer_size); - break; - case 0x32: - strncpy(buffer, "incorrect drive type stored in CMOS (Compaq)", buffer_size); - break; - case 0x40: - strncpy(buffer, "seek failed", buffer_size); - break; - case 0x80: - strncpy(buffer, "timeout (not ready)", buffer_size); - break; - case 0xAA: - strncpy(buffer, "drive not ready (hard disk)", buffer_size); - break; - case 0xB0: - strncpy(buffer, "volume not locked in drive (INT 13 extensions)", buffer_size); - break; - case 0xB1: - strncpy(buffer, "volume locked in drive (INT 13 extensions)", buffer_size); - break; - case 0xB2: - strncpy(buffer, "volume not removable (INT 13 extensions)", buffer_size); - break; - case 0xB3: - strncpy(buffer, "volume in use (INT 13 extensions)", buffer_size); - break; - case 0xB4: - strncpy(buffer, "lock count exceeded (INT 13 extensions)", buffer_size); - break; - case 0xB5: - strncpy(buffer, "valid eject request failed (INT 13 extensions)", buffer_size); - break; - case 0xBB: - strncpy(buffer, "undefined error (hard disk)", buffer_size); - break; - case 0xCC: - strncpy(buffer, "write fault (hard disk)", buffer_size); - break; - case 0xE0: - strncpy(buffer, "status register error (hard disk)", buffer_size); - break; - case 0xFF: - strncpy(buffer, "sense operation failed (hard disk)", buffer_size); - break; - } -} -- cgit v1.2.1 From 731660cc2060f3bfdf5cd916bce1573985df6408 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 09:53:16 -0700 Subject: gpllib: Move partition declarations to disk/partition.h Add a new file for partition related structures. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/partition.h | 23 +++++++++++++++++++++++ com32/gplinclude/disk/util.h | 17 ----------------- 2 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 com32/gplinclude/disk/partition.h diff --git a/com32/gplinclude/disk/partition.h b/com32/gplinclude/disk/partition.h new file mode 100644 index 00000000..3bffa89e --- /dev/null +++ b/com32/gplinclude/disk/partition.h @@ -0,0 +1,23 @@ +#ifndef _PARTITION_H_ +#define _PARTITION_H_ + +#include + +#define PARTITION_TABLES_OFFSET 0x1be + +/* A DOS partition table entry */ +struct part_entry { + uint8_t active_flag; /* 0x80 if "active" */ + uint8_t start_head; + uint8_t start_sect; + uint8_t start_cyl; + uint8_t ostype; + uint8_t end_head; + uint8_t end_sect; + uint8_t end_cyl; + uint32_t start_lba; + uint32_t length; +} __attribute__((packed)); + +void get_label(int label, char** buffer_label); +#endif /* _PARTITION_H_ */ diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h index b6cb1850..dd0d5c02 100644 --- a/com32/gplinclude/disk/util.h +++ b/com32/gplinclude/disk/util.h @@ -3,23 +3,6 @@ #include -#define PARTITION_TABLES_OFFSET 0x1be -/* A DOS partition table entry */ -struct part_entry { - uint8_t active_flag; /* 0x80 if "active" */ - uint8_t start_head; - uint8_t start_sect; - uint8_t start_cyl; - uint8_t ostype; - uint8_t end_head; - uint8_t end_sect; - uint8_t end_cyl; - uint32_t start_lba; - uint32_t length; -} __attribute__((packed)); - int int13_retry(const com32sys_t *inreg, com32sys_t *outreg); void get_error(const int, char**); -void get_label(int label, char** buffer_label); - #endif /* _UTIL_H_ */ -- cgit v1.2.1 From bdeb4237ed17d2deab8ecf3cb95721047731cc3c Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 09:56:11 -0700 Subject: gpllib: Propagate error codes in disk library It is worth propagating read/write error codes back to the caller. He can pass NULL to ignore them, or an int* that will be populated. To decode it, one can use the get_error function (see disk/error.c). Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/read.h | 11 +++++++---- com32/gplinclude/disk/write.h | 17 ++++++++++------- com32/gpllib/disk/read.c | 24 +++++++++++++++++------- com32/gpllib/disk/write.c | 26 ++++++++++++++++---------- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h index 79c79524..fee10daf 100644 --- a/com32/gplinclude/disk/read.h +++ b/com32/gplinclude/disk/read.h @@ -1,7 +1,10 @@ #ifndef _READ_H_ #define _READ_H_ -void *read_mbr(int drive); -void *dev_read(int drive, unsigned int lba, int sectors); -void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, - const int sectors); + +#include + +void *read_mbr(int, int*); +void *dev_read(int, unsigned int, int, int*); +void *read_sectors(struct driveinfo*, const unsigned int, + const int, int *); #endif /* _READ_H */ diff --git a/com32/gplinclude/disk/write.h b/com32/gplinclude/disk/write.h index 89ca8736..be6494fa 100644 --- a/com32/gplinclude/disk/write.h +++ b/com32/gplinclude/disk/write.h @@ -1,11 +1,14 @@ #ifndef _WRITE_H_ #define _WRITE_H_ -int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, - const void *data, const int size); + +#include + +int write_sectors(const struct driveinfo*, const unsigned int, + const void *, const int, int *); int write_verify_sector(struct driveinfo* drive_info, - const unsigned int lba, - const void *data); -int write_verify_sectors(struct driveinfo* drive_info, - const unsigned int lba, - const void *data, const int size); + const unsigned int, + const void *, int*); +int write_verify_sectors(struct driveinfo*, + const unsigned int, + const void *, const int, int *); #endif diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index de4dee9f..a5cb120c 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -1,6 +1,7 @@ #include #include #include + #include #include #include @@ -9,14 +10,15 @@ /** * read_mbr - return a pointer to a malloced buffer containing the mbr * @drive: Drive number + * @error: Return the error code on failure **/ -void *read_mbr(int drive) +void *read_mbr(int drive, int *error) { struct driveinfo drive_info; drive_info.disk = drive; /* MBR: lba = 0, 1 sector */ - return read_sectors(&drive_info, 0, 1); + return read_sectors(&drive_info, 0, 1, error); } /** @@ -24,15 +26,16 @@ void *read_mbr(int drive) * @drive: Drive number * @lba: Position to start reading from * @sectors: Number of sectors to read + * @error: Return the error code on failure * * High-level routine to read from a hard drive. **/ -void *dev_read(int drive, unsigned int lba, int sectors) +void *dev_read(int drive, unsigned int lba, int sectors, int *error) { struct driveinfo drive_info; drive_info.disk = drive; - return read_sectors(&drive_info, lba, sectors); + return read_sectors(&drive_info, lba, sectors, error); } /** @@ -40,13 +43,14 @@ void *dev_read(int drive, unsigned int lba, int sectors) * @drive_info: driveinfo struct describing the disk * @lba: Position to read * @sectors: Number of sectors to read + * @error: Return the error code on failure * * Return a pointer to a malloc'ed buffer containing the data. **/ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, - const int sectors) + const int sectors, int *error) { - com32sys_t inreg; + com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; void *data; @@ -92,8 +96,14 @@ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, } /* Perform the read */ - if (int13_retry(&inreg, NULL)) + if (int13_retry(&inreg, &outreg)) { + if (error) + *error = outreg.eax.b[1]; return NULL; /* Give up */ + } else { + if (error) + *error = 0; + } data = malloc(sectors * SECTOR); if (data) diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index 100f3aab..cd585481 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -12,11 +12,12 @@ * @lba: Position to write * @data: Buffer to write * @size: Size of the buffer (number of sectors) + * @error: Return the error code on failure **/ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, - const void *data, const int size) + const void *data, const int size, int *error) { - com32sys_t inreg; + com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + size; @@ -60,10 +61,15 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, } /* Perform the write */ - if (int13_retry(&inreg, NULL)) - return -1; - else + if (int13_retry(&inreg, &outreg)) { + if (error) + *error = outreg.eax.b[1]; + return -1; /* Give up */ + } else { + if (error) + *error = 0; return 0; + } } /** @@ -74,9 +80,9 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, **/ int write_verify_sector(struct driveinfo* drive_info, const unsigned int lba, - const void *data) + const void *data, int *error) { - return write_verify_sectors(drive_info, lba, data, SECTOR); + return write_verify_sectors(drive_info, lba, data, SECTOR, error); } /** @@ -88,16 +94,16 @@ int write_verify_sector(struct driveinfo* drive_info, **/ int write_verify_sectors(struct driveinfo* drive_info, const unsigned int lba, - const void *data, const int size) + const void *data, const int size, int* error) { char *rb; int rv; - rv = write_sectors(drive_info, lba, data, size); + rv = write_sectors(drive_info, lba, data, size, error); if (rv) return rv; /* Write failure */ - rb = read_sectors(drive_info, lba, size); + rb = read_sectors(drive_info, lba, size, error); if (!rb) return -1; /* Readback failure */ -- cgit v1.2.1 From 6a802f4761cb40de2fe25f6df3f9eab8af94d032 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 09:58:35 -0700 Subject: gpllib: Add swsusp_check to check for swsusp signature swsusp is a Linux mechanism to put a computer to sleep. In case of hibernation, an image is written to the disk, on a swap partition. swsusp_check can be used to check if a device contains the magic swsusp signature, meaning that an image is present. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/swsusp.h | 19 +++++++++++++++++++ com32/gpllib/disk/swsusp.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 com32/gplinclude/disk/swsusp.h create mode 100644 com32/gpllib/disk/swsusp.c diff --git a/com32/gplinclude/disk/swsusp.h b/com32/gplinclude/disk/swsusp.h new file mode 100644 index 00000000..54140b3d --- /dev/null +++ b/com32/gplinclude/disk/swsusp.h @@ -0,0 +1,19 @@ +#ifndef _SWSUSP_H_ +#define _SWSUSP_H_ + +#include +#include +#include + +#define SWSUSP_SIG "S1SUSPEND" + +struct swsusp_header { + char reserved[PAGE_SIZE - 20 - sizeof(unsigned long) - sizeof(int)]; + unsigned long image; + unsigned int flags; /* Flags to pass to the "boot" kernel */ + char orig_sig[10]; + char sig[10]; +} __attribute__((packed)); + +int swsusp_check(struct driveinfo*, struct part_entry*, int*); +#endif /* _SWSUSP_H */ diff --git a/com32/gpllib/disk/swsusp.c b/com32/gpllib/disk/swsusp.c new file mode 100644 index 00000000..f627aca4 --- /dev/null +++ b/com32/gpllib/disk/swsusp.c @@ -0,0 +1,31 @@ +#include +#include + +#include +#include +#include + +/** + * swsusp_check - check if a (swap) partition contains the swsusp signature + * @drive_info: driveinfo struct describing the disk containing the partition + * @ptab; Partition table of the partition + * @error: Return the error code on failure + **/ +int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab, int *error) +{ + struct swsusp_header *header_p; + int offset; + int found; + + /* Read first page of the swap device */ + offset = ptab->start_lba; + header_p = (struct swsusp_header *) read_sectors(drive_info, offset, PAGE_SIZE/SECTOR, error); + + if (!header_p) + return -1; /* The error code has been stored in `error' */ + else { + found = !memcmp(SWSUSP_SIG, header_p->sig, 10); + free(header_p); + return found; + } +} -- cgit v1.2.1 From 22026c3e9cd6d466c2f5a895fa983ca4bffddb62 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 10:01:38 -0700 Subject: gpllib: Build new objects (disk) Add error.o and swsusp.o as part of the gpllib build. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 39df17b4..7897af58 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -11,7 +11,7 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o \ - disk/util.o disk/labels.o vpd/vpd.o + disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o BINDIR = /usr/bin LIBDIR = /usr/lib -- cgit v1.2.1 From 49eb3ef573eb339824241b5013fceab3ed3fe049 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 10:02:51 -0700 Subject: hdt: Check if a swsusp image exists on swap partitions Impact: new feature, add error debug information When printing partitions information, add a message in the CLI if a swap device contains a valid swsusp (hibernate) image. Misc.: check and print, if needed, errors after each I/O operation. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 60 ++++++++++++++++++++++++++++++++++++++--------- com32/hdt/hdt-menu-disk.c | 5 ++-- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 7cc40a17..5a12f43a 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -33,17 +33,21 @@ #include #include -#include +#include +#include #include "hdt-cli.h" #include "hdt-common.h" #include "hdt-util.h" -static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, int start); +static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, int start, struct part_entry *ptab_root); /** * show_partition_information - print information about a partition * @ptab: part_entry describing the partition * @i: Partition number (UI purposes only) + * @ptab_root: part_entry describing the root partition (extended only) + * @drive_info: driveinfo struct describing the drive on which the partition + * is * * Note on offsets (from hpa, see chain.c32): * @@ -52,19 +56,39 @@ static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, in * are relative to the beginning of the extended partition all the way back * at the MBR... but still not absolute! **/ -static void show_partition_information(struct part_entry *ptab, int i) +static void show_partition_information(struct part_entry *ptab, int i, + struct part_entry *ptab_root, + struct driveinfo *drive_info) { char size[8]; char *parttype; + int error; + char *error_buffer; + + /* Adjust offsets */ + if (ptab_root) + ptab->start_lba += ptab_root->start_lba; sectors_to_size(ptab->length, size); get_label(ptab->ostype, &parttype); - more_printf(" %d %s %8d %8d %s %02X %s\n", + more_printf(" %d %s %8d %8d %s %02X %s", i, (ptab->active_flag == 0x80) ? " x " : " ", ptab->start_lba, ptab->start_lba + ptab->length, size, ptab->ostype, parttype); + + /* Extra info */ + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab, &error)) { + more_printf("%s", " (Swsusp sig. detected)"); + } else if (error) { + get_error(error, &error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); + } + + more_printf("\n"); + free(parttype); } @@ -77,15 +101,21 @@ static void show_partition_information(struct part_entry *ptab, int i) static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_root, int ebr_seen) { + int error; + char *error_buffer; + /* The ebr is located at the first sector of the extended partition */ - char* ebr = read_sectors(drive_info, ptab_root->start_lba, 1); + char* ebr = read_sectors(drive_info, ptab_root->start_lba, 1, &error); if (!ebr) { - more_printf("Unable to read the ebr."); + more_printf("Unable to read the ebr:\n"); + get_error(error, &error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); return; } struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); - return process_br(drive_info, ptab_child, ebr_seen); + return process_br(drive_info, ptab_child, ebr_seen, ptab_root); } /** @@ -96,11 +126,14 @@ static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_ro * @ebr_seen: Number of ebr processed (UI purposes only) **/ static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, - int ebr_seen) + int ebr_seen, struct part_entry *ptab_root) { for (int i = 0; i < 4; i++) { if (ptab[i].ostype) { - show_partition_information(&ptab[i], ebr_seen * 4 + i + 1); + show_partition_information(&ptab[i], + ebr_seen * 4 + i + 1, + ptab_root, + drive_info); /* 3 types for extended partitions */ if ( ptab[i].ostype == 0x05 || @@ -115,6 +148,8 @@ void main_show_disk(int argc __unused, char **argv __unused, struct s_hardware *hardware) { int i = -1; + int error; + char *error_buffer; detect_disks(hardware); @@ -139,15 +174,18 @@ void main_show_disk(int argc __unused, char **argv __unused, more_printf(" Host bus: %s, Interface type: %s\n\n", d->edd_params.host_bus_type, d->edd_params.interface_type); - char *mbr = read_mbr(d->disk); + char *mbr = read_mbr(d->disk, &error); if (!mbr) { more_printf("Unable to read the mbr."); + get_error(error, &error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); continue; } more_printf(" # Boot Start End Size Id Type\n"); struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); - process_br(d, ptab, 0); + process_br(d, ptab, 0, NULL); } } diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index a1383deb..2283cafa 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include "hdt-menu.h" #include "hdt-util.h" @@ -178,7 +179,7 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_sep(); /* Compute disk partitions menus */ - mbr = read_mbr(d[disk_number].disk); + mbr = read_mbr(d[disk_number].disk, NULL); if (mbr) { struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); char menu_title[MENULEN + 1]; -- cgit v1.2.1 From 43de53a76113bf5de185098d3130e316c5826594 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 10:05:05 -0700 Subject: hdt: Add missing header in hdt-util.c Impact: fix build Add missing #include in hdt-util.c. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/com32/hdt/hdt-util.c b/com32/hdt/hdt-util.c index 7e55ff3c..5bc566af 100644 --- a/com32/hdt/hdt-util.c +++ b/com32/hdt/hdt-util.c @@ -27,6 +27,7 @@ */ #include +#include void sectors_to_size(int sectors, char *buffer) { -- cgit v1.2.1 From 87ecdfc5006737a107465f6ef27787184044e73d Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 12:01:15 -0700 Subject: gpllib: Add default error handling (disk) In case of an unknown error, display a default message. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/error.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 469609b2..763dcfdc 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -1,3 +1,4 @@ +#include #include #include @@ -119,5 +120,8 @@ void get_error(int status, char** buffer_ptr) case 0xFF: strncpy(buffer, "sense operation failed (hard disk)", buffer_size); break; + default: + snprintf(buffer, buffer_size, "unknown error 0x%X, buggy bios?", status); + break; } } -- cgit v1.2.1 From 5681e04fe55a0907d2136223fecc7e85e6b1b876 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 12:02:23 -0700 Subject: gpllib: Handle unknown labels (disk) Return "Unknown" for unknown labels. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/labels.c | 1 + 1 file changed, 1 insertion(+) diff --git a/com32/gpllib/disk/labels.c b/com32/gpllib/disk/labels.c index 0f3a0cc1..cb28be9d 100644 --- a/com32/gpllib/disk/labels.c +++ b/com32/gpllib/disk/labels.c @@ -240,5 +240,6 @@ void get_label(int label, char** buffer_label) //case 0xfe: strncpy(buffer, "Windows NT Disk Administrator hidden partition", buffer_size); break; //case 0xfe: strncpy(buffer, "Linux Logical Volume Manager partition (old)", buffer_size); break; case 0xff: strncpy(buffer, "Xenix Bad Block Table ", buffer_size); break; + default: strncpy(buffer, "Unknown", buffer_size); break; } } -- cgit v1.2.1 From bb646b9842e85f1bbf51bb1bac1c72e3e763aa03 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 12:04:03 -0700 Subject: hdt: Do not modify offsets in the part_entry itself Impact: fix bug When printing extended partitions information, we need to adjust the start lba. Do not modify it in the part_entry struct but just print the adjusted one. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 5a12f43a..8689a37a 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -62,19 +62,25 @@ static void show_partition_information(struct part_entry *ptab, int i, { char size[8]; char *parttype; - int error; + int error = 0; char *error_buffer; + int start; - /* Adjust offsets */ if (ptab_root) - ptab->start_lba += ptab_root->start_lba; + start = ptab->start_lba + ptab_root->start_lba; + else + start = ptab->start_lba; + + if (ptab->length > 0) + sectors_to_size(ptab->length, size); + else + memset(size, 0, sizeof size); - sectors_to_size(ptab->length, size); get_label(ptab->ostype, &parttype); more_printf(" %d %s %8d %8d %s %02X %s", i, (ptab->active_flag == 0x80) ? " x " : " ", - ptab->start_lba, - ptab->start_lba + ptab->length, + start, + start + ptab->length, size, ptab->ostype, parttype); -- cgit v1.2.1 From 5fa9fcefee51b0ea0dd27ab655a4acec6426a935 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 21 Apr 2009 12:05:46 -0700 Subject: hdt: Do not print information about buggy extended partitions Impact: bug fix Add a sanity check before printing extended partitions. As hpa notes in chain.c: Sanity check entry: must not extend outside the extended partition. This is necessary since some OSes put crap in some entries. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 8689a37a..9bd4b1fe 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -109,6 +109,7 @@ static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_ro { int error; char *error_buffer; + int offset; /* The ebr is located at the first sector of the extended partition */ char* ebr = read_sectors(drive_info, ptab_root->start_lba, 1, &error); @@ -121,7 +122,17 @@ static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_ro } struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); - return process_br(drive_info, ptab_child, ebr_seen, ptab_root); + + if (!ptab_child->length) + return; + + offset = ptab_child->start_lba + ptab_root->start_lba; + + if ( offset + ptab_child->length <= ptab_root->start_lba || + offset >= ptab_root->start_lba + ptab_root->length ) + return; + else + return process_br(drive_info, ptab_child, ebr_seen, ptab_root); } /** -- cgit v1.2.1 From 3058efaac90bbc57c1e332a80d76094382cec138 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Thu, 23 Apr 2009 22:08:51 +0200 Subject: hdt: displaying only populated VPD' items Impact: No need to display empty items This commit improve VPD menu by not displaying empty items --- com32/hdt/hdt-menu-vpd.c | 70 +++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/com32/hdt/hdt-menu-vpd.c b/com32/hdt/hdt-menu-vpd.c index 817c1079..49caf8ea 100644 --- a/com32/hdt/hdt-menu-vpd.c +++ b/com32/hdt/hdt-menu-vpd.c @@ -47,54 +47,68 @@ void compute_vpd(struct s_my_menu *menu, struct s_hardware *hardware) add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; - snprintf(buffer, sizeof buffer, "Bios Build ID : %s", + if (strlen(hardware->vpd.bios_build_id) > 0) { + snprintf(buffer, sizeof buffer, "Bios Build ID : %s", hardware->vpd.bios_build_id); - snprintf(statbuffer, sizeof statbuffer, "Bios Build ID: %s", + snprintf(statbuffer, sizeof statbuffer, "Bios Build ID: %s", hardware->vpd.bios_build_id); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Bios Release Date : %s", + if (strlen(hardware->vpd.bios_release_date) > 0) { + snprintf(buffer, sizeof buffer, "Bios Release Date : %s", hardware->vpd.bios_release_date); - snprintf(statbuffer, sizeof statbuffer, "Bios Release Date: %s", + snprintf(statbuffer, sizeof statbuffer, "Bios Release Date: %s", hardware->vpd.bios_release_date); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Bios Version : %s", + if (strlen(hardware->vpd.bios_version) > 0) { + snprintf(buffer, sizeof buffer, "Bios Version : %s", hardware->vpd.bios_version); - snprintf(statbuffer, sizeof statbuffer, "Bios Version: %s", + snprintf(statbuffer, sizeof statbuffer, "Bios Version: %s", hardware->vpd.bios_version); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Default Flash Filename : %s", + if (strlen(hardware->vpd.default_flash_filename) > 0) { + snprintf(buffer, sizeof buffer, "Default Flash Filename : %s", hardware->vpd.default_flash_filename); - snprintf(statbuffer, sizeof statbuffer, "Default Flash Filename: %s", + snprintf(statbuffer, sizeof statbuffer, "Default Flash Filename: %s", hardware->vpd.default_flash_filename); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Box Serial Number : %s", + if (strlen(hardware->vpd.box_serial_number) > 0) { + snprintf(buffer, sizeof buffer, "Box Serial Number : %s", hardware->vpd.box_serial_number); - snprintf(statbuffer, sizeof statbuffer, "Box Serial Number: %s", + snprintf(statbuffer, sizeof statbuffer, "Box Serial Number: %s", hardware->vpd.box_serial_number); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Motherboard Serial Number: %s", + if (strlen(hardware->vpd.motherboard_serial_number) > 0) { + snprintf(buffer, sizeof buffer, "Motherboard Serial Number: %s", hardware->vpd.motherboard_serial_number); - snprintf(statbuffer, sizeof statbuffer, "Motherboard Serial Number: %s", + snprintf(statbuffer, sizeof statbuffer, "Motherboard Serial Number: %s", hardware->vpd.motherboard_serial_number); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } - snprintf(buffer, sizeof buffer, "Machine Type/Model : %s", + if (strlen(hardware->vpd.machine_type_model) > 0) { + snprintf(buffer, sizeof buffer, "Machine Type/Model : %s", hardware->vpd.machine_type_model); - snprintf(statbuffer, sizeof statbuffer, "Machine Type/Model: %s", + snprintf(statbuffer, sizeof statbuffer, "Machine Type/Model: %s", hardware->vpd.machine_type_model); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } printf("MENU: VPD menu done (%d items)\n", menu->items_count); } -- cgit v1.2.1 From ecc21733bb9be5b9b8185389ab7cffe9d6f2e1ff Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Thu, 23 Apr 2009 22:10:08 +0200 Subject: hdt: Adding hotkey for VPD Impact: VPD menu is now reachable via its "V" hotkey Prior to that commit, VPD menu wasn't selectable using a direct keyboard key. --- com32/hdt/hdt-menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index 18158ae3..f2bafa4c 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -244,7 +244,7 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) } if (hardware->is_vpd_valid == true) { - add_item("VPD","VPD Information Menu", OPT_SUBMENU, NULL, + add_item("PD","VPD Information Menu", OPT_SUBMENU, NULL, hdt_menu->vpd_menu.menu); hdt_menu->main_menu.items_count++; } -- cgit v1.2.1 From fdd21ff85b3fa41641f711311f7e62081442dbe2 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Thu, 23 Apr 2009 22:28:43 +0200 Subject: hdt: Adding hdt> show vpd Impact: Adding a missing CLI command Prior to that commit, "hdt> show vpd" didn't worked. --- com32/hdt/hdt-cli-hdt.c | 5 +++++ com32/hdt/hdt-cli.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index 46f3669a..b0ee0342 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -304,6 +304,11 @@ struct cli_callback_descr list_hdt_show_modules[] = { .name = CLI_HDT, .exec = main_show_hdt, }, + { + .name = CLI_VPD, + .exec = main_show_vpd, + }, + { .name = "modes", .exec = main_show_modes, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 516d2fc8..c51127ef 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -184,4 +184,7 @@ void main_show_syslinux(int argc, char **argv, struct s_hardware *hardware); // VESA STUFF void main_show_vesa(int argc, char **argv, struct s_hardware *hardware); + +// VPD STUFF +void main_show_vpd(int argc __unused, char **argv __unused, struct s_hardware *hardware); #endif -- cgit v1.2.1 From 3ea01d1af4dd0c22b292ce887141a95c9d629f19 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 25 Apr 2009 17:52:02 -0700 Subject: hdt: Improve disk output (CLI) Do not print EDD C/H/S info, since it is not really useful. Add disk size to the summary. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 9bd4b1fe..0d3cc18d 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -175,18 +175,21 @@ void main_show_disk(int argc __unused, char **argv __unused, if (!hardware->disk_info[i].cbios) continue; /* Invalid geometry */ struct driveinfo *d = &hardware->disk_info[i]; + char disk_size[8]; + + if ((int) d->edd_params.sectors > 0) + sectors_to_size((int) d->edd_params.sectors, disk_size); + else + memset(disk_size, 0, sizeof disk_size); more_printf("DISK 0x%X:\n", d->disk); - more_printf(" C/H/S: %d heads, %d cylinders\n", - d->legacy_max_head + 1, d->legacy_max_cylinder + 1); - more_printf(" %d sectors/track, %d drives\n", - d->legacy_sectors_per_track, d->legacy_max_drive); - more_printf(" EDD: ebios=%d, EDD version: %X\n", - d->ebios, d->edd_version); - more_printf(" %d heads, %d cylinders\n", - (int) d->edd_params.heads, (int) d->edd_params.cylinders); - more_printf(" %d sectors, %d bytes/sector, %d sectors/track\n", - (int) d->edd_params.sectors, (int) d->edd_params.bytes_per_sector, + more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n", + d->legacy_max_cylinder + 1, d->legacy_max_head + 1, + d->legacy_sectors_per_track); + more_printf(" EDD: Version: %X\n", d->edd_version); + more_printf(" Size: %s, %d bytes/sector, %d sectors/track\n", + disk_size, + (int) d->edd_params.bytes_per_sector, (int) d->edd_params.sectors_per_track); more_printf(" Host bus: %s, Interface type: %s\n\n", d->edd_params.host_bus_type, d->edd_params.interface_type); -- cgit v1.2.1 From 262e71498984cd2518cde54961f92c12e2f5ad0a Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 26 Apr 2009 14:09:18 -0700 Subject: gpllib: Add parse_partition_table() to iterate through all partitions on a disk Impact: expand gpllib disk API parse_partition_table() can be used to execute a callback on each partition. The signature of the callback is: void callback(struct driveinfo *drive_info, struct part_entry *ptab, struct part_entry *ptab_root, int offset_root, int local_partition_number, int ebr_seen) * drive_info represents the disk. * ptab is the current partition entry processed. * ptab_root is the partition entry linking to the current one processed (extended only). * offset_root is the offset of the ebr when iterating through extended partitions (0 otherwise). * local_partition_number is the number of the partition processed (0->3). * ebr_seen counts the total number of ebr processed. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/msdos.h | 8 +++ com32/gpllib/Makefile | 2 +- com32/gpllib/disk/msdos.c | 149 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 com32/gplinclude/disk/msdos.h create mode 100644 com32/gpllib/disk/msdos.c diff --git a/com32/gplinclude/disk/msdos.h b/com32/gplinclude/disk/msdos.h new file mode 100644 index 00000000..b6dd9481 --- /dev/null +++ b/com32/gplinclude/disk/msdos.h @@ -0,0 +1,8 @@ +#ifndef _MSDOS_H_ +#define _MSDOS_H_ + +#include + +int parse_partition_table(struct driveinfo *, void *, int *); + +#endif /* _MSDOS_H_ */ diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 7897af58..83f1407a 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -10,7 +10,7 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ - dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o \ + dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o disk/msdos.o \ disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o BINDIR = /usr/bin diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c new file mode 100644 index 00000000..da28b8bb --- /dev/null +++ b/com32/gpllib/disk/msdos.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include + +static inline int is_extended_partition(struct part_entry *ptab) +{ + return (ptab->ostype == 0x05 || + ptab->ostype == 0x0f || + ptab->ostype == 0x85); +} +static inline int msdos_magic_present(char *ptab) +{ + return ( *(uint16_t *)(ptab + 0x1fe) == 0xaa55 ); +} + +/** + * process_ebr - execute a callback for each partition contained in an ebr + * @drive_info: driveinfo struct describing the drive + * @ptab_root: part_entry struct describing the root partition (pointing to the ebr) + * @ebr_seen: Number of ebr processed + * @callback: Callback to execute + **/ +static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_root, + int ebr_seen, + void *callback(struct driveinfo *, struct part_entry *, struct part_entry *, int, int, int), + int *error, int offset_root) +{ + /* The ebr is located at the first sector of the extended partition */ + char* ebr = read_sectors(drive_info, ptab_root->start_lba+offset_root, 1, error); + if (!ebr) + return; + + /* Check msdos magic signature */ + if(!msdos_magic_present(ebr)) + return; + ebr_seen += 1; + + struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); + + /* First process the data partitions */ + for (int i = 0; i < 4; i++) { + if (*error) + return; + + if (ptab_child[i].start_sect > 0) { + if (is_extended_partition(&ptab_child[i])) { + continue; + } + + /* Check for garbage in the 3rd and 4th entries */ + if (i > 2) { + unsigned int offset = ptab_child->start_lba + ptab_root->start_lba; + if ( offset + ptab_child->length <= ptab_root->start_lba || + offset >= ptab_root->start_lba + ptab_root->length ) { + continue; + } + } + callback(drive_info, + &ptab_child[i], + ptab_root, + offset_root, + i, + ebr_seen); + } + } + + /* Now process the extended partitions */ + for (int i = 0; i < 4; i++) { + if (is_extended_partition(&ptab_child[i])) { + callback(drive_info, + &ptab_child[i], + ptab_root, + offset_root, + i, + ebr_seen); + process_ebr(drive_info, &ptab_child[i], ebr_seen + 1, callback, error, ptab_root->start_lba); + } + } +} + +/** + * process_mbr - execute a callback for each partition contained in an {m,e}br + * @drive_info: driveinfo struct describing the drive + * @ptab: Pointer to the partition table + * @callback: Callback to execute + * @error: Return the error code (I/O), if needed + **/ +static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, + void *callback(struct driveinfo *, struct part_entry *, struct part_entry *, int, int, int), + int *error) +{ + for (int i = 0; i < 4; i++) { + if (*error) + return; + + if (ptab[i].start_sect > 0) { + if (is_extended_partition(&ptab[i])) { + callback(drive_info, + &ptab[i], + ptab, + 0, + i, + 0); + process_ebr(drive_info, &ptab[i], 0, callback, error, 0); + } else + callback(drive_info, + &ptab[i], + ptab, + 0, + i, + 0); + } + } +} + +/** + * parse_partition_table - execute a callback for each partition entry + * @d: driveinfo struct describing the drive + * @callback: Callback to execute + * @error: Return the error code (I/O), if needed + * + * The signature of the callback should be the following: + * + * void callback(struct driveinfo *drive_info, + * struct part_entry *ptab, + * struct part_entry *ptab_root, + * int offset_root, + * int local_partition_number, + * int ebr_seen) + **/ +int parse_partition_table(struct driveinfo *d, void *callback, int *error) +{ + char *mbr = read_mbr(d->disk, error); + if (!mbr) + return -1; + else { + /* Check msdos magic signature */ + if (!msdos_magic_present(mbr)) + return -1; + + struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); + process_mbr(d, ptab, callback, error); + if (*error) + return -1; + else + return 0; + } +} -- cgit v1.2.1 From 7bd5d73a1b559935dae9f6b29703d71856554f3e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 26 Apr 2009 14:14:49 -0700 Subject: hdt: Make the disk mode use parse_partition_table() (CLI) Impact: code refactoring Leverage the new call parse_partition_table() in the disk CLI. Misc.: enhance UI output, add space in the columns for up to 46 TB disks. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 112 +++++++++++------------------------------------ 1 file changed, 26 insertions(+), 86 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 0d3cc18d..506efba7 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -35,12 +35,12 @@ #include #include #include +#include #include "hdt-cli.h" #include "hdt-common.h" #include "hdt-util.h" -static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, int start, struct part_entry *ptab_root); /** * show_partition_information - print information about a partition * @ptab: part_entry describing the partition @@ -56,20 +56,22 @@ static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, in * are relative to the beginning of the extended partition all the way back * at the MBR... but still not absolute! **/ -static void show_partition_information(struct part_entry *ptab, int i, +static void show_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab, struct part_entry *ptab_root, - struct driveinfo *drive_info) + int offset_root, int data_partitions_seen, + int ebr_seen) { char size[8]; char *parttype; int error = 0; char *error_buffer; - int start; + unsigned int start, end; - if (ptab_root) - start = ptab->start_lba + ptab_root->start_lba; - else - start = ptab->start_lba; + int i = 1 + ebr_seen * 4 + data_partitions_seen; + + start = ptab->start_lba + ptab_root->start_lba + offset_root; + end = (ptab->start_lba + ptab_root->start_lba) + ptab->length + offset_root; if (ptab->length > 0) sectors_to_size(ptab->length, size); @@ -77,10 +79,10 @@ static void show_partition_information(struct part_entry *ptab, int i, memset(size, 0, sizeof size); get_label(ptab->ostype, &parttype); - more_printf(" %d %s %8d %8d %s %02X %s", - i, (ptab->active_flag == 0x80) ? " x " : " ", + more_printf(" %2d %s %11d %11d %s %02X %s", + i, (ptab->active_flag == 0x80) ? "x" : " ", start, - start + ptab->length, + end, size, ptab->ostype, parttype); @@ -98,69 +100,6 @@ static void show_partition_information(struct part_entry *ptab, int i, free(parttype); } -/** - * process_ebr - print information for partitions contained in an ebr - * @drive_info: driveinfo struct describing the drive - * @ptab_root: part_entry struct describing the root partition (pointing to the ebr) - * @ebr_seen: Number of ebr processed (UI purposes only) - **/ -static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_root, - int ebr_seen) -{ - int error; - char *error_buffer; - int offset; - - /* The ebr is located at the first sector of the extended partition */ - char* ebr = read_sectors(drive_info, ptab_root->start_lba, 1, &error); - if (!ebr) { - more_printf("Unable to read the ebr:\n"); - get_error(error, &error_buffer); - more_printf("%s\n", error_buffer); - free(error_buffer); - return; - } - - struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); - - if (!ptab_child->length) - return; - - offset = ptab_child->start_lba + ptab_root->start_lba; - - if ( offset + ptab_child->length <= ptab_root->start_lba || - offset >= ptab_root->start_lba + ptab_root->length ) - return; - else - return process_br(drive_info, ptab_child, ebr_seen, ptab_root); -} - -/** - * process_br - print information for partitions contained in an {m,e}br - * @drive_info: driveinfo struct describing the drive - * @ptab_root: part_entry struct describing the root partition - * (pointing to the {m,e}br) - * @ebr_seen: Number of ebr processed (UI purposes only) - **/ -static void process_br(struct driveinfo *drive_info, struct part_entry *ptab, - int ebr_seen, struct part_entry *ptab_root) -{ - for (int i = 0; i < 4; i++) { - if (ptab[i].ostype) { - show_partition_information(&ptab[i], - ebr_seen * 4 + i + 1, - ptab_root, - drive_info); - - /* 3 types for extended partitions */ - if ( ptab[i].ostype == 0x05 || - ptab[i].ostype == 0x0f || - ptab[i].ostype == 0x85) - process_ebr(drive_info, &ptab[i], ebr_seen + 1); - } - } -} - void main_show_disk(int argc __unused, char **argv __unused, struct s_hardware *hardware) { @@ -192,20 +131,21 @@ void main_show_disk(int argc __unused, char **argv __unused, (int) d->edd_params.bytes_per_sector, (int) d->edd_params.sectors_per_track); more_printf(" Host bus: %s, Interface type: %s\n\n", - d->edd_params.host_bus_type, d->edd_params.interface_type); - - char *mbr = read_mbr(d->disk, &error); - if (!mbr) { - more_printf("Unable to read the mbr."); - get_error(error, &error_buffer); - more_printf("%s\n", error_buffer); - free(error_buffer); + remove_spaces(d->edd_params.host_bus_type), + remove_spaces(d->edd_params.interface_type)); + + more_printf(" # B Start End Size Id Type\n"); + error = 0; + if (parse_partition_table(d, &show_partition_information, &error)) { + if (error) { + more_printf("I/O error: "); + get_error(error, &error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); + } else + more_printf("An unknown error occured.\n"); continue; } - - more_printf(" # Boot Start End Size Id Type\n"); - struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); - process_br(d, ptab, 0, NULL); } } -- cgit v1.2.1 From 6240ecadc145ce1a7b9955e0de08d5faeedc45e5 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 26 Apr 2009 23:17:19 -0700 Subject: hdt: Fix modules lookup to compare against full callback name (CLI) Impact: remove auto-aliases feature but fix potential bug Comparing the first letters of the supplied command to look for the callback was interesting, since it added aliases automatically (`show bi' matched `show bios'). Unfortunately, that caused some issues in certain situation (`show disk' matching `show disks'). Removing the feature. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 324c74ae..6df2818f 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -439,7 +439,7 @@ void find_cli_callback_descr(const char* module_name, while (modules_list->modules[modules_iter].name && strncmp(module_name, modules_list->modules[modules_iter].name, - module_len) != 0) + strlen(modules_list->modules[modules_iter].name)) != 0) modules_iter++; if (modules_list->modules[modules_iter].name) { -- cgit v1.2.1 From 81910f64ece4b1ca9e7e1ff276d673ef2321b1ea Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 26 Apr 2009 23:24:50 -0700 Subject: hdt: Add disk callbacks (CLI) In the hdt mode, `show disk' outputs a summary for all disks (C/H/S, EDD (version, size) and host/interface). In the disk mode, `show' outputs the same as above, `show disks' a full description for all disks (with partitions) and `show disk 0x80' detailed information for one disk only (0x80 in that example). Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 114 ++++++++++++++++++++++++++++++++++++++--------- com32/hdt/hdt-cli-hdt.c | 2 +- com32/hdt/hdt-cli.h | 2 +- 3 files changed, 94 insertions(+), 24 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 506efba7..3209c8b1 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -100,12 +100,82 @@ static void show_partition_information(struct driveinfo *drive_info, free(parttype); } -void main_show_disk(int argc __unused, char **argv __unused, +void main_show_disk(int argc, char **argv, struct s_hardware *hardware) { - int i = -1; + reset_more_printf(); + if (!argc) { + more_printf("Which disk?\n"); + return; + } + + int drive = strtol(argv[0], (char**) NULL, 16); + + if (drive < 0x80 || drive >= 0xff) { + more_printf("Invalid disk: %d.\n", drive); + return; + } + + int i = drive - 0x80; + struct driveinfo *d = &hardware->disk_info[i]; int error; char *error_buffer; + char disk_size[8]; + + detect_disks(hardware); + if (!hardware->disk_info[i].cbios) + return; /* Invalid geometry */ + + if ((int) d->edd_params.sectors > 0) + sectors_to_size((int) d->edd_params.sectors, disk_size); + else + memset(disk_size, 0, sizeof disk_size); + + more_printf("DISK 0x%X:\n", d->disk); + more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n", + d->legacy_max_cylinder + 1, d->legacy_max_head + 1, + d->legacy_sectors_per_track); + more_printf(" EDD: Version: %X\n", d->edd_version); + more_printf(" Size: %s, %d bytes/sector, %d sectors/track\n", + disk_size, + (int) d->edd_params.bytes_per_sector, + (int) d->edd_params.sectors_per_track); + more_printf(" Host bus: %s, Interface type: %s\n\n", + remove_spaces(d->edd_params.host_bus_type), + remove_spaces(d->edd_params.interface_type)); + + more_printf(" # B Start End Size Id Type\n"); + error = 0; + if (parse_partition_table(d, &show_partition_information, &error)) { + if (error) { + more_printf("I/O error: "); + get_error(error, &error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); + } else + more_printf("An unknown error occured.\n"); + return; + } +} + +void main_show_disks(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + detect_disks(hardware); + + for (int drive = 0x80; drive < 0xff; drive++) { + char buf[5] = ""; + sprintf(buf, "0x%x", drive); + char *argv[1] = { buf }; + main_show_disk(1, argv, hardware); + } +} + +void disks_summary(int argc __unused, char** argv __unused, + struct s_hardware *hardware) +{ + int i = -1; detect_disks(hardware); @@ -125,33 +195,33 @@ void main_show_disk(int argc __unused, char **argv __unused, more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n", d->legacy_max_cylinder + 1, d->legacy_max_head + 1, d->legacy_sectors_per_track); - more_printf(" EDD: Version: %X\n", d->edd_version); - more_printf(" Size: %s, %d bytes/sector, %d sectors/track\n", - disk_size, - (int) d->edd_params.bytes_per_sector, - (int) d->edd_params.sectors_per_track); + more_printf(" EDD: Version: %X, size: %s\n", d->edd_version, + disk_size); more_printf(" Host bus: %s, Interface type: %s\n\n", remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); - - more_printf(" # B Start End Size Id Type\n"); - error = 0; - if (parse_partition_table(d, &show_partition_information, &error)) { - if (error) { - more_printf("I/O error: "); - get_error(error, &error_buffer); - more_printf("%s\n", error_buffer); - free(error_buffer); - } else - more_printf("An unknown error occured.\n"); - continue; - } } } +struct cli_callback_descr list_disk_show_modules[] = { + { + .name = "disks", + .exec = main_show_disks, + }, + { + .name = "disk", + .exec = main_show_disk, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + + struct cli_module_descr disk_show_modules = { - .modules = NULL, - .default_callback = main_show_disk, + .modules = list_disk_show_modules, + .default_callback = disks_summary, }; struct cli_mode_descr disk_mode = { diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index 76785a79..df86e691 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -286,7 +286,7 @@ struct cli_callback_descr list_hdt_show_modules[] = { }, { .name = CLI_DISK, - .exec = main_show_disk, + .exec = disks_summary, }, { .name = CLI_PXE, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 9a8e15d7..73e74508 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -177,7 +177,7 @@ void cli_detect_pci(struct s_hardware *hardware); void main_show_cpu(int argc, char **argv, struct s_hardware *hardware); // DISK STUFF -void main_show_disk(int argc, char **argv, struct s_hardware *hardware); +void disks_summary(int argc, char **argv, struct s_hardware *hardware); // PXE STUFF void main_show_pxe(int argc, char **argv, struct s_hardware *hardware); -- cgit v1.2.1 From 8518be2b8e1a9b04d71239610757da22758cc363 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sun, 26 Apr 2009 23:33:53 -0700 Subject: hdt: Fix bug in module lookup (CLI) Compare the exact length. The previous version allowed `show diskkkkkk' to match `show disk'. Using strcmp is safe here, both strings are null-terminated by construction. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 6df2818f..5fe1436a 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -430,16 +430,14 @@ void find_cli_callback_descr(const char* module_name, struct cli_callback_descr** module_found) { int modules_iter = 0; - int module_len = strlen(module_name); if (modules_list == NULL) goto not_found; /* Find the callback to execute */ while (modules_list->modules[modules_iter].name && - strncmp(module_name, - modules_list->modules[modules_iter].name, - strlen(modules_list->modules[modules_iter].name)) != 0) + strcmp(module_name, + modules_list->modules[modules_iter].name) != 0) modules_iter++; if (modules_list->modules[modules_iter].name) { -- cgit v1.2.1 From a335437d0d97ad87db72a26fa4d4392853cd65d2 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 16:41:07 +0200 Subject: pci: Adding get_module_name_from_alias() Impact: Users can now use modules.alias to find kernel modules get_module_name_from_alias() parses modules.alias to find the appropriate kernel modules required by the local pci devices. --- com32/include/sys/pci.h | 4 +- com32/lib/pci/scan.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/com32/include/sys/pci.h b/com32/include/sys/pci.h index b44db62f..dc86ad86 100644 --- a/com32/include/sys/pci.h +++ b/com32/include/sys/pci.h @@ -18,7 +18,8 @@ typedef uint32_t pciaddr_t; enum { ENOPCIIDS = 100, - ENOMODULESPCIMAP + ENOMODULESPCIMAP, + ENOMODULESALIAS }; /* a structure for extended pci information */ @@ -145,6 +146,7 @@ struct match * find_pci_device(const struct pci_domain *pci_domain, struct match *list); int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path); +int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path); int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); void gather_additional_pci_config(struct pci_domain *domain); #endif /* _SYS_PCI_H */ diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index 07794102..1b3e9d1f 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -570,3 +570,128 @@ void free_pci_domain(struct pci_domain *domain) } } } + +/* Try to match any pci device to the appropriate kernel module */ +/* it uses the modules.alias from the boot device */ +int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_path) +{ + char line[MAX_LINE]; + char module_name[21]; // the module name field is 21 char long + char delims[]="*"; // colums are separated by spaces + char vendor_id[16]; + char product_id[16]; + char sub_vendor_id[16]; + char sub_product_id[16]; + FILE *f; + struct pci_device *dev=NULL; + + /* Intializing the linux_kernel_module for each pci device to "unknown" */ + /* adding a dev_info member if needed */ + for_each_pci_func(dev, domain) { + /* initialize the dev_info structure if it doesn't exist yet. */ + if (! dev->dev_info) { + dev->dev_info = zalloc(sizeof *dev->dev_info); + if (!dev->dev_info) + return -1; + } + for (int i=0;idev_info->linux_kernel_module[i], "unknown",7); + } + } + + /* Opening the modules.pcimap (of a linux kernel) from the boot device */ + f=fopen(modules_alias_path, "r"); + if (!f) + return -ENOMODULESALIAS; + + dev->dev_info->linux_kernel_module_count=0; + + /* for each line we found in the modules.pcimap */ + while ( fgets(line, sizeof line, f) ) { + /* skipping unecessary lines */ + if ((line[0] == '#') || (strstr(line,"alias pci:v")==NULL)) + continue; + + /* Resetting temp buffer*/ + memset(module_name,0,sizeof(module_name)); + memset(vendor_id,0,sizeof(vendor_id)); + memset(sub_vendor_id,0,sizeof(sub_vendor_id)); + memset(product_id,0,sizeof(product_id)); + memset(sub_product_id,0,sizeof(sub_product_id)); + strcpy(vendor_id,"0000"); + strcpy(product_id,"0000"); + /* ffff will be used to match any device as in modules.alias + * a missing subvendor/product have to be considered as 0xFFFF*/ + strcpy(sub_product_id,"ffff"); + strcpy(sub_vendor_id,"ffff"); + + char *result = NULL; + int field=0; + + /* looking for the next field */ + result = strtok(line+strlen("alias pci:v"), delims); + while( result != NULL ) { + if (field==0) { + + /* Searching for the vendor separator*/ + char *temp = strstr(result,"d"); + if (temp != NULL) { + strncpy(vendor_id,result,temp-result); + result+=strlen(vendor_id)+1; + } + + /* Searching for the product separator*/ + temp = strstr(result,"sv"); + if (temp != NULL) { + strncpy(product_id,result,temp-result); + result+=strlen(product_id)+1; + } + + /* Searching for the sub vendor separator*/ + temp = strstr(result,"sd"); + if (temp != NULL) { + strncpy(sub_vendor_id,result,temp-result); + result+=strlen(sub_vendor_id)+1; + } + + /* Searching for the sub product separator*/ + temp = strstr(result,"bc"); + if (temp != NULL) { + strncpy(sub_product_id,result,temp-result); + result+=strlen(sub_product_id)+1; + } + /* That's the module name */ + } else if ((strlen(result)>2) && + (result[0]==0x20)) + strcpy(module_name,result+1); + /* We have to replace \n by \0*/ + module_name[strlen(module_name)-1]='\0'; + field++; + + /* Searching the next field */ + result = strtok( NULL, delims ); + } + + /* Now we have extracted informations from the modules.alias + * Let's compare it with the devices we know*/ + int int_vendor_id=hex_to_int(vendor_id); + int int_sub_vendor_id=hex_to_int(sub_vendor_id); + int int_product_id=hex_to_int(product_id); + int int_sub_product_id=hex_to_int(sub_product_id); + /* if a pci_device matches an entry, fill the linux_kernel_module with + the appropriate kernel module */ + for_each_pci_func(dev, domain) { + if (int_vendor_id == dev->vendor && + int_product_id == dev->product && + (int_sub_product_id & dev->sub_product) + == dev->sub_product && + (int_sub_vendor_id & dev->sub_vendor) + == dev->sub_vendor) { + strcpy(dev->dev_info->linux_kernel_module[dev->dev_info->linux_kernel_module_count], module_name); + dev->dev_info->linux_kernel_module_count++; + } + } + } + fclose(f); + return 0; +} -- cgit v1.2.1 From db265a9a03849966ec9183f675d539fc3b0d6ecd Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 16:43:46 +0200 Subject: hdt: Adding modules.alias support Impact: It is now possible to use modules.alias to search kernel modules. This commit rename modules= command line parameter to modules_pcimap= It introduce modules_alias= parameter to override the default "modules.alias" filename. Both methods (pcimap & alias) are tried when detecting hardware. A failure message will occurs only if both methods fails. --- com32/hdt/hdt-cli-kernel.c | 5 +++-- com32/hdt/hdt-cli-pci.c | 27 ++++++++++++++++++++------- com32/hdt/hdt-common.c | 20 +++++++++++++++++--- com32/hdt/hdt-common.h | 2 ++ com32/hdt/hdt-menu-kernel.c | 13 +++++++------ com32/hdt/hdt-menu.c | 3 ++- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/com32/hdt/hdt-cli-kernel.c b/com32/hdt/hdt-cli-kernel.c index d9ba27f8..41c80bea 100644 --- a/com32/hdt/hdt-cli-kernel.c +++ b/com32/hdt/hdt-cli-kernel.c @@ -50,8 +50,9 @@ void main_show_kernel(int argc __unused, char **argv __unused, // more_printf(" PCI device no: %d \n", p->pci_device_pos); - if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { - more_printf(" modules.pcimap is missing\n"); + if ((hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) + && (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { + more_printf(" modules.pcimap and modules.alias files are missing\n"); return; } diff --git a/com32/hdt/hdt-cli-pci.c b/com32/hdt/hdt-cli-pci.c index 39bc0fb9..d130b7b3 100644 --- a/com32/hdt/hdt-cli-pci.c +++ b/com32/hdt/hdt-cli-pci.c @@ -50,6 +50,8 @@ static void show_pci_device(int argc, char **argv, int pcidev = -1; bool nopciids = false; bool nomodulespcimap = false; + bool nomodulesalias = false; + bool nomodulesfiles = false; char kernel_modules[LINUX_KERNEL_MODULE_SIZE * MAX_KERNEL_MODULES_PER_PCI_DEVICE]; int bus = 0, slot = 0, func = 0; @@ -75,7 +77,10 @@ static void show_pci_device(int argc, char **argv, if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { nomodulespcimap = true; } - + if (hardware->modules_alias_return_code == -ENOMODULESALIAS) { + nomodulesalias = true; + } + nomodulesfiles=nomodulespcimap && nomodulesalias; for_each_pci_func(temp_pci_device, hardware->pci_domain) { i++; if (i == pcidev) { @@ -115,7 +120,7 @@ static void show_pci_device(int argc, char **argv, pci_device->dev_info->class_name); } - if (nomodulespcimap == false) { + if (nomodulesfiles == false) { printf("Kernel module : %s\n", kernel_modules); } @@ -152,6 +157,8 @@ static void show_pci_devices(int argc __unused, char **argv __unused, MAX_KERNEL_MODULES_PER_PCI_DEVICE]; bool nopciids = false; bool nomodulespcimap = false; + bool nomodulesalias = false; + bool nomodulesfile = false; char first_line[81]; char second_line[81]; @@ -164,6 +171,11 @@ static void show_pci_devices(int argc __unused, char **argv __unused, if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { nomodulespcimap = true; } + if (hardware->modules_pcimap_return_code == -ENOMODULESALIAS) { + nomodulesalias = true; + } + + nomodulesfile = nomodulespcimap && nomodulesalias; /* For every detected pci device, compute its submenu */ for_each_pci_func(pci_device, hardware->pci_domain) { @@ -186,7 +198,7 @@ static void show_pci_devices(int argc __unused, char **argv __unused, "%02d: %s %s \n", i, pci_device->dev_info->vendor_name, pci_device->dev_info->product_name); - if (nomodulespcimap == false) + if (nomodulesfile == false) snprintf(second_line, sizeof(second_line), " # %-25s # Kmod: %s\n", pci_device->dev_info->class_name, @@ -204,7 +216,7 @@ static void show_pci_devices(int argc __unused, char **argv __unused, more_printf(second_line); more_printf("\n"); } else if (nopciids == true) { - if (nomodulespcimap == true) { + if (nomodulesfile == true) { more_printf("%02d: %04x:%04x [%04x:%04x] \n", i, pci_device->vendor, pci_device->product, @@ -299,10 +311,11 @@ void cli_detect_pci(struct s_hardware *hardware) printf("Please put one in same dir as hdt\n"); error = true; } - if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + if ((hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) && + (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { printf - ("The modules.pcimap file is missing, device names can't be computed.\n"); - printf("Please put one in same dir as hdt\n"); + ("The modules.pcimap or modules.alias files are missing, device names can't be computed.\n"); + printf("Please put one of them in same dir as hdt\n"); error = true; } if (error == true) { diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 0331bd19..987c5ae7 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -56,14 +56,18 @@ void detect_parameters(const int argc, const char *argv[], struct s_hardware *hardware) { for (int i = 1; i < argc; i++) { - if (!strncmp(argv[i], "modules=", 8)) { - strncpy(hardware->modules_pcimap_path, argv[i] + 8, + if (!strncmp(argv[i], "modules_pcimap=", 15)) { + strncpy(hardware->modules_pcimap_path, argv[i] + 15, sizeof(hardware->modules_pcimap_path)); convert_isolinux_filename(hardware->modules_pcimap_path,hardware); } else if (!strncmp(argv[i], "pciids=", 7)) { strncpy(hardware->pciids_path, argv[i] + 7, sizeof(hardware->pciids_path)); convert_isolinux_filename(hardware->pciids_path,hardware); + } else if (!strncmp(argv[i], "modules_alias=", 14)) { + strncpy(hardware->modules_alias_path, argv[i] + 14, + sizeof(hardware->modules_alias_path)); + convert_isolinux_filename(hardware->modules_alias_path,hardware); } else if (!strncmp(argv[i], "memtest=", 8)) { strncpy(hardware->memtest_label, argv[i] + 8, sizeof(hardware->memtest_label)); @@ -100,6 +104,7 @@ void init_hardware(struct s_hardware *hardware) { hardware->pci_ids_return_code = 0; hardware->modules_pcimap_return_code = 0; + hardware->modules_alias_return_code = 0; hardware->cpu_detection = false; hardware->pci_detection = false; hardware->disk_detection = false; @@ -125,9 +130,12 @@ void init_hardware(struct s_hardware *hardware) memset(hardware->pciids_path, 0, sizeof hardware->pciids_path); memset(hardware->modules_pcimap_path, 0, sizeof hardware->modules_pcimap_path); + memset(hardware->modules_alias_path, 0, + sizeof hardware->modules_alias_path); memset(hardware->memtest_label, 0, sizeof hardware->memtest_label); strcat(hardware->pciids_path, "pci.ids"); strcat(hardware->modules_pcimap_path, "modules.pcimap"); + strcat(hardware->modules_alias_path, "modules.alias"); strcat(hardware->memtest_label, "memtest"); } @@ -451,11 +459,17 @@ void detect_pci(struct s_hardware *hardware) hardware->pciids_path); printf("PCI: Resolving module names\n"); - /* Detecting which kernel module should match each device */ + /* Detecting which kernel module should match each device using modules.pcimap*/ hardware->modules_pcimap_return_code = get_module_name_from_pcimap(hardware->pci_domain, hardware->modules_pcimap_path); + /* Detecting which kernel module should match each device using modules.alias*/ + hardware->modules_alias_return_code = + get_module_name_from_alias(hardware->pci_domain, + hardware->modules_alias_path); + + /* We try to detect the pxe stuff to populate the PXE: field of pci devices */ detect_pxe(hardware); } diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h index 9fd8a565..5118dd6a 100644 --- a/com32/hdt/hdt-common.h +++ b/com32/hdt/hdt-common.h @@ -117,6 +117,7 @@ struct s_hardware { int pci_ids_return_code; int modules_pcimap_return_code; + int modules_alias_return_code; int nb_pci_devices; bool is_dmi_valid; bool is_pxe_valid; @@ -134,6 +135,7 @@ struct s_hardware { char syslinux_fs[22]; const struct syslinux_version *sv; char modules_pcimap_path[255]; + char modules_alias_path[255]; char pciids_path[255]; char memtest_label[255]; }; diff --git a/com32/hdt/hdt-menu-kernel.c b/com32/hdt/hdt-menu-kernel.c index b94d1fed..7e2d6cab 100644 --- a/com32/hdt/hdt-menu-kernel.c +++ b/com32/hdt/hdt-menu-kernel.c @@ -41,13 +41,14 @@ void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware) menu->items_count = 0; set_menu_pos(SUBMENU_Y, SUBMENU_X); - if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { - add_item("The modules.pcimap file is missing", - "Missing modules.pcimap file", OPT_INACTIVE, NULL, 0); + if ((hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) && + (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { + add_item("The modules.{pcimap|alias} file is missing", + "Missing modules.{pcimap|alias} file", OPT_INACTIVE, NULL, 0); add_item("Kernel modules can't be computed.", - "Missing modules.pcimap file", OPT_INACTIVE, NULL, 0); - add_item("Please put one in same dir as hdt", - "Missing modules.pcimap file", OPT_INACTIVE, NULL, 0); + "Missing modules.{pcimap|alias} file", OPT_INACTIVE, NULL, 0); + add_item("Please put one of them in same dir as hdt", + "Missing modules.{pcimap|alias} file", OPT_INACTIVE, NULL, 0); add_item("", "", OPT_SEP, "", 0); } else { /* diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index a699f72a..2f4f1209 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -263,7 +263,8 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) add_item("", "", OPT_SEP, "", 0); #ifdef WITH_PCI - if (hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) { + if ((hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) || + (hardware->modules_alias_return_code != -ENOMODULESALIAS)) { add_item("ernel Modules", "Kernel Modules Menu", OPT_SUBMENU, NULL, hdt_menu->kernel_menu.menu); hdt_menu->main_menu.items_count++; -- cgit v1.2.1 From 2bc1f8f6971f8cd6e3b6b4a4ad1168d10b839cab Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 16:50:59 +0200 Subject: hdt: fix wrong kernel module display in menu mode Impact: prevent wrong module display for some pci devices The buffer wasn't clean and could contain some previous kernel modules. This bug leads to display too many kernel modules for a single pci device --- com32/hdt/hdt-menu-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com32/hdt/hdt-menu-pci.c b/com32/hdt/hdt-menu-pci.c index 74c07107..451aaaeb 100644 --- a/com32/hdt/hdt-menu-pci.c +++ b/com32/hdt/hdt-menu-pci.c @@ -94,6 +94,8 @@ static void compute_pci_device(struct s_my_menu *menu, add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); menu->items_count++; + memset(kernel_modules,0,sizeof(kernel_modules)); + if (pci_device->dev_info->linux_kernel_module_count > 1) { for (int i = 0; i < pci_device->dev_info->linux_kernel_module_count; i++) { -- cgit v1.2.1 From 1576299ac1409d028d5f88d1edfe34c804cb3eea Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 16:56:16 +0200 Subject: hdt: preventing mac address to be shown of all pci devices Impact: Fixing wrong display of MAC Address This commit fix a wrong behavior where the MAC address was displaying for every pci device instead of only for the related pci device. --- com32/hdt/hdt-menu-pci.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/com32/hdt/hdt-menu-pci.c b/com32/hdt/hdt-menu-pci.c index 451aaaeb..4e0d5887 100644 --- a/com32/hdt/hdt-menu-pci.c +++ b/com32/hdt/hdt-menu-pci.c @@ -119,14 +119,15 @@ static void compute_pci_device(struct s_my_menu *menu, menu->items_count++; if (hardware->is_pxe_valid == true) { - snprintf(buffer,sizeof buffer,"MAC Addr. : %s",hardware->pxe.mac_addr); - snprintf(statbuffer,sizeof statbuffer,"MAC Address : %s",hardware->pxe.mac_addr); - add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); - menu->items_count++; - if ((hardware->pxe.pci_device != NULL) && (hardware->pxe.pci_device == pci_device)) { - snprintf(buffer,sizeof buffer,"PXE : %s","Current Boot device"); + + snprintf(buffer,sizeof buffer,"MAC Addr: %s",hardware->pxe.mac_addr); + snprintf(statbuffer,sizeof statbuffer,"MAC Address : %s",hardware->pxe.mac_addr); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"PXE : %s","Current Boot device"); snprintf(statbuffer,sizeof statbuffer,"PXE : %s","Current Boot device"); add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); menu->items_count++; -- cgit v1.2.1 From 457d3e6325861028a7dbf60fac87e0dce293ade9 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 17:17:35 +0200 Subject: pci: prevent modules.alias to destroy modules.pcimap content Impact: multiple get_module_name_from_* corrupt result Prior to that commit, calling both get_module_name_from_pcimap and get_module_name_from_alias were reporting unknown modules. --- com32/lib/pci/scan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index 1b3e9d1f..8df77052 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -95,7 +95,8 @@ int get_module_name_from_pcimap(struct pci_domain *domain, char *modules_pcimap_ return -1; } for (int i=0;idev_info->linux_kernel_module[i], "unknown",7); + if (strlen(dev->dev_info->linux_kernel_module[i])==0) + strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7); } } @@ -595,7 +596,8 @@ int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_pa return -1; } for (int i=0;idev_info->linux_kernel_module[i], "unknown",7); + if (strlen(dev->dev_info->linux_kernel_module[i])==0) + strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7); } } -- cgit v1.2.1 From 47efe9f5bbcdd0ad81ea8ec8a8c3138f40c53de1 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 17:22:35 +0200 Subject: hdt: missing \n on disk detection Impact: visual improvements Fixing missing return while printing "DISKS: Detecting" --- com32/hdt/hdt-menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index 2f4f1209..ff615017 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -294,7 +294,7 @@ void detect_hardware(struct s_hardware *hardware) printf("CPU: Detecting\n"); cpu_detect(hardware); - printf("DISKS: Detecting"); + printf("DISKS: Detecting\n"); detect_disks(hardware); printf("DMI: Detecting Table\n"); -- cgit v1.2.1 From 45d5c4865a92c4182da9b2498d2606dc33f4f924 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 17:45:16 +0200 Subject: hdt: detect_disks requires detect_vesa (FIXME) Impact: Prevent empty strings while detecting disks Calling detect_vesa before doing int13 make it works.... --- com32/hdt/hdt-common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 987c5ae7..33645ffb 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -257,6 +257,10 @@ void detect_disks(struct s_hardware *hardware) if (hardware->disk_detection) return; + /* FIXME: this is needed to have the int13 working. + * Until we figured why, we need this workaround*/ + detect_vesa(hardware); + hardware->disk_detection = true; for (int drive = 0x80; drive < 0xff; drive++) { i++; -- cgit v1.2.1 From b2d62ad8ee23653521daad7812a89aed63167cc5 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 22:10:47 +0200 Subject: hdt: updating disk's menu to match latest disk api Impact: Menu mode now display every partition Updating the menu to use the latest API. The menu now display all detected partitions --- com32/hdt/hdt-menu-disk.c | 198 ++++++++++++++++++++++++++++++---------------- 1 file changed, 131 insertions(+), 67 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 2283cafa..34c143a4 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -31,30 +31,100 @@ #include #include #include +#include +#include #include "hdt-menu.h" #include "hdt-util.h" -static void compute_partition_info(int partnb, - struct part_entry *ptab, - char menu_title_ref[], - char menu_title[]) +static int dn; + +static void show_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab, + struct part_entry *ptab_root, + int offset_root, int data_partitions_seen, + int ebr_seen) +{ + char menu_title[MENULEN + 1]; + char menu_title_ref[MENULEN + 1]; + /* Useless code to prevent warnings */ + ptab=ptab; ptab_root=ptab_root;offset_root=offset_root; + + int i = 1 + ebr_seen * 4 + data_partitions_seen; + + memset(menu_title,0,sizeof menu_title); + memset(menu_title_ref,0,sizeof menu_title_ref); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", + drive_info[dn].disk, i); + snprintf(menu_title, sizeof menu_title, "Partition %d", i); + + add_item(menu_title, "Partition information (start, end, length, type, ...)", + OPT_SUBMENU, menu_title_ref, 0); + +} +/** + * compute_partition_information - print information about a partition + * @ptab: part_entry describing the partition + * @i: Partition number (UI purposes only) + * @ptab_root: part_entry describing the root partition (extended only) + * @drive_info: driveinfo struct describing the drive on which the partition + * is + * + * Note on offsets (from hpa, see chain.c32): + * + * To make things extra confusing: data partition offsets are relative to where + * the data partition record is stored, whereas extended partition offsets + * are relative to the beginning of the extended partition all the way back + * at the MBR... but still not absolute! + **/ +static void compute_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab, + struct part_entry *ptab_root, + int offset_root, int data_partitions_seen, + int ebr_seen) { - char buffer[56]; - char statbuffer[STATLEN]; - int previous_size, size; - char previous_unit[3], unit[3]; // GB - char size_iec[8]; // GiB - sectors_to_size_dec(previous_unit, &previous_size, unit, &size, ptab->length); - sectors_to_size(ptab->length, size_iec); - - add_named_menu(menu_title_ref, menu_title, -1); - set_menu_pos(5, 17); - - snprintf(buffer, sizeof buffer, "Partition # : %d", - partnb); - snprintf(statbuffer, sizeof statbuffer, "Partition #: %d", - partnb); + char size[8]; + char *parttype; + int error = 0; + char *error_buffer; + unsigned int start, end; + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + char menu_title[MENULEN + 1]; + char menu_title_ref[MENULEN + 1]; + + int i = 1 + ebr_seen * 4 + data_partitions_seen; + + memset(buffer,0,sizeof buffer); + memset(statbuffer,0,sizeof statbuffer); + memset(menu_title,0,sizeof menu_title); + memset(menu_title_ref,0,sizeof menu_title_ref); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", drive_info[dn].disk, i); + snprintf(menu_title, sizeof menu_title, "Partition %d", i); + + add_named_menu(menu_title_ref,menu_title,-1); + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + start = ptab->start_lba + ptab_root->start_lba + offset_root; + end = (ptab->start_lba + ptab_root->start_lba) + ptab->length + offset_root; + + if (ptab->length > 0) + sectors_to_size(ptab->length, size); + else + memset(size, 0, sizeof size); + + get_label(ptab->ostype, &parttype); + + snprintf(buffer, sizeof buffer, "Size : %s)", + remove_spaces(size)); + snprintf(statbuffer, sizeof statbuffer, "Size : %s)", + remove_spaces(size)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Type : %s", + parttype); + snprintf(statbuffer, sizeof statbuffer, "Type: %s", + parttype); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); snprintf(buffer, sizeof buffer, "Bootable : %s", @@ -64,21 +134,15 @@ static void compute_partition_info(int partnb, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); snprintf(buffer, sizeof buffer, "Start : %d", - ptab->start_lba); + start); snprintf(statbuffer, sizeof statbuffer, "Start: %d", - ptab->start_lba); + start); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); snprintf(buffer, sizeof buffer, "End : %d", - ptab->start_lba + ptab->length); + end); snprintf(statbuffer, sizeof statbuffer, "End: %d", - ptab->start_lba + ptab->length); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - - snprintf(buffer, sizeof buffer, "Length : %s/%d %s (%d)", - size_iec, size, unit, ptab->length); - snprintf(statbuffer, sizeof statbuffer, "Length: %s/%d %s (%d)", - size_iec, size, unit, ptab->length); + end); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); snprintf(buffer, sizeof buffer, "Id : %X", @@ -87,14 +151,22 @@ static void compute_partition_info(int partnb, ptab->ostype); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - char *parttype; - get_label(ptab->ostype, &parttype); - snprintf(buffer, sizeof buffer, "Type : %s", - parttype); - snprintf(statbuffer, sizeof statbuffer, "Type: %s", - parttype); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + free(parttype); + + /* Extra info */ + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab, &error)) { + snprintf(buffer, sizeof buffer, "%s","Swsusp sig : detected"); + snprintf(statbuffer, sizeof statbuffer, "%s","Swsusp sig : detected"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } else if (error) { + get_error(error, &error_buffer); + snprintf(buffer, sizeof buffer, "%s",error_buffer); + snprintf(statbuffer, sizeof statbuffer, "%s",error_buffer); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + free(error_buffer); + } + } /* Compute the disk submenu */ @@ -103,7 +175,6 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, { char buffer[MENULEN + 1]; char statbuffer[STATLEN + 1]; - char *mbr = NULL; snprintf(buffer, sizeof buffer, " Disk <0x%X> ", d[disk_number].disk); menu[nb_sub_disk_menu].menu = add_menu(buffer, -1); @@ -115,9 +186,9 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, sectors_to_size_dec(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); sectors_to_size(d[disk_number].edd_params.sectors, size_iec); - snprintf(buffer, sizeof buffer, "Size : %s/%d %s (%d %s)", size_iec, + snprintf(buffer, sizeof buffer, "Size : %s/%d %s (%d %s)", remove_spaces(size_iec), size, unit, previous_size, previous_unit); - snprintf(statbuffer, sizeof statbuffer, "Size: %s/%d %s (%d %s)", size_iec, size, + snprintf(statbuffer, sizeof statbuffer, "Size: %s/%d %s (%d %s)", remove_spaces(size_iec), size, unit, previous_size, previous_unit); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; @@ -176,34 +247,27 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - add_sep(); - - /* Compute disk partitions menus */ - mbr = read_mbr(d[disk_number].disk, NULL); - if (mbr) { - struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); - char menu_title[MENULEN + 1]; - char menu_title_ref[MENULEN + 1]; - /* The calls to add_item need to be done first to draw the main submenu first */ - int submenu_done = 0; -submenu_disk: - for (int i = 0; i < 4; i++) { - if (ptab[i].ostype) { - snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", d[disk_number].disk, i); - snprintf(menu_title, sizeof menu_title, "Disk <%X>, Partition %d", d[disk_number].disk, i); - if (!submenu_done) - add_item(menu_title, "Partition information (start, end, length, type, ...)", - OPT_SUBMENU, menu_title_ref, 0); - else - compute_partition_info(i, &ptab[i], menu_title_ref, menu_title); - } - /* Now, draw the sub sub menus */ - if (i == 3 && !submenu_done) { - submenu_done = 1; - goto submenu_disk; - } - } - } + add_sep(); + dn=disk_number; + + int error; + parse_partition_table(d, &show_partition_information, &error); + if (parse_partition_table(d, &compute_partition_information, &error)) { + if (error) { + char *error_buffer; + get_error(error, &error_buffer); + snprintf(buffer, sizeof buffer, "I/O error : %s", error_buffer); + snprintf(statbuffer, sizeof statbuffer, "I/O error : %s", error_buffer); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + free(error_buffer); + } else { + snprintf(buffer, sizeof buffer, "An unknown error occured"); + snprintf(statbuffer, sizeof statbuffer, "An unknown error occured"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + } + } return 0; } -- cgit v1.2.1 From f3518b90f640af68dc939f2b3da3583014805e3e Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 22:33:47 +0200 Subject: hdt: optmizing disk's menu Impact: Improving visuals Optimizing disk'screen to have an efficient display --- com32/hdt/hdt-menu-disk.c | 54 ++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 34c143a4..730d20b7 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -176,7 +176,8 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, char buffer[MENULEN + 1]; char statbuffer[STATLEN + 1]; - snprintf(buffer, sizeof buffer, " Disk <0x%X> ", d[disk_number].disk); + snprintf(buffer, sizeof buffer, " Disk <0x%X> (EDD %X)", d[disk_number].disk, + d[disk_number].edd_version); menu[nb_sub_disk_menu].menu = add_menu(buffer, -1); menu[nb_sub_disk_menu].items_count = 0; @@ -186,67 +187,40 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, sectors_to_size_dec(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); sectors_to_size(d[disk_number].edd_params.sectors, size_iec); - snprintf(buffer, sizeof buffer, "Size : %s/%d %s (%d %s)", remove_spaces(size_iec), + snprintf(buffer, sizeof buffer, "Size : %s/%d %s (%d %s)", remove_spaces(size_iec), size, unit, previous_size, previous_unit); snprintf(statbuffer, sizeof statbuffer, "Size: %s/%d %s (%d %s)", remove_spaces(size_iec), size, unit, previous_size, previous_unit); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Interface : %s", + snprintf(buffer, sizeof buffer, "Host Bus / Interface : %s / %s", + remove_spaces(d[disk_number].edd_params.host_bus_type), d[disk_number].edd_params.interface_type); - snprintf(statbuffer, sizeof statbuffer, "Interface: %s", + snprintf(statbuffer, sizeof statbuffer, "Host Bus / Interface: %s / %s", + remove_spaces(d[disk_number].edd_params.host_bus_type), d[disk_number].edd_params.interface_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Host Bus : %s", - d[disk_number].edd_params.host_bus_type); - snprintf(statbuffer, sizeof statbuffer, "Host Bus Type: %s", - d[disk_number].edd_params.host_bus_type); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - - snprintf(buffer, sizeof buffer, "Sectors : %d", + snprintf(buffer, sizeof buffer, "C / H / S : %d / %d / %d", + d[disk_number].legacy_max_cylinder + 1, + d[disk_number].legacy_max_head + 1, (int) d[disk_number].edd_params.sectors); - snprintf(statbuffer, sizeof statbuffer, "Sectors: %d", + snprintf(statbuffer, sizeof statbuffer, "Cylinders / Heads / Sectors: %d / %d / %d", + d[disk_number].legacy_max_cylinder + 1, + d[disk_number].legacy_max_head + 1, (int) d[disk_number].edd_params.sectors); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Heads : %d", - d[disk_number].legacy_max_head + 1); - snprintf(statbuffer, sizeof statbuffer, "Heads: %d", - d[disk_number].legacy_max_head + 1); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - - snprintf(buffer, sizeof buffer, "Cylinders : %d", - d[disk_number].legacy_max_cylinder + 1); - snprintf(statbuffer, sizeof statbuffer, "Cylinders: %d", - d[disk_number].legacy_max_cylinder + 1); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - - snprintf(buffer, sizeof buffer, "Sectors/Track : %d", + snprintf(buffer, sizeof buffer, "Sectors/Track : %d", d[disk_number].legacy_sectors_per_track); snprintf(statbuffer, sizeof statbuffer, "Sectors per Track: %d", d[disk_number].legacy_sectors_per_track); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - snprintf(buffer, sizeof buffer, "Drive number : 0x%X", d[disk_number].disk); - snprintf(statbuffer, sizeof statbuffer, "Drive number: 0x%X", d[disk_number].disk); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - - snprintf(buffer, sizeof buffer, "EDD Version : %X", - d[disk_number].edd_version); - snprintf(statbuffer, sizeof statbuffer, "EDD Version: %X", - d[disk_number].edd_version); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - add_sep(); dn=disk_number; -- cgit v1.2.1 From 16cf9d768f36fc57ae0ffdd05047554f49b3d26a Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 27 Apr 2009 22:37:19 +0200 Subject: hdt: 0.3.2-pre1 Impact: pre version pre1 --- com32/hdt/hdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index dfcb4368..1bb3a0d7 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -32,7 +32,7 @@ #define PRODUCT_NAME "Hardware Detection Tool" #define AUTHOR "Erwan Velu" #define CONTACT "hdt@zytor.com" -#define VERSION "0.3.1" +#define VERSION "0.3.2-pre1" #define NB_CONTRIBUTORS 2 #define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"} -- cgit v1.2.1 From 2d34df8a37030e609ec867c33c0f84a73d902058 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 28 Apr 2009 20:57:48 +0200 Subject: hdt: Remove useless comments Impact: code cleaning Removing useless comments --- com32/hdt/hdt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/com32/hdt/hdt.c b/com32/hdt/hdt.c index a2b9b538..93c4aae2 100644 --- a/com32/hdt/hdt.c +++ b/com32/hdt/hdt.c @@ -51,6 +51,7 @@ int main(const int argc, const char *argv[]) snprintf(version_string, sizeof version_string, "%s %s by %s", PRODUCT_NAME,VERSION,AUTHOR); + /* Opening the Syslinux console */ console_ansi_raw(); /* Cleaning structures */ @@ -62,8 +63,6 @@ int main(const int argc, const char *argv[]) /* Detecting parameters */ detect_parameters(argc, argv, &hardware); - /* Opening the Syslinux console */ -// openconsole(&dev_stdcon_r, &dev_ansicon_w); clear_screen(); printf("%s\n", version_string); -- cgit v1.2.1 From d222f57d5fce7908f7cca3f32546ac789e8b3f4d Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Wed, 29 Apr 2009 20:00:19 +0200 Subject: cmenu: fixing getnumrows values Impact: Allow users to use 25 lines instead of 24 Prior to that commit it was impossible to setup a 25 lines menu --- com32/cmenu/libmenu/com32io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/cmenu/libmenu/com32io.h b/com32/cmenu/libmenu/com32io.h index 78ce72fa..c95c0cd8 100644 --- a/com32/cmenu/libmenu/com32io.h +++ b/com32/cmenu/libmenu/com32io.h @@ -71,7 +71,7 @@ static inline unsigned char readbiosb(unsigned int ofs) static inline char getnumrows() { - return readbiosb(0x484); // Actually numrows - 1 + return readbiosb(0x484)+1; // Actually numrows - 1 } static inline char getnumcols(void) -- cgit v1.2.1 From 146c95f97bf8818278be0662f7fefce42c9c0626 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 30 Apr 2009 20:42:43 -0700 Subject: gpllib: Add copyright/license information (disklib) The disklib is distributed under GPLv2. Add copyright holders for borrowed code: * H. Peter Anvin/Intel Corporation (read/write BIOS calls) * Matt Domsch (edd structures) Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/common.h | 14 ++++++++++++++ com32/gplinclude/disk/error.h | 9 +++++++++ com32/gplinclude/disk/geom.h | 19 +++++++++++++++++++ com32/gplinclude/disk/msdos.h | 9 +++++++++ com32/gplinclude/disk/partition.h | 14 ++++++++++++++ com32/gplinclude/disk/read.h | 9 +++++++++ com32/gplinclude/disk/util.h | 14 ++++++++++++++ com32/gplinclude/disk/write.h | 14 ++++++++++++++ com32/gpllib/disk/error.c | 9 +++++++++ com32/gpllib/disk/geom.c | 14 ++++++++++++++ com32/gpllib/disk/labels.c | 9 +++++++++ com32/gpllib/disk/msdos.c | 14 ++++++++++++++ com32/gpllib/disk/read.c | 14 ++++++++++++++ com32/gpllib/disk/util.c | 14 ++++++++++++++ com32/gpllib/disk/write.c | 14 ++++++++++++++ 15 files changed, 190 insertions(+) diff --git a/com32/gplinclude/disk/common.h b/com32/gplinclude/disk/common.h index 6e4f3d61..c6df2f4e 100644 --- a/com32/gplinclude/disk/common.h +++ b/com32/gplinclude/disk/common.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _COMMON_H_ #define _COMMON_H_ diff --git a/com32/gplinclude/disk/error.h b/com32/gplinclude/disk/error.h index 3a7614e9..5eb54e01 100644 --- a/com32/gplinclude/disk/error.h +++ b/com32/gplinclude/disk/error.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _ERROR_H_ #define _ERROR_H_ void get_error(const int, char**); diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h index 30dc86bf..0d3eed57 100644 --- a/com32/gplinclude/disk/geom.h +++ b/com32/gplinclude/disk/geom.h @@ -1,3 +1,22 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 2002, 2003, 2004 Dell Inc. + * by Matt Domsch + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _GEOM_H_ #define _GEOM_H_ diff --git a/com32/gplinclude/disk/msdos.h b/com32/gplinclude/disk/msdos.h index b6dd9481..1f565f32 100644 --- a/com32/gplinclude/disk/msdos.h +++ b/com32/gplinclude/disk/msdos.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _MSDOS_H_ #define _MSDOS_H_ diff --git a/com32/gplinclude/disk/partition.h b/com32/gplinclude/disk/partition.h index 3bffa89e..be6bfaab 100644 --- a/com32/gplinclude/disk/partition.h +++ b/com32/gplinclude/disk/partition.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _PARTITION_H_ #define _PARTITION_H_ diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h index fee10daf..6d6d9fe9 100644 --- a/com32/gplinclude/disk/read.h +++ b/com32/gplinclude/disk/read.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _READ_H_ #define _READ_H_ diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h index dd0d5c02..df2eadda 100644 --- a/com32/gplinclude/disk/util.h +++ b/com32/gplinclude/disk/util.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _UTIL_H_ #define _UTIL_H_ diff --git a/com32/gplinclude/disk/write.h b/com32/gplinclude/disk/write.h index be6494fa..fe251f94 100644 --- a/com32/gplinclude/disk/write.h +++ b/com32/gplinclude/disk/write.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _WRITE_H_ #define _WRITE_H_ diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 763dcfdc..6848ef3e 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 7bbb698d..02ac681b 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/labels.c b/com32/gpllib/disk/labels.c index cb28be9d..7efe1ad1 100644 --- a/com32/gpllib/disk/labels.c +++ b/com32/gpllib/disk/labels.c @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index da28b8bb..9bfcacca 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index a5cb120c..3fc0e0c7 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/util.c b/com32/gpllib/disk/util.c index c03ed37b..6faac399 100644 --- a/com32/gpllib/disk/util.c +++ b/com32/gpllib/disk/util.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index cd585481..70c73ba4 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include -- cgit v1.2.1 From c9621dba0331d0024f9c43fc2a5a9f91decded67 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Fri, 1 May 2009 07:48:35 +0200 Subject: hdt: removing useless clear screen on dmi> show memory Impact: Improving display usage No need to clearscreen for such display --- com32/hdt/hdt-cli-dmi.c | 12 ++---------- com32/hdt/hdt-cli-hdt.c | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index d395c672..4e18b794 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -374,19 +374,13 @@ void main_show_dmi(int argc __unused, char **argv __unused, void show_dmi_memory_modules(int argc __unused, char** argv __unused, struct s_hardware *hardware) { - int clear = 1, show_free_banks = 1; + int show_free_banks = 1; /* Sanitize arguments */ if (argc > 0) { - clear = strtol(argv[0], NULL, 10); - if (errno == ERANGE || clear < 0 || clear > 1) - goto usage; - - if (argc > 1) { - show_free_banks = strtol(argv[1], NULL, 10); + show_free_banks = strtol(argv[0], NULL, 10); if (errno == ERANGE || show_free_banks < 0 || show_free_banks > 1) goto usage; - } } char bank_number[10]; @@ -398,8 +392,6 @@ void show_dmi_memory_modules(int argc __unused, char** argv __unused, return; } - if (clear) - clear_screen(); more_printf("Memory Banks\n"); for (int i = 0; i < hardware->dmi.memory_count; i++) { if (hardware->dmi.memory[i].filled == true) { diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index df86e691..8069b190 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -217,8 +217,8 @@ void main_show_summary(int argc __unused, char **argv __unused, more_printf(" Release : %s\n", hardware->dmi.bios.release_date); - int argc = 2; - char *argv[2] = { "0", "0" }; + int argc = 1; + char *argv[1] = { "0" }; show_dmi_memory_modules(argc, argv, hardware); } main_show_pci(argc, argv, hardware); -- cgit v1.2.1 From b82f770d01303e1a5a0dedb006b992e01f6b6276 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 2 May 2009 08:52:55 -0700 Subject: gpllib: Add detect_memory_e820 call detect_memory_e820 populates an array of struct e820entry using INT 15, AX = E820h. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/memory.h | 35 +++++++++++ com32/gpllib/Makefile | 3 +- com32/gpllib/memory.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 com32/gplinclude/memory.h create mode 100644 com32/gpllib/memory.c diff --git a/com32/gplinclude/memory.h b/com32/gplinclude/memory.h new file mode 100644 index 00000000..b5232f53 --- /dev/null +++ b/com32/gplinclude/memory.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from meminfo.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2007 rPath, Inc. - All Rights Reserved + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _MEMORY_H_ +#define _MEMORY_H_ +#include + +struct e820entry { + uint64_t addr; /* start of memory segment */ + uint64_t size; /* size of memory segment */ + uint64_t type; /* type of memory segment */ +} __attribute__((packed)); + +const char * const e820_types[5]; + +void get_type(int, char*, int); +void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found); +#endif diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 83f1407a..e8d7e57f 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -11,7 +11,8 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o disk/msdos.o \ - disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o + disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o \ + memory.o BINDIR = /usr/bin LIBDIR = /usr/lib diff --git a/com32/gpllib/memory.c b/com32/gpllib/memory.c new file mode 100644 index 00000000..969e7230 --- /dev/null +++ b/com32/gpllib/memory.c @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from meminfo.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2007 rPath, Inc. - All Rights Reserved + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * Interrupt list from Ralf Brown (http://www.cs.cmu.edu/~ralf/files.html) + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include + +const char * const e820_types[] = { + "usable", + "reserved", + "ACPI reclaim", + "ACPI NVS", + "unusable", +}; + +struct e820_ext_entry { + struct e820entry std; + uint32_t ext_flags; +} __attribute__((packed)); + +#define SMAP 0x534d4150 /* ASCII "SMAP" */ + +void get_type(int type, char *type_ptr, int type_ptr_sz) +{ + unsigned int real_type = type - 1; + if (real_type < sizeof(e820_types)/sizeof(e820_types[0])) + strncpy(type_ptr, e820_types[real_type], type_ptr_sz); +} + +/** + *INT 15 - newer BIOSes - GET SYSTEM MEMORY MAP + * AX = E820h + * EAX = 0000E820h + * EDX = 534D4150h ('SMAP') + * EBX = continuation value or 00000000h to start at beginning of map + * ECX = size of buffer for result, in bytes (should be >= 20 bytes) + * ES:DI -> buffer for result (see #00581) + * + * Return: CF clear if successful + * EAX = 534D4150h ('SMAP') + * ES:DI buffer filled + * EBX = next offset from which to copy or 00000000h if all done + * ECX = actual length returned in bytes + * CF set on error + * AH = error code (86h) (see #00496 at INT 15/AH=80h) + * + * Notes: originally introduced with the Phoenix BIOS v4.0, this function is + * now supported by most newer BIOSes, since various versions of Windows + * call it to find out about the system memory + * a maximum of 20 bytes will be transferred at one time, even if ECX is + * higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the + * value of ECX on entry, and always copy 20 bytes + * some BIOSes expect the high word of EAX to be clear on entry, i.e. + * EAX=0000E820h + * if this function is not supported, an application should fall back + * to AX=E802h, AX=E801h, and then AH=88h + * the BIOS is permitted to return a nonzero continuation value in EBX + * and indicate that the end of the list has already been reached by + * returning with CF set on the next iteration + * this function will return base memory and ISA/PCI memory contiguous + * with base memory as normal memory ranges; it will indicate + * chipset-defined address holes which are not in use and motherboard + * memory-mapped devices, and all occurrences of the system BIOS as + * reserved; standard PC address ranges will not be reported + * + * ACPI 3.0 added the extended flags support. If bit 0 + * in the extended flags is zero, we're supposed to simply + * ignore the entry -- a backwards incompatible change! + **/ +void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found) +{ + int count = 0; + static struct e820_ext_entry buf; /* static so it is zeroed */ + + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0xe820; + ireg.edx.l = SMAP; + ireg.ecx.l = sizeof(struct e820_ext_entry); + ireg.edi.w[0] = OFFS(__com32.cs_bounce); + ireg.es = SEG(__com32.cs_bounce); + + /* + * Set this here so that if the BIOS doesn't change this field + * but still doesn't change %ecx, we're still okay... + */ + memset(&buf, 0, sizeof buf); + buf.ext_flags = 1; + + do { + memcpy(__com32.cs_bounce, &buf, sizeof buf); + + /* Important: %edx and %esi are clobbered by some BIOSes, + so they must be either used for the error output + or explicitly marked clobbered. Given that, assume there + is something out there clobbering %ebp and %edi, too. */ + __intcall(0x15, &ireg, &oreg); + + /* Some BIOSes stop returning SMAP in the middle of + the search loop. We don't know exactly how the BIOS + screwed up the map at that point, we might have a + partial map, the full map, or complete garbage, so + just return failure. */ + if (oreg.eax.l != SMAP) { + count = 0; + break; + } + + if (oreg.eflags.l & EFLAGS_CF || + oreg.ecx.l < 20) + break; + + memcpy(&buf, __com32.cs_bounce, sizeof buf); + + if (oreg.ecx.l < 24) + buf.ext_flags = 1; + + memcpy(&desc[count], &buf, sizeof buf); + count++; + + /* Set continuation value */ + ireg.ebx.l = oreg.ebx.l; + } while (ireg.ebx.l && count < size_map); + + *size_found = count; +} -- cgit v1.2.1 From f64daac1ca99a8c49dbe18bb38398d55f15ab504 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 2 May 2009 08:56:51 -0700 Subject: hdt: Add memory mode (CLI) The memory mode will be used to dump the memory map (via e820, e802, e801 and 88). Only `show e820' is implemented. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-memory.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ com32/hdt/hdt-cli.c | 6 ++++ com32/hdt/hdt-cli.h | 3 ++ 3 files changed, 84 insertions(+) create mode 100644 com32/hdt/hdt-cli-memory.c diff --git a/com32/hdt/hdt-cli-memory.c b/com32/hdt/hdt-cli-memory.c new file mode 100644 index 00000000..d55c6fb5 --- /dev/null +++ b/com32/hdt/hdt-cli-memory.c @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + */ + +#include + +#include "hdt-cli.h" +#include "hdt-common.h" + +#define E820MAX 128 + +static void show_memory_e820(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + struct e820entry map[E820MAX]; + int count = 0; + char type[14]; + + detect_memory_e820(map, E820MAX, &count); + printf("BIOS-provided physical RAM e820 map:\n"); + for (int i = 0; i < count; i++) { + get_type(map[i].type, type, 14); + more_printf("%016llx - %016llx %016llx (%s)\n", + map[i].addr, map[i].size, map[i].addr+map[i].size, + remove_spaces(type)); + } +} + +struct cli_callback_descr list_memory_show_modules[] = { + { + .name = "e820", + .exec = show_memory_e820, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr memory_show_modules = { + .modules = list_memory_show_modules, + .default_callback = NULL, +}; + +struct cli_mode_descr memory_mode = { + .mode = MEMORY_MODE, + .name = CLI_MEMORY, + .default_modules = NULL, + .show_modules = &memory_show_modules, + .set_modules = NULL, +}; diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 5fe1436a..c77a8bef 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -45,6 +45,7 @@ struct cli_mode_descr *list_modes[] = { &vesa_mode, &disk_mode, &vpd_mode, + &memory_mode, NULL, }; @@ -196,6 +197,11 @@ void set_mode(cli_mode_t mode, struct s_hardware* hardware) snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_VPD); break; + case MEMORY_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", + CLI_MEMORY); + break; default: /* Invalid mode */ printf("Unknown mode, please choose among:\n"); diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 73e74508..df324fd2 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -69,6 +69,7 @@ #define CLI_IRQ "irq" #define CLI_MODES "modes" #define CLI_VPD "vpd" +#define CLI_MEMORY "memory" typedef enum { INVALID_MODE, @@ -83,6 +84,7 @@ typedef enum { VESA_MODE, DISK_MODE, VPD_MODE, + MEMORY_MODE, } cli_mode_t; #define PROMPT_SIZE 32 @@ -142,6 +144,7 @@ struct cli_mode_descr pci_mode; struct cli_mode_descr vesa_mode; struct cli_mode_descr disk_mode; struct cli_mode_descr vpd_mode; +struct cli_mode_descr memory_mode; /* cli helpers */ void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found); -- cgit v1.2.1 From b3a797d35d21bef58b4a36cc76d8e39b822022ec Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 30 Apr 2009 20:42:43 -0700 Subject: gpllib: Add copyright/license information (disklib) The disklib is distributed under GPLv2. Add copyright holders for borrowed code: * H. Peter Anvin/Intel Corporation (read/write BIOS calls) * Matt Domsch (edd structures) Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/common.h | 14 ++++++++++++++ com32/gplinclude/disk/error.h | 9 +++++++++ com32/gplinclude/disk/geom.h | 19 +++++++++++++++++++ com32/gplinclude/disk/msdos.h | 9 +++++++++ com32/gplinclude/disk/partition.h | 14 ++++++++++++++ com32/gplinclude/disk/read.h | 9 +++++++++ com32/gplinclude/disk/util.h | 14 ++++++++++++++ com32/gplinclude/disk/write.h | 14 ++++++++++++++ com32/gpllib/disk/error.c | 9 +++++++++ com32/gpllib/disk/geom.c | 14 ++++++++++++++ com32/gpllib/disk/labels.c | 9 +++++++++ com32/gpllib/disk/msdos.c | 14 ++++++++++++++ com32/gpllib/disk/read.c | 14 ++++++++++++++ com32/gpllib/disk/util.c | 14 ++++++++++++++ com32/gpllib/disk/write.c | 14 ++++++++++++++ 15 files changed, 190 insertions(+) diff --git a/com32/gplinclude/disk/common.h b/com32/gplinclude/disk/common.h index 6e4f3d61..c6df2f4e 100644 --- a/com32/gplinclude/disk/common.h +++ b/com32/gplinclude/disk/common.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _COMMON_H_ #define _COMMON_H_ diff --git a/com32/gplinclude/disk/error.h b/com32/gplinclude/disk/error.h index 3a7614e9..5eb54e01 100644 --- a/com32/gplinclude/disk/error.h +++ b/com32/gplinclude/disk/error.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _ERROR_H_ #define _ERROR_H_ void get_error(const int, char**); diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h index 30dc86bf..0d3eed57 100644 --- a/com32/gplinclude/disk/geom.h +++ b/com32/gplinclude/disk/geom.h @@ -1,3 +1,22 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 2002, 2003, 2004 Dell Inc. + * by Matt Domsch + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _GEOM_H_ #define _GEOM_H_ diff --git a/com32/gplinclude/disk/msdos.h b/com32/gplinclude/disk/msdos.h index b6dd9481..1f565f32 100644 --- a/com32/gplinclude/disk/msdos.h +++ b/com32/gplinclude/disk/msdos.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _MSDOS_H_ #define _MSDOS_H_ diff --git a/com32/gplinclude/disk/partition.h b/com32/gplinclude/disk/partition.h index 3bffa89e..be6bfaab 100644 --- a/com32/gplinclude/disk/partition.h +++ b/com32/gplinclude/disk/partition.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _PARTITION_H_ #define _PARTITION_H_ diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h index fee10daf..6d6d9fe9 100644 --- a/com32/gplinclude/disk/read.h +++ b/com32/gplinclude/disk/read.h @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _READ_H_ #define _READ_H_ diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h index dd0d5c02..df2eadda 100644 --- a/com32/gplinclude/disk/util.h +++ b/com32/gplinclude/disk/util.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _UTIL_H_ #define _UTIL_H_ diff --git a/com32/gplinclude/disk/write.h b/com32/gplinclude/disk/write.h index be6494fa..fe251f94 100644 --- a/com32/gplinclude/disk/write.h +++ b/com32/gplinclude/disk/write.h @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #ifndef _WRITE_H_ #define _WRITE_H_ diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 763dcfdc..6848ef3e 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 7bbb698d..02ac681b 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/labels.c b/com32/gpllib/disk/labels.c index cb28be9d..7efe1ad1 100644 --- a/com32/gpllib/disk/labels.c +++ b/com32/gpllib/disk/labels.c @@ -1,3 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index da28b8bb..9bfcacca 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index a5cb120c..3fc0e0c7 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/util.c b/com32/gpllib/disk/util.c index c03ed37b..6faac399 100644 --- a/com32/gpllib/disk/util.c +++ b/com32/gpllib/disk/util.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index cd585481..70c73ba4 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -1,3 +1,17 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + #include #include #include -- cgit v1.2.1 From 485b4c07c607e2860b4ad96d94627a4394c48721 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Sat, 2 May 2009 19:24:58 +0200 Subject: hdt: 0.3.2 Impact: new release New 0.3.2 release --- com32/hdt/hdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index 1bb3a0d7..e29c7bfe 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -32,7 +32,7 @@ #define PRODUCT_NAME "Hardware Detection Tool" #define AUTHOR "Erwan Velu" #define CONTACT "hdt@zytor.com" -#define VERSION "0.3.2-pre1" +#define VERSION "0.3.2" #define NB_CONTRIBUTORS 2 #define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"} -- cgit v1.2.1 From c8162edd3e880e8f0d84f26ffbf5316dee472ef0 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 2 May 2009 20:37:58 -0700 Subject: gpllib: Fix ACPI 3.0 quirk (memory) If 24 bytes are returned in the e820 map, the entry should be ignored if bit 0 of the Extended Attributes is clear. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/memory.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/com32/gpllib/memory.c b/com32/gpllib/memory.c index 969e7230..91e9874e 100644 --- a/com32/gpllib/memory.c +++ b/com32/gpllib/memory.c @@ -82,10 +82,6 @@ void get_type(int type, char *type_ptr, int type_ptr_sz) * chipset-defined address holes which are not in use and motherboard * memory-mapped devices, and all occurrences of the system BIOS as * reserved; standard PC address ranges will not be reported - * - * ACPI 3.0 added the extended flags support. If bit 0 - * in the extended flags is zero, we're supposed to simply - * ignore the entry -- a backwards incompatible change! **/ void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found) { @@ -133,8 +129,13 @@ void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found) memcpy(&buf, __com32.cs_bounce, sizeof buf); - if (oreg.ecx.l < 24) - buf.ext_flags = 1; + /* + * ACPI 3.0 added the extended flags support. If bit 0 + * in the extended flags is zero, we're supposed to simply + * ignore the entry -- a backwards incompatible change! + */ + if (oreg.ecx.l > 20 && !(buf.ext_flags & 1)) + continue; memcpy(&desc[count], &buf, sizeof buf); count++; -- cgit v1.2.1 From 6e2f4b3d0a6061ea240de478878274898407960c Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 2 May 2009 20:43:18 -0700 Subject: gllib: Add e801 and 88 memory detection Add Bios calls INT 0x15, AX = 0xE801 and INT 0x15, AH = 0x88 to detect the memory. These can be used as a fallback when e820 is not available. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/memory.h | 2 ++ com32/gpllib/memory.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/com32/gplinclude/memory.h b/com32/gplinclude/memory.h index b5232f53..c9f386d4 100644 --- a/com32/gplinclude/memory.h +++ b/com32/gplinclude/memory.h @@ -32,4 +32,6 @@ const char * const e820_types[5]; void get_type(int, char*, int); void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found); +int detect_memory_e801(int*, int*); +int detect_memory_88(int*); #endif diff --git a/com32/gpllib/memory.c b/com32/gpllib/memory.c index 91e9874e..6c6e351c 100644 --- a/com32/gpllib/memory.c +++ b/com32/gpllib/memory.c @@ -146,3 +146,71 @@ void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found) *size_found = count; } + +/** + * detect_memory_e801 + * + *INT 15 - Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS + * AX = E801h + * + * Return: CF clear if successful + * AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) + * BX = extended memory above 16M, in 64K blocks + * CX = configured memory 1M to 16M, in K + * DX = configured memory above 16M, in 64K blocks + * CF set on error + * + * Notes: supported by the A03 level (6/14/94) and later XPS P90 BIOSes, as well + * as the Compaq Contura, 3/8/93 DESKPRO/i, and 7/26/93 LTE Lite 386 ROM + * BIOS + * supported by AMI BIOSes dated 8/23/94 or later + * on some systems, the BIOS returns AX=BX=0000h; in this case, use CX + * and DX instead of AX and BX + * this interface is used by Windows NT 3.1, OS/2 v2.11/2.20, and is + * used as a fall-back by newer versions if AX=E820h is not supported + * this function is not used by MS-DOS 6.0 HIMEM.SYS when an EISA machine + * (for example with parameter /EISA) (see also MEM F000h:FFD9h), or no + * Compaq machine was detected, or parameter /NOABOVE16 was given. + **/ +int detect_memory_e801(int* mem_size_below_16, int* mem_size_above_16) +{ + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0xe801; + + __intcall(0x15, &ireg, &oreg); + + if (oreg.eflags.l & EFLAGS_CF) + return -1; + + if (oreg.eax.w[0] > 0x3c00) + return -1; /* Bogus! */ + + /* Linux seems to use ecx and edx by default if they are defined */ + if (oreg.eax.w[0] || oreg.eax.w[0]) { + oreg.eax.w[0] = oreg.ecx.w[0]; + oreg.ebx.w[0] = oreg.edx.w[0]; + } + + *mem_size_below_16 = oreg.eax.w[0]; /* 1K blocks */ + *mem_size_above_16 = oreg.ebx.w[0]; /* 64K blocks */ + + return 0; +} + +int detect_memory_88(int* mem_size) +{ + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0x8800; + + __intcall(0x15, &ireg, &oreg); + + if (oreg.eflags.l & EFLAGS_CF) + return -1; + + *mem_size = oreg.eax.w[0]; + return 0; +} -- cgit v1.2.1 From e5b7f8a34a095267e97ce23e4477e61327f1e7fa Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 2 May 2009 20:44:56 -0700 Subject: hdt: Add e801 and 88 calls in the memory mode (CLI) Enhance the new memory mode: * show e801: to show the memory layout reported by the INT 15, AX = 0xE801 call * show 88: to show the memory size (contiguous Kb above 1M) reported by the INT 0x15, AH = 0x88 call Note: `show' now defaults to the DMI banks listing. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 3 +++ com32/hdt/hdt-cli-memory.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index d395c672..4c43a691 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -374,6 +374,9 @@ void main_show_dmi(int argc __unused, char **argv __unused, void show_dmi_memory_modules(int argc __unused, char** argv __unused, struct s_hardware *hardware) { + /* Needed, if called by the memory mode */ + detect_dmi(hardware); + int clear = 1, show_free_banks = 1; /* Sanitize arguments */ diff --git a/com32/hdt/hdt-cli-memory.c b/com32/hdt/hdt-cli-memory.c index d55c6fb5..e0516aef 100644 --- a/com32/hdt/hdt-cli-memory.c +++ b/com32/hdt/hdt-cli-memory.c @@ -50,11 +50,45 @@ static void show_memory_e820(int argc __unused, char **argv __unused, } } +static void show_memory_e801(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int mem_low, mem_high = 0; + + if (detect_memory_e801(&mem_low, &mem_high)) { + more_printf("e801 bogus!\n"); + } else { + more_printf("e801: %d Kb (%d MiB) - %d Kb (%d MiB)\n", + mem_low, mem_low >> 10, mem_high << 6, mem_high >> 4); + } +} + +static void show_memory_88(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int mem_size = 0; + + if (detect_memory_88(&mem_size)) { + more_printf("8800h bogus!\n"); + } else { + more_printf("8800h memory size: %d Kb (%d MiB)\n", mem_size, + mem_size >> 10); + } +} + struct cli_callback_descr list_memory_show_modules[] = { { .name = "e820", .exec = show_memory_e820, }, + { + .name = "e801", + .exec = show_memory_e801, + }, + { + .name = "88", + .exec = show_memory_88, + }, { .name = NULL, .exec = NULL, @@ -63,7 +97,7 @@ struct cli_callback_descr list_memory_show_modules[] = { struct cli_module_descr memory_show_modules = { .modules = list_memory_show_modules, - .default_callback = NULL, + .default_callback = show_dmi_memory_modules, }; struct cli_mode_descr memory_mode = { -- cgit v1.2.1 From 3e5b7b7a03bc8264c2b68b2a3a174ec548b65f37 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Sun, 3 May 2009 10:30:20 +0200 Subject: hdt: fixing BACKSPACE behavior Impact: Fixing CLI behavior Prior to that commit, the BACKSPACE didn't worked properly. In some cases, the cursor was misplaced and was confusing user. --- com32/hdt/hdt-cli.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 5fe1436a..7e8954c8 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -971,14 +971,10 @@ void start_cli_mode(struct s_hardware *hardware) /* Print the resulting buffer */ printf("%s", hdt_cli.input + hdt_cli.cursor_pos - 1); - /* Realing to the place we were */ - move_cursor_left(strlen(hdt_cli.input + hdt_cli.cursor_pos - 1)); - move_cursor_right(1); + /* Realing to a char before the place we were */ + hdt_cli.cursor_pos--; + move_cursor_to_column(strlen(hdt_cli.prompt)+hdt_cli.cursor_pos+1); - /* Don't decrement the position unless - * if we are at then end of the line*/ - if (hdt_cli.cursor_pos > (int)strlen(hdt_cli.input)) - hdt_cli.cursor_pos--; break; case KEY_F1: -- cgit v1.2.1 From 16da4bf8a346e3fc7abf75d0ad903a088301dccc Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Sun, 3 May 2009 19:49:20 +0200 Subject: hdt: Input cursor is now blinking Impact: Improve user experience This commit let the cursor blinking while waiting for a keyboard input. The blinking mode seems to fails under qemu but works fine on real hardware. --- com32/hdt/hdt-cli.c | 9 ++++++++- com32/hdt/lib-ansi.c | 7 +++++++ com32/hdt/lib-ansi.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 7e8954c8..c8d9ce8b 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -776,9 +776,16 @@ void start_cli_mode(struct s_hardware *hardware) while (hdt_cli.mode != EXIT_MODE) { - //fgets(cli_line, sizeof cli_line, stdin); + /* Let's put the cursor blinking until we get an input */ + set_cursor_blink(true); + + /* We wait endlessly for a keyboard input*/ current_key = get_key(stdin, 0); + /* We have to cancel the blinking mode to prevent + * input text to blink */ + set_cursor_blink(false); + /* Reset autocomplete buffer unless TAB is pressed */ if (current_key != KEY_TAB) autocomplete_destroy_list(); diff --git a/com32/hdt/lib-ansi.c b/com32/hdt/lib-ansi.c index 12e5ecc7..411dba80 100644 --- a/com32/hdt/lib-ansi.c +++ b/com32/hdt/lib-ansi.c @@ -61,6 +61,13 @@ void move_cursor_right(int count) { fputs(buffer, stdout); } +void set_cursor_blink(bool status) { + if (status == true) + fputs("\033[05m",stdout); + else + fputs("\033[0m",stdout); +} + void clear_line() { fputs("\033[2K", stdout); } diff --git a/com32/hdt/lib-ansi.h b/com32/hdt/lib-ansi.h index 2a17766f..0b0d0d18 100644 --- a/com32/hdt/lib-ansi.h +++ b/com32/hdt/lib-ansi.h @@ -40,4 +40,5 @@ void disable_utf8(); void set_g1_special_char(); void set_us_g0_charset(); void clear_entire_screen(); +void set_cursor_blink(bool status); #endif -- cgit v1.2.1 From b7817ae596d1f9b79d027210f0e7958da3516cb6 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Sun, 3 May 2009 19:53:49 +0200 Subject: hdt: fixing cursor disapearing Impact: Improve user experience After some commands, the cursor was disapearing. That could confuse users. This commit resolve this weird cases. --- com32/hdt/hdt-cli.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index c8d9ce8b..030757da 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -769,13 +769,13 @@ void start_cli_mode(struct s_hardware *hardware) printf("Entering CLI mode\n"); - /* Display the cursor */ - display_cursor(true); - reset_prompt(); while (hdt_cli.mode != EXIT_MODE) { + /* Display the cursor */ + display_cursor(true); + /* Let's put the cursor blinking until we get an input */ set_cursor_blink(true); -- cgit v1.2.1 From a88671c995e6f25f46c921e1035a3a68a3a72660 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Sun, 3 May 2009 21:45:26 +0200 Subject: hdt: using reset_more_printf in memory mode Impact: prevent weird display more_printf needs reset_more_printf() --- com32/hdt/hdt-cli-memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/com32/hdt/hdt-cli-memory.c b/com32/hdt/hdt-cli-memory.c index e0516aef..c23dbbdd 100644 --- a/com32/hdt/hdt-cli-memory.c +++ b/com32/hdt/hdt-cli-memory.c @@ -42,6 +42,7 @@ static void show_memory_e820(int argc __unused, char **argv __unused, detect_memory_e820(map, E820MAX, &count); printf("BIOS-provided physical RAM e820 map:\n"); + reset_more_printf(); for (int i = 0; i < count; i++) { get_type(map[i].type, type, 14); more_printf("%016llx - %016llx %016llx (%s)\n", @@ -55,6 +56,7 @@ static void show_memory_e801(int argc __unused, char **argv __unused, { int mem_low, mem_high = 0; + reset_more_printf(); if (detect_memory_e801(&mem_low, &mem_high)) { more_printf("e801 bogus!\n"); } else { @@ -68,6 +70,7 @@ static void show_memory_88(int argc __unused, char **argv __unused, { int mem_size = 0; + reset_more_printf(); if (detect_memory_88(&mem_size)) { more_printf("8800h bogus!\n"); } else { -- cgit v1.2.1 From 3e761dad4cfec0f2dcafb859fb13b8692daf8882 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Mon, 4 May 2009 20:58:29 +0200 Subject: hdt: improve help message Impact: Improve display usage Prior to that commit, the help message was using too much lines. This commit make it more compact --- com32/hdt/hdt-cli-hdt.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index 8069b190..ab2a1d29 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -54,9 +54,10 @@ static void main_show_modes(int argc __unused, char** argv __unused, printf("Available modes:\n"); while (list_modes[i]) { - printf("\t%s\n", list_modes[i]->name); + printf("%s ", list_modes[i]->name); i++; } + printf("\n"); } /** @@ -132,25 +133,27 @@ static void show_cli_help(int argc __unused, char** argv __unused, /* List secondly the show modules of the mode */ if (current_mode->show_modules && current_mode->show_modules->modules) { - printf("show commands:\n"); + printf("\nshow commands:\n"); j = 0; while (current_mode->show_modules->modules[j].name) { - printf("\t%s\n", + printf("%s ", current_mode->show_modules->modules[j].name); j++; } + printf("\n"); } /* List thirdly the set modules of the mode */ if (current_mode->set_modules && current_mode->set_modules->modules) { - printf("set commands:\n"); + printf("\nset commands:\n"); j = 0; while (current_mode->set_modules->modules[j].name) { - printf("\t%s\n", + printf("%s ", current_mode->set_modules->modules[j].name); j++; } + printf("\n"); } /* List finally the default modules of the hdt mode */ @@ -177,6 +180,7 @@ static void show_cli_help(int argc __unused, char** argv __unused, printf("\n"); } + printf("\n"); main_show_modes(argc, argv, hardware); } -- cgit v1.2.1 From 5de3f4b4fd47d098a4393a35f302c98116fd78dd Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 5 May 2009 19:59:12 +0200 Subject: hdt: adding memory> show bank xx Impact: Improving command coherency memory> show bank is now implemented like dmi> show bank --- com32/hdt/hdt-cli-dmi.c | 4 ++-- com32/hdt/hdt-cli-memory.c | 4 ++++ com32/hdt/hdt-cli.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 08343b4d..1e5af06d 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -303,7 +303,7 @@ static void show_dmi_cpu(int argc __unused, char** argv __unused, } } -static void show_dmi_memory_bank(int argc, char** argv, +void show_dmi_memory_bank(int argc, char** argv, struct s_hardware *hardware) { int bank = -1; @@ -374,7 +374,7 @@ void main_show_dmi(int argc __unused, char **argv __unused, void show_dmi_memory_modules(int argc __unused, char** argv __unused, struct s_hardware *hardware) { - int clear = 1, show_free_banks = 1; + int show_free_banks = 1; /* Needed, if called by the memory mode */ detect_dmi(hardware); diff --git a/com32/hdt/hdt-cli-memory.c b/com32/hdt/hdt-cli-memory.c index c23dbbdd..89f871e1 100644 --- a/com32/hdt/hdt-cli-memory.c +++ b/com32/hdt/hdt-cli-memory.c @@ -92,6 +92,10 @@ struct cli_callback_descr list_memory_show_modules[] = { .name = "88", .exec = show_memory_88, }, + { + .name = CLI_DMI_MEMORY_BANK, + .exec = show_dmi_memory_bank, + }, { .name = NULL, .exec = NULL, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index df324fd2..a9415ac0 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -170,6 +170,7 @@ void main_show(char *item, struct s_hardware *hardware); #define CLI_DMI_LIST CLI_SHOW_LIST void main_show_dmi(int argc, char **argv, struct s_hardware *hardware); void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware); +void show_dmi_memory_bank(int argc, char** argv, struct s_hardware *hardware); // PCI STUFF #define CLI_PCI_DEVICE "device" -- cgit v1.2.1 From a872cb0ac3389c9b15798fafd9722caf83c7dc49 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 5 May 2009 20:02:16 +0200 Subject: hdt: adding "hdt> show memory" Impact: more command coherency hdt> show memory now reports the same as memory> show --- com32/hdt/hdt-cli-hdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index ab2a1d29..5bebf584 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -316,7 +316,10 @@ struct cli_callback_descr list_hdt_show_modules[] = { .name = CLI_VPD, .exec = main_show_vpd, }, - + { + .name = CLI_MEMORY, + .exec = show_dmi_memory_modules, + }, { .name = "modes", .exec = main_show_modes, -- cgit v1.2.1 From ea541f040ebfce40e6719b8fbde53010e97fd984 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 5 May 2009 21:03:11 +0200 Subject: hdt: Adding e820, e801, e88 memory information Impact: More memory detection This commit introduce 3 new memory information in the menu mode - e820 - e801 - e88 --- com32/hdt/hdt-menu-dmi.c | 141 ---------------------- com32/hdt/hdt-menu-memory.c | 277 ++++++++++++++++++++++++++++++++++++++++++++ com32/hdt/hdt-menu.c | 3 +- 3 files changed, 278 insertions(+), 143 deletions(-) create mode 100644 com32/hdt/hdt-menu-memory.c diff --git a/com32/hdt/hdt-menu-dmi.c b/com32/hdt/hdt-menu-dmi.c index a3a3a8e6..77ee90e5 100644 --- a/com32/hdt/hdt-menu-dmi.c +++ b/com32/hdt/hdt-menu-dmi.c @@ -245,147 +245,6 @@ void compute_motherboard(struct s_my_menu *menu, s_dmi * dmi) printf("MENU: Motherboard menu done (%d items)\n", menu->items_count); } -/* Compute the Memory submenu */ -static void compute_memory_module(struct s_my_menu *menu, s_dmi * dmi, - int slot_number) -{ - int i = slot_number; - char buffer[MENULEN + 1]; - char statbuffer[STATLEN + 1]; - - sprintf(buffer, " Bank <%d> ", i); - menu->items_count = 0; - menu->menu = add_menu(buffer, -1); - - snprintf(buffer, sizeof buffer, "Form Factor : %s", - dmi->memory[i].form_factor); - snprintf(statbuffer, sizeof statbuffer, "Form Factor: %s", - dmi->memory[i].form_factor); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Type : %s", - dmi->memory[i].type); - snprintf(statbuffer, sizeof statbuffer, "Type: %s", - dmi->memory[i].type); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Type Details : %s", - dmi->memory[i].type_detail); - snprintf(statbuffer, sizeof statbuffer, "Type Details: %s", - dmi->memory[i].type_detail); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Speed : %s", - dmi->memory[i].speed); - snprintf(statbuffer, sizeof statbuffer, "Speed (Mhz): %s", - dmi->memory[i].speed); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Size : %s", - dmi->memory[i].size); - snprintf(statbuffer, sizeof statbuffer, "Size: %s", - dmi->memory[i].size); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Device Set : %s", - dmi->memory[i].device_set); - snprintf(statbuffer, sizeof statbuffer, "Device Set: %s", - dmi->memory[i].device_set); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Device Loc. : %s", - dmi->memory[i].device_locator); - snprintf(statbuffer, sizeof statbuffer, "Device Location: %s", - dmi->memory[i].device_locator); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Bank Locator : %s", - dmi->memory[i].bank_locator); - snprintf(statbuffer, sizeof statbuffer, "Bank Locator: %s", - dmi->memory[i].bank_locator); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Total Width : %s", - dmi->memory[i].total_width); - snprintf(statbuffer, sizeof statbuffer, "Total bit Width: %s", - dmi->memory[i].total_width); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Data Width : %s", - dmi->memory[i].data_width); - snprintf(statbuffer, sizeof statbuffer, "Data bit Width: %s", - dmi->memory[i].data_width); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Error : %s", - dmi->memory[i].error); - snprintf(statbuffer, sizeof statbuffer, "Error: %s", - dmi->memory[i].error); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Vendor : %s", - dmi->memory[i].manufacturer); - snprintf(statbuffer, sizeof statbuffer, "Vendor: %s", - dmi->memory[i].manufacturer); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Serial : %s", - dmi->memory[i].serial); - snprintf(statbuffer, sizeof statbuffer, "Serial: %s", - dmi->memory[i].serial); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Asset Tag : %s", - dmi->memory[i].asset_tag); - snprintf(statbuffer, sizeof statbuffer, "Asset Tag: %s", - dmi->memory[i].asset_tag); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - - snprintf(buffer, sizeof buffer, "Part Number : %s", - dmi->memory[i].part_number); - snprintf(buffer, sizeof statbuffer, "Part Number: %s", - dmi->memory[i].part_number); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu->items_count++; - -} - -/* Compute the Memory menu */ -void compute_memory(struct s_hdt_menu *menu, s_dmi * dmi, struct s_hardware *hardware) -{ - char buffer[MENULEN + 1]; - for (int i = 0; i < dmi->memory_count; i++) { - compute_memory_module(&(menu->memory_sub_menu[i]), dmi, i); - } - - menu->memory_menu.menu = add_menu(" Memory Banks ", -1); - menu->memory_menu.items_count = 0; - - for (int i = 0; i < dmi->memory_count; i++) { - snprintf(buffer, sizeof buffer, " Bank <%d> ", i); - add_item(buffer, "Memory Bank", OPT_SUBMENU, NULL, - menu->memory_sub_menu[i].menu); - menu->memory_menu.items_count++; - } - printf("MENU: Memory menu done (%d items)\n", - menu->memory_menu.items_count); - add_item("Run Test", "Run Test", OPT_RUN, hardware->memtest_label, 0); -} - /* Compute Main IPMI menu */ void compute_ipmi(struct s_my_menu *menu, s_dmi * dmi) { diff --git a/com32/hdt/hdt-menu-memory.c b/com32/hdt/hdt-menu-memory.c new file mode 100644 index 00000000..ddc26fef --- /dev/null +++ b/com32/hdt/hdt-menu-memory.c @@ -0,0 +1,277 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + */ + +#include +#include "hdt-menu.h" +#define E820MAX 128 + +/* Compute the e820 submenu */ +static void compute_e820(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " e820 Physical RAM map "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + struct e820entry map[E820MAX]; + int count = 0; + char type[14]; + + detect_memory_e820(map, E820MAX, &count); + for (int j = 0; j < count; j++) { + get_type(map[j].type, type, 14); + snprintf(buffer, sizeof buffer, + "%016llx - %016llx (%s)", + map[j].addr, map[j].size, + remove_spaces(type)); + snprintf(statbuffer, sizeof statbuffer, + "%016llx - %016llx (%s)", + map[j].addr, map[j].size, + remove_spaces(type)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } +} + +/* Compute the e801 submenu */ +static void compute_e801(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " e801 information "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + int mem_low, mem_high = 0; + if (detect_memory_e801(&mem_low, &mem_high)) { + snprintf(buffer, sizeof buffer, "%s", "e801 output is bogus"); + snprintf(statbuffer, sizeof statbuffer, "%s", "e801 output is bogus"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } else { + snprintf(buffer, sizeof buffer, "%d Kb (%d MiB) - %d Kb (%d MiB)", + mem_low, mem_low >> 10, mem_high << 6, mem_high >> 4); + snprintf(statbuffer, sizeof statbuffer, "%d Kb (%d MiB) - %d Kb (%d MiB)", + mem_low, mem_low >> 10, mem_high << 6, mem_high >> 4); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } + menu->items_count++; +} + +/* Compute the e88 submenu */ +static void compute_e88(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " e88 information "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + int mem_size = 0; + if (detect_memory_88(&mem_size)) { + snprintf(buffer, sizeof buffer, "%s", "e88 output is bogus"); + snprintf(statbuffer, sizeof statbuffer, "%s", "e88 output is bogus"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } else { + snprintf(buffer, sizeof buffer, "%d Kb (%d MiB)", + mem_size, mem_size >> 10); + snprintf(statbuffer, sizeof statbuffer, "%d Kb (%d MiB)", + mem_size, mem_size >> 10); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } + menu->items_count++; +} +/* Compute the Memory submenu */ +static void compute_memory_module(struct s_my_menu *menu, s_dmi * dmi, + int slot_number) +{ + int i = slot_number; + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " Bank <%d> ", i); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + snprintf(buffer, sizeof buffer, "Form Factor : %s", + dmi->memory[i].form_factor); + snprintf(statbuffer, sizeof statbuffer, "Form Factor: %s", + dmi->memory[i].form_factor); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Type : %s", + dmi->memory[i].type); + snprintf(statbuffer, sizeof statbuffer, "Type: %s", + dmi->memory[i].type); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Type Details : %s", + dmi->memory[i].type_detail); + snprintf(statbuffer, sizeof statbuffer, "Type Details: %s", + dmi->memory[i].type_detail); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Speed : %s", + dmi->memory[i].speed); + snprintf(statbuffer, sizeof statbuffer, "Speed (Mhz): %s", + dmi->memory[i].speed); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Size : %s", + dmi->memory[i].size); + snprintf(statbuffer, sizeof statbuffer, "Size: %s", + dmi->memory[i].size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Device Set : %s", + dmi->memory[i].device_set); + snprintf(statbuffer, sizeof statbuffer, "Device Set: %s", + dmi->memory[i].device_set); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Device Loc. : %s", + dmi->memory[i].device_locator); + snprintf(statbuffer, sizeof statbuffer, "Device Location: %s", + dmi->memory[i].device_locator); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Bank Locator : %s", + dmi->memory[i].bank_locator); + snprintf(statbuffer, sizeof statbuffer, "Bank Locator: %s", + dmi->memory[i].bank_locator); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Total Width : %s", + dmi->memory[i].total_width); + snprintf(statbuffer, sizeof statbuffer, "Total bit Width: %s", + dmi->memory[i].total_width); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Data Width : %s", + dmi->memory[i].data_width); + snprintf(statbuffer, sizeof statbuffer, "Data bit Width: %s", + dmi->memory[i].data_width); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Error : %s", + dmi->memory[i].error); + snprintf(statbuffer, sizeof statbuffer, "Error: %s", + dmi->memory[i].error); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Vendor : %s", + dmi->memory[i].manufacturer); + snprintf(statbuffer, sizeof statbuffer, "Vendor: %s", + dmi->memory[i].manufacturer); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Serial : %s", + dmi->memory[i].serial); + snprintf(statbuffer, sizeof statbuffer, "Serial: %s", + dmi->memory[i].serial); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Asset Tag : %s", + dmi->memory[i].asset_tag); + snprintf(statbuffer, sizeof statbuffer, "Asset Tag: %s", + dmi->memory[i].asset_tag); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Part Number : %s", + dmi->memory[i].part_number); + snprintf(buffer, sizeof statbuffer, "Part Number: %s", + dmi->memory[i].part_number); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + +} + +/* Compute the Memory menu */ +void compute_memory(struct s_hdt_menu *menu, s_dmi * dmi, struct s_hardware *hardware) +{ + char buffer[MENULEN + 1]; + int i=0; + for (i = 0; i < dmi->memory_count; i++) { + compute_memory_module(&(menu->memory_sub_menu[i]), dmi, i); + } + + compute_e820(&(menu->memory_sub_menu[++i])); + compute_e801(&(menu->memory_sub_menu[++i])); + compute_e88(&(menu->memory_sub_menu[++i])); + + menu->memory_menu.menu = add_menu(" Memory Banks ", -1); + menu->memory_menu.items_count = 0; + + for (i = 0; i < dmi->memory_count; i++) { + snprintf(buffer, sizeof buffer, " Bank <%d> ", i); + add_item(buffer, "Memory Bank", OPT_SUBMENU, NULL, + menu->memory_sub_menu[i].menu); + menu->memory_menu.items_count++; + } + + add_item("", "", OPT_SEP, "", 0); + + snprintf(buffer, sizeof buffer, " e820 "); + add_item(buffer, "e820 mapping", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + snprintf(buffer, sizeof buffer, " e801 "); + add_item(buffer, "e801 information", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + snprintf(buffer, sizeof buffer, " e88 "); + add_item(buffer, "e88 information", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + add_item("", "", OPT_SEP, "", 0); + printf("MENU: Memory menu done (%d items)\n", + menu->memory_menu.items_count); + add_item("Run Test", "Run Test", OPT_RUN, hardware->memtest_label, 0); +} diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index ff615017..c37fd41b 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -195,8 +195,7 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) } if (hdt_menu->memory_menu.items_count > 0) { - snprintf(menu_item, sizeof(menu_item), "emory (%2d)\n", - hdt_menu->memory_menu.items_count); + snprintf(menu_item, sizeof(menu_item), "emory\n"); add_item(menu_item, "Memory Menu", OPT_SUBMENU, NULL, hdt_menu->memory_menu.menu); hdt_menu->main_menu.items_count++; -- cgit v1.2.1 From b691a5d99c460e6aefe60d9557bde2dc2c98fe34 Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 5 May 2009 21:09:44 +0200 Subject: hdt: 0.3.3 Impact: new release New release 0.3.3 --- com32/hdt/hdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index e29c7bfe..94ce1f48 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -32,7 +32,7 @@ #define PRODUCT_NAME "Hardware Detection Tool" #define AUTHOR "Erwan Velu" #define CONTACT "hdt@zytor.com" -#define VERSION "0.3.2" +#define VERSION "0.3.3" #define NB_CONTRIBUTORS 2 #define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"} -- cgit v1.2.1 From d9822499f847c67842e4de71eebc33c833fe9a5e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 7 May 2009 13:14:13 -0700 Subject: gpllib: Specify size of the edd structure in the buffer (disklib) The first word of the result buffer should contain the size of the expected result, as specified in the ATA/ATAPI Command set: The caller shall set this value to the maximum Result Buffer length, in bytes. (Impact: fixes #1) Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/geom.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 02ac681b..9f54967f 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -121,10 +121,22 @@ static int detect_extensions(struct driveinfo* drive_info) static int get_drive_parameters_with_extensions(struct driveinfo* drive_info) { com32sys_t inreg, outreg; - struct device_parameter *dp = __com32.cs_bounce; + struct edd_device_parameters *dp = __com32.cs_bounce; memset(&inreg, 0, sizeof inreg); + /* + * The caller shall set this value to the maximum Result Buffer + * length, in bytes. If the length of this buffer is less than 30 + * bytes, this function shall not return the pointer to Drive Parameter + * Table (DPT) extension. If the buffer length is 30 or greater on + * entry, it shall be set to 30 on exit. If the buffer length is + * between 26 and 29, it shall be set to 26 on exit. + * If the buffer length is less than 26 on entry an error shall be + * returned. + */ + dp->len = sizeof(struct edd_device_parameters); + inreg.esi.w[0] = OFFS(dp); inreg.ds = SEG(dp); inreg.edx.b[0] = drive_info->disk; -- cgit v1.2.1 From d4fa24a948a6fcdfe9dfe6e12e4df46d63ced3f7 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 7 May 2009 20:26:25 -0700 Subject: hdt: Fix partition display (menu) Pass the correct disk structure when extracting partitioning information. Misc.: remove extra paren in output. (Impact: fixes #2) Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 730d20b7..7e60b06e 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -115,9 +115,9 @@ static void compute_partition_information(struct driveinfo *drive_info, get_label(ptab->ostype, &parttype); - snprintf(buffer, sizeof buffer, "Size : %s)", + snprintf(buffer, sizeof buffer, "Size : %s", remove_spaces(size)); - snprintf(statbuffer, sizeof statbuffer, "Size : %s)", + snprintf(statbuffer, sizeof statbuffer, "Size : %s", remove_spaces(size)); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); @@ -225,8 +225,8 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, dn=disk_number; int error; - parse_partition_table(d, &show_partition_information, &error); - if (parse_partition_table(d, &compute_partition_information, &error)) { + parse_partition_table(&d[disk_number], &show_partition_information, &error); + if (parse_partition_table(&d[disk_number], &compute_partition_information, &error)) { if (error) { char *error_buffer; get_error(error, &error_buffer); -- cgit v1.2.1 From 8c173101c0bd7a97ce76bf41c3e9df5c06cc3231 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 7 May 2009 13:14:13 -0700 Subject: gpllib: Specify size of the edd structure in the buffer (disklib) The first word of the result buffer should contain the size of the expected result, as specified in the ATA/ATAPI Command set: The caller shall set this value to the maximum Result Buffer length, in bytes. (Impact: fixes #1) Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/geom.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 02ac681b..9f54967f 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -121,10 +121,22 @@ static int detect_extensions(struct driveinfo* drive_info) static int get_drive_parameters_with_extensions(struct driveinfo* drive_info) { com32sys_t inreg, outreg; - struct device_parameter *dp = __com32.cs_bounce; + struct edd_device_parameters *dp = __com32.cs_bounce; memset(&inreg, 0, sizeof inreg); + /* + * The caller shall set this value to the maximum Result Buffer + * length, in bytes. If the length of this buffer is less than 30 + * bytes, this function shall not return the pointer to Drive Parameter + * Table (DPT) extension. If the buffer length is 30 or greater on + * entry, it shall be set to 30 on exit. If the buffer length is + * between 26 and 29, it shall be set to 26 on exit. + * If the buffer length is less than 26 on entry an error shall be + * returned. + */ + dp->len = sizeof(struct edd_device_parameters); + inreg.esi.w[0] = OFFS(dp); inreg.ds = SEG(dp); inreg.edx.b[0] = drive_info->disk; -- cgit v1.2.1 From 0976f8629c48dcc420b6a86511dc3571df89c18e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 7 May 2009 20:26:25 -0700 Subject: hdt: Fix partition display (menu) Pass the correct disk structure when extracting partitioning information. Misc.: remove extra paren in output. (Impact: fixes #2) Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-menu-disk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 730d20b7..7e60b06e 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -115,9 +115,9 @@ static void compute_partition_information(struct driveinfo *drive_info, get_label(ptab->ostype, &parttype); - snprintf(buffer, sizeof buffer, "Size : %s)", + snprintf(buffer, sizeof buffer, "Size : %s", remove_spaces(size)); - snprintf(statbuffer, sizeof statbuffer, "Size : %s)", + snprintf(statbuffer, sizeof statbuffer, "Size : %s", remove_spaces(size)); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); @@ -225,8 +225,8 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, dn=disk_number; int error; - parse_partition_table(d, &show_partition_information, &error); - if (parse_partition_table(d, &compute_partition_information, &error)) { + parse_partition_table(&d[disk_number], &show_partition_information, &error); + if (parse_partition_table(&d[disk_number], &compute_partition_information, &error)) { if (error) { char *error_buffer; get_error(error, &error_buffer); -- cgit v1.2.1 From 3057d76cb13d5ca5e5270f42c012e8abfe3542ee Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Fri, 8 May 2009 19:11:10 -0700 Subject: hdt: Remove vesa hack (cli) The vesa detection hack is not needed anymore as the disklib has been fixed. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-common.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 33645ffb..987c5ae7 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -257,10 +257,6 @@ void detect_disks(struct s_hardware *hardware) if (hardware->disk_detection) return; - /* FIXME: this is needed to have the int13 working. - * Until we figured why, we need this workaround*/ - detect_vesa(hardware); - hardware->disk_detection = true; for (int drive = 0x80; drive < 0xff; drive++) { i++; -- cgit v1.2.1 From 98d010375584121be6e9b09bdae92258911585a7 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Fri, 8 May 2009 19:12:21 -0700 Subject: hdt: Silence harmless errors when detecting disks Detecting disk geometry can fail either because the extension query failed (invalid disk number?) or because the legacy geometry call failed (int 13 not supported?). The latter happens for instance when querying geometry for CDROMs. In either case, the error message is not meaningful. Don't print it (and don't confuse the user). (Impact: fixes #5) Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 987c5ae7..0f98ab9e 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -263,8 +263,11 @@ void detect_disks(struct s_hardware *hardware) hardware->disk_info[i].disk = drive; err = get_drive_parameters(&hardware->disk_info[i]); - /* Do not print output when drive does not exists */ - if (err == -1) + /* + * Do not print output when drive does not exist or + * doesn't support int13 (cdrom, ...) + */ + if (err == -1 || !hardware->disk_info[i].cbios) continue; if (err) { -- cgit v1.2.1 From dd21aee0f0815aa717930ca9033949618c949dab Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Fri, 8 May 2009 21:56:36 -0700 Subject: gpllib: Add Memory Module Information (Type 6, Obsolete) (DMI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SMBIOS specification defines: 3.3.7 Memory Module Information (Type 6, Obsolete) From the spec (v2.6.1): One Memory Module Information structure is included for each memory-module socket in the system. The structure describes the speed, type, size, and error status of each system memory module. The supported attributes of each module are described by the “owning” Memory Controller Information structure. Note: This structure, and its companion Memory Controller Information (Type 5, Obsolete), are obsolete starting with version 2.1 of this specification; the Physical Memory Array (Type 16) and Memory Device (Type 17) structures should be used instead. BIOS providers might choose to implement both memory description types to allow existing DMI browsers to properly display the system’s memory attributes. This patch adds decoding support for this type. Adapted from the dmidecode project. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 2 + com32/gplinclude/dmi/dmi_memory.h | 16 +++++++ com32/gpllib/dmi/dmi.c | 14 ++++++ com32/gpllib/dmi/dmi_memory.c | 91 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index 89782a97..d065534f 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -64,8 +64,10 @@ typedef struct { s_chassis chassis; s_processor processor; s_battery battery; + s_memory_module memory_module[MAX_DMI_MEMORY_ITEMS]; s_memory memory[MAX_DMI_MEMORY_ITEMS]; s_ipmi ipmi; + int memory_module_count; int memory_count; dmi_table dmitable; } s_dmi; diff --git a/com32/gplinclude/dmi/dmi_memory.h b/com32/gplinclude/dmi/dmi_memory.h index 2b744b5c..6939cd00 100644 --- a/com32/gplinclude/dmi/dmi_memory.h +++ b/com32/gplinclude/dmi/dmi_memory.h @@ -49,6 +49,17 @@ char part_number[MEMORY_PART_NUMBER_SIZE]; bool filled; } s_memory; +typedef struct { +char socket_designation[8]; +char bank_connections[8]; +char speed[8]; +char type[16]; +char installed_size[8]; +char enabled_size[8]; +char error_status[8]; +bool filled; +} s_memory_module; + void dmi_memory_array_error_handle(uint16_t code,char *array); void dmi_memory_device_width(uint16_t code, char *width); void dmi_memory_device_size(uint16_t code, char *size); @@ -58,4 +69,9 @@ const char *dmi_memory_device_type(uint8_t code); void dmi_memory_device_type_detail(uint16_t code,char *type_detail); void dmi_memory_device_speed(uint16_t code, char *speed); +void dmi_memory_module_connections(uint8_t, char*); +void dmi_memory_module_speed(uint8_t, char*); +void dmi_memory_module_types(uint16_t, const char*, char*); +void dmi_memory_module_size(uint8_t, char*); +void dmi_memory_module_error(uint8_t, const char*, char*); #endif diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 23caa334..f0f8b6c3 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -492,6 +492,20 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) strcpy(dmi->processor.asset_tag,dmi_string(h, data[0x21])); strcpy(dmi->processor.part_number,dmi_string(h, data[0x22])); break; + case 6: /* 3.3.7 Memory Module Information */ + if(h->length<0x0C) break; + dmi->memory_module_count++; + s_memory_module *module = &dmi->memory_module[dmi->memory_module_count-1]; + dmi->memory_module[dmi->memory_module_count-1].filled=true; + strncpy(module->socket_designation, dmi_string(h, data[0x04]), + sizeof(module->socket_designation)); + dmi_memory_module_connections(data[0x05], module->bank_connections); + dmi_memory_module_speed(data[0x06], module->speed); + dmi_memory_module_types(WORD(data+0x07), " ", module->type); + dmi_memory_module_size(data[0x09], module->installed_size); + dmi_memory_module_size(data[0x0A], module->enabled_size); + dmi_memory_module_error(data[0x0B], "\t\t", module->error_status); + break; case 17: /* 3.3.18 Memory Device */ if (h->length < 0x15) break; dmi->memory_count++; diff --git a/com32/gpllib/dmi/dmi_memory.c b/com32/gpllib/dmi/dmi_memory.c index dc354df1..87edb6e9 100644 --- a/com32/gpllib/dmi/dmi_memory.c +++ b/com32/gpllib/dmi/dmi_memory.c @@ -170,3 +170,94 @@ void dmi_memory_device_speed(uint16_t code, char *speed) sprintf(speed,"%u MHz", code); } +/* + * 3.3.7 Memory Module Information (Type 6) + */ + +void dmi_memory_module_types(uint16_t code, const char *sep, char *type) +{ + /* 3.3.7.1 */ + static const char *types[]={ + "Other", /* 0 */ + "Unknown", + "Standard", + "FPM", + "EDO", + "Parity", + "ECC", + "SIMM", + "DIMM", + "Burst EDO", + "SDRAM" /* 10 */ + }; + + if((code&0x07FF)==0) + sprintf(type, "%s", "None"); + else + { + int i; + + for(i=0; i<=10; i++) + if(code&(1<>4); + if((code&0x0F)!=0x0F) + sprintf(connection, "%u", code&0x0F); + } +} + +void dmi_memory_module_speed(uint8_t code, char* speed) +{ + if(code==0) + sprintf(speed, "%s", "Unknown"); + else + sprintf(speed, "%u ns", code); +} + +void dmi_memory_module_size(uint8_t code, char* size) +{ + /* 3.3.7.2 */ + switch(code&0x7F) + { + case 0x7D: + sprintf(size, "%s", "Not Determinable"); + break; + case 0x7E: + sprintf(size, "%s", "Disabled"); + break; + case 0x7F: + sprintf(size, "%s", "Not Installed"); + return; + default: + sprintf(size, "%u MB", 1<<(code&0x7F)); + } + + if(code&0x80) + printf(size, "%s", "(Double-bank Connection)"); + else + printf(size, "%s", "(Single-bank Connection)"); +} + +void dmi_memory_module_error(uint8_t code, const char *prefix, char *error) +{ + if(code&(1<<2)) + sprintf(error, "%s", "See Event Log\n"); + else + { if((code&0x03)==0) + printf(error, "%s", "OK\n"); + if(code&(1<<0)) + printf(error, "%sUncorrectable Errors\n", prefix); + if(code&(1<<1)) + printf(error, "%sCorrectable Errors\n", prefix); + } +} -- cgit v1.2.1 From 4899adbd7ad688fb6a6b8dc2f8aad54719168e09 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Fri, 8 May 2009 22:03:22 -0700 Subject: hdt: Add SMBIOS Memory Module Support (CLI) Add `show module ' in the DMI module to display SMBIOS 3.3.7 Memory Module Information (Type 6, Obsolete). Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 1e5af06d..9f211d87 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -55,6 +55,12 @@ static void show_dmi_modules(int argc __unused, char** argv __unused, break; } } + for (int i = 0; i < hardware->dmi.memory_module_count; i++) { + if (hardware->dmi.memory_module[i].filled == true) { + printf("\tmodule \n"); + break; + } + } if (hardware->dmi.processor.filled == true) printf("\t%s\n", CLI_DMI_PROCESSOR); if (hardware->dmi.system.filled == true) @@ -354,6 +360,47 @@ void show_dmi_memory_bank(int argc, char** argv, hardware->dmi.memory[bank].part_number); } +void show_dmi_memory_module(int argc, char** argv, + struct s_hardware *hardware) +{ + int module = -1; + + /* Sanitize arguments */ + if (argc > 0) + module = strtol(argv[0], (char **)NULL, 10); + + if (errno == ERANGE || module < 0) { + printf("This module number is incorrect\n"); + return; + } + + if ((module >= hardware->dmi.memory_module_count) || (module < 0)) { + printf("Module number %d doesn't exist\n", module); + return; + } + + if (hardware->dmi.memory_module[module].filled == false) { + printf("Module %d doesn't contain any information\n", module); + return; + } + + printf("Memory Module %d\n", module); + printf(" Socket Designation : %s\n", + hardware->dmi.memory_module[module].socket_designation); + printf(" Bank Connections : %s\n", + hardware->dmi.memory_module[module].bank_connections); + printf(" Current Speed : %s\n", + hardware->dmi.memory_module[module].speed); + printf(" Type : %s\n", + hardware->dmi.memory_module[module].type); + printf(" Installed Size : %s\n", + hardware->dmi.memory_module[module].installed_size); + printf(" Enabled Size : %s\n", + hardware->dmi.memory_module[module].enabled_size); + printf(" Error Status : %s\n", + hardware->dmi.memory_module[module].error_status); +} + void main_show_dmi(int argc __unused, char **argv __unused, struct s_hardware *hardware) { @@ -454,6 +501,10 @@ struct cli_callback_descr list_dmi_show_modules[] = { .name = CLI_DMI_MEMORY_BANK, .exec = show_dmi_memory_bank, }, + { + .name = "module", + .exec = show_dmi_memory_module, + }, { .name = CLI_DMI_PROCESSOR, .exec = show_dmi_cpu, -- cgit v1.2.1 From 76a40a4c43bc76078a949650fc912be49007e78f Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Thu, 14 May 2009 22:21:59 +0200 Subject: hdt: Fixing some issues with cdrom drives Impact: Prevent hard freeze on some hardware Some Optical drivers doesn't like AH=48 when AH=08 failed. Let's do that way even if it looks like a little bit weird. --- com32/gpllib/disk/geom.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c index 9f54967f..2305ed16 100644 --- a/com32/gpllib/disk/geom.c +++ b/com32/gpllib/disk/geom.c @@ -256,11 +256,17 @@ static int get_drive_parameters_without_extensions(struct driveinfo* drive_info) **/ int get_drive_parameters(struct driveinfo *drive_info) { + int return_code; + if (detect_extensions(drive_info)) return -1; - if (drive_info->ebios) + return_code = get_drive_parameters_without_extensions(drive_info); + + /* If geometry isn't valid, no need to try to get more info about the drive*/ + /* Looks like in can confuse some optical drives */ + if (drive_info->ebios && drive_info->cbios) get_drive_parameters_with_extensions(drive_info); - return get_drive_parameters_without_extensions(drive_info); + return return_code; } -- cgit v1.2.1 From 6bb4566204d84145d3f870e57099e428cce9c6db Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 21:58:54 -0700 Subject: gpllib: Add support for Cache Information (Type 7) (dmi) From the SMBIOS spec (v2.6.1): 3.3.8 Cache Information (Type 7): The information in this structure defines the attributes of CPU cache device in the system. One structure is specified for each such device, whether the device is internal to or external to the CPU module. Cache modules can be associated with a processor structure in one or two ways depending on the SMBIOS version, see 3.3.5 Processor Information (Type 4) on page 25 and 3.3.15 Group Associations (Type 14) on page 46 for more information. Implementation mostly borrowed from the dmidecode project. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 4 ++ com32/gplinclude/dmi/dmi_cache.h | 47 ++++++++++++++ com32/gpllib/Makefile | 3 +- com32/gpllib/dmi/dmi.c | 34 +++++++++- com32/gpllib/dmi/dmi_cache.c | 135 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 com32/gplinclude/dmi/dmi_cache.h create mode 100644 com32/gpllib/dmi/dmi_cache.c diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index 89782a97..50cd4cac 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -14,6 +14,7 @@ #define DMI_H #include #define MAX_DMI_MEMORY_ITEMS 32 +#define MAX_DMI_CACHE_ITEMS 32 #define PAGE_SIZE 4096 @@ -34,6 +35,7 @@ enum {DMI_TABLE_PRESENT = 100, ENODMITABLE}; #include "dmi_memory.h" #include "dmi_battery.h" #include "dmi_ipmi.h" +#include "dmi_cache.h" extern char display_line; #define moreprintf(...) do { display_line++; if (display_line == 24) { char tempbuf[10]; display_line=0; printf("Press enter to continue"); fgets(tempbuf, sizeof tempbuf, stdin);} printf ( __VA_ARGS__); } while (0); @@ -66,7 +68,9 @@ typedef struct { s_battery battery; s_memory memory[MAX_DMI_MEMORY_ITEMS]; s_ipmi ipmi; + s_cache cache[MAX_DMI_CACHE_ITEMS]; int memory_count; + int cache_count; dmi_table dmitable; } s_dmi; diff --git a/com32/gplinclude/dmi/dmi_cache.h b/com32/gplinclude/dmi/dmi_cache.h new file mode 100644 index 00000000..50f93afd --- /dev/null +++ b/com32/gplinclude/dmi/dmi_cache.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Some part borrowed from DMI Decode: + * + * (C) 2000-2002 Alan Cox + * (C) 2002-2007 Jean Delvare + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#ifndef DMI_CACHE_H +#define DMI_CACHE_H + +#include + +#include "stdbool.h" + +typedef struct { + char socket_designation[32]; + char configuration[32]; + char mode[32]; + char location[8]; + uint16_t installed_size; + uint16_t max_size; + char supported_sram_types[32]; + char installed_sram_types[32]; + uint16_t speed; + char error_correction_type[32]; + char system_type[16]; + char associativity[32]; +} __attribute__((__packed__)) s_cache; + +const char *dmi_cache_mode(uint8_t code); +const char *dmi_cache_location(uint8_t code); +uint16_t dmi_cache_size(uint16_t code); +void dmi_cache_types(uint16_t code, const char *sep, char* array); +const char *dmi_cache_ec_type(uint8_t code); +const char *dmi_cache_type(uint8_t code); +const char *dmi_cache_associativity(uint8_t code); +#endif /* DMI_CACHE_H */ diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index e8d7e57f..8026a45c 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -10,7 +10,8 @@ REQFLAGS += -I../gplinclude LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ - dmi/dmi_ipmi.o cpuid.o disk/geom.o disk/read.o disk/write.o disk/msdos.o \ + dmi/dmi_ipmi.o dmi/dmi_cache.o cpuid.o disk/geom.o disk/read.o \ + disk/write.o disk/msdos.o \ disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o \ memory.o diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 23caa334..dfaf622f 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -492,7 +492,39 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) strcpy(dmi->processor.asset_tag,dmi_string(h, data[0x21])); strcpy(dmi->processor.part_number,dmi_string(h, data[0x22])); break; - case 17: /* 3.3.18 Memory Device */ + case 7: /* 3.3.8 Cache Information */ + if(h->length<0x0F) break; + dmi->cache_count++; + if (dmi->cache_count > MAX_DMI_CACHE_ITEMS) break; + strcpy(dmi->cache[dmi->cache_count-1].socket_designation, + dmi_string(h, data[0x04])); + sprintf(dmi->cache[dmi->cache_count-1].configuration, + "%s, %s, %u", + WORD(data+0x05)&0x0080?"Enabled":"Disabled", + WORD(data+0x05)&0x0008?"Socketed":"Not Socketed", + (WORD(data+0x05)&0x0007)+1); + strcpy(dmi->cache[dmi->cache_count-1].mode, + dmi_cache_mode((WORD(data+0x05)>>8)&0x0003)); + strcpy(dmi->cache[dmi->cache_count-1].location, + dmi_cache_location((WORD(data+0x05)>>5)&0x0003)); + dmi->cache[dmi->cache_count-1].installed_size = + dmi_cache_size(WORD(data+0x09)); + dmi->cache[dmi->cache_count-1].max_size = + dmi_cache_size(WORD(data+0x07)); + dmi_cache_types(WORD(data+0x0B), " ", + dmi->cache[dmi->cache_count-1].supported_sram_types); + dmi_cache_types(WORD(data+0x0D), " ", + dmi->cache[dmi->cache_count-1].installed_sram_types); + if(h->length<0x13) break; + dmi->cache[dmi->cache_count-1].speed = data[0x0F]; /* ns */ + strcpy(dmi->cache[dmi->cache_count-1].error_correction_type, + dmi_cache_ec_type(data[0x10])); + strcpy(dmi->cache[dmi->cache_count-1].system_type, + dmi_cache_type(data[0x11])); + strcpy(dmi->cache[dmi->cache_count-1].associativity, + dmi_cache_associativity(data[0x12])); + break; + case 17: /* 3.3.18 Memory Device */ if (h->length < 0x15) break; dmi->memory_count++; s_memory *mem = &dmi->memory[dmi->memory_count-1]; diff --git a/com32/gpllib/dmi/dmi_cache.c b/com32/gpllib/dmi/dmi_cache.c new file mode 100644 index 00000000..bc1fc45f --- /dev/null +++ b/com32/gpllib/dmi/dmi_cache.c @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Some part borrowed from DMI Decode: + * + * (C) 2000-2002 Alan Cox + * (C) 2002-2007 Jean Delvare + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include + +/* + * 3.3.8 Cache Information (Type 7) + */ + +const char *dmi_cache_mode(uint8_t code) +{ + static const char *mode[]={ + "Write Through", /* 0x00 */ + "Write Back", + "Varies With Memory Address", + "Unknown" /* 0x03 */ + }; + + return mode[code]; +} + +const char *dmi_cache_location(uint8_t code) +{ + static const char *location[4]={ + "Internal", /* 0x00 */ + "External", + NULL, /* 0x02 */ + "Unknown" /* 0x03 */ + }; + + if(location[code]!=NULL) + return location[code]; + return out_of_spec; +} + +uint16_t dmi_cache_size(uint16_t code) +{ + if(code&0x8000) + return (code&0x7FFF)<<6; /* KB */ + else + return code; /* KB */ +} + +void dmi_cache_types(uint16_t code, const char *sep, char* array) +{ + /* 3.3.8.2 */ + static const char *types[]={ + "Other", /* 0 */ + "Unknown", + "Non-burst", + "Burst", + "Pipeline Burst", + "Synchronous", + "Asynchronous" /* 6 */ + }; + + if((code&0x007F)==0) + strcpy(array, "None"); + else + { + int i; + + for(i=0; i<=6; i++) + if(code&(1<=0x01 && code<=0x06) + return type[code-0x01]; + return out_of_spec; +} + +const char *dmi_cache_type(uint8_t code) +{ + /* 3.3.8.4 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Instruction", + "Data", + "Unified" /* 0x05 */ + }; + + if(code>=0x01 && code<=0x05) + return type[code-0x01]; + return out_of_spec; +} + +const char *dmi_cache_associativity(uint8_t code) +{ + /* 3.3.8.5 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Direct Mapped", + "2-way Set-associative", + "4-way Set-associative", + "Fully Associative", + "8-way Set-associative", + "16-way Set-associative" /* 0x08 */ + }; + + if(code>=0x01 && code<=0x08) + return type[code-0x01]; + return out_of_spec; +} -- cgit v1.2.1 From 46db836cba26dca258554bda0b175cd372144194 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:03:48 -0700 Subject: hdt: Add SMBIOS Cache Information (Type 7) (CLI) Implements: dmi> show cache to get information about CPU cache devices in the system. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ com32/hdt/hdt-cli.h | 1 + 2 files changed, 57 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 08343b4d..f0b371e1 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -61,6 +61,8 @@ static void show_dmi_modules(int argc __unused, char** argv __unused, printf("\t%s\n", CLI_DMI_SYSTEM); if (hardware->dmi.ipmi.filled == true) printf("\t%s\n", CLI_DMI_IPMI); + if (hardware->dmi.cache_count) + printf("\t%s\n", CLI_DMI_CACHE); } static void show_dmi_base_board(int argc __unused, char** argv __unused, @@ -354,6 +356,56 @@ static void show_dmi_memory_bank(int argc, char** argv, hardware->dmi.memory[bank].part_number); } +static void show_dmi_cache(int argc, char** argv, + struct s_hardware *hardware) +{ + if (!hardware->dmi.cache_count) { + printf("cache information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + + int cache = strtol(argv[0], NULL, 10); + + if (argc != 1 || cache > hardware->dmi.cache_count) { + printf("show cache [0-%d]\n", hardware->dmi.cache_count-1); + return; + } + + reset_more_printf(); + + more_printf("Cache Information #%d\n", cache); + more_printf(" Socket Designation : %s\n", + hardware->dmi.cache[cache].socket_designation); + more_printf(" Configuration : %s\n", + hardware->dmi.cache[cache].configuration); + more_printf(" Operational Mode : %s\n", + hardware->dmi.cache[cache].mode); + more_printf(" Location : %s\n", + hardware->dmi.cache[cache].location); + more_printf(" Installed Size : %u KB", + hardware->dmi.cache[cache].installed_size); + more_printf("\n"); + more_printf(" Maximum Size : %u KB", + hardware->dmi.cache[cache].max_size); + more_printf("\n"); + more_printf(" Supported SRAM Types : %s", + hardware->dmi.cache[cache].supported_sram_types); + more_printf("\n"); + more_printf(" Installed SRAM Type : %s", + hardware->dmi.cache[cache].installed_sram_types); + more_printf("\n"); + more_printf(" Speed : %u ns", + hardware->dmi.cache[cache].speed); + more_printf("\n"); + more_printf(" Error Correction Type : %s\n", + hardware->dmi.cache[cache].error_correction_type); + more_printf(" System Type : %s\n", + hardware->dmi.cache[cache].system_type); + more_printf(" Associativity : %s\n", + hardware->dmi.cache[cache].associativity); +} + void main_show_dmi(int argc __unused, char **argv __unused, struct s_hardware *hardware) { @@ -466,6 +518,10 @@ struct cli_callback_descr list_dmi_show_modules[] = { .name = CLI_DMI_IPMI, .exec = show_dmi_ipmi, }, + { + .name = CLI_DMI_CACHE, + .exec = show_dmi_cache, + }, { .name = CLI_DMI_LIST, .exec = show_dmi_modules, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index df324fd2..7c435959 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -167,6 +167,7 @@ void main_show(char *item, struct s_hardware *hardware); #define CLI_DMI_PROCESSOR "cpu" #define CLI_DMI_SYSTEM "system" #define CLI_DMI_IPMI "ipmi" +#define CLI_DMI_CACHE "cache" #define CLI_DMI_LIST CLI_SHOW_LIST void main_show_dmi(int argc, char **argv, struct s_hardware *hardware); void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware); -- cgit v1.2.1 From 3ebc43d1bc1319053e5dcdae3f6669dc975a343e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:08:12 -0700 Subject: gpllib: Add support for 3.3.33 System Boot Information (Type 32) (dmi) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From SMBIOS spec (v2.6.1): 3.3.33 System Boot Information (Type 32): The client system firmware, e.g. BIOS, communicates the System Boot Status to the client’s Pre-boot Execution Environment (PXE) boot image or OS-present management application via this structure. When used in the PXE environment, for example, this code identifies the reason the PXE was initiated and can be used by boot-image software to further automate an enterprise’s PXE sessions. For example, an enterprise could choose to automatically download a hardware-diagnostic image to a client whose reason code indicated either a firmware- or operating system-detected hardware failure. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi_system.h | 4 +++- com32/gpllib/dmi/dmi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/com32/gplinclude/dmi/dmi_system.h b/com32/gplinclude/dmi/dmi_system.h index 5a461d5f..d24f82a7 100644 --- a/com32/gplinclude/dmi/dmi_system.h +++ b/com32/gplinclude/dmi/dmi_system.h @@ -22,6 +22,8 @@ #define SYSTEM_SKU_NUMBER_SIZE 32 #define SYSTEM_FAMILY_SIZE 32 +#define SYSTEM_BOOT_STATUS_SIZE 50 + typedef struct { char manufacturer[SYSTEM_MANUFACTURER_SIZE]; char product_name[SYSTEM_PRODUCT_NAME_SIZE]; @@ -33,6 +35,6 @@ char sku_number[SYSTEM_SKU_NUMBER_SIZE]; char family[SYSTEM_FAMILY_SIZE]; /* The filled field have to be set to true when the dmitable implement that item */ bool filled; +char system_boot_status[SYSTEM_BOOT_STATUS_SIZE]; } s_system; - #endif diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index dfaf622f..023159b2 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -33,6 +33,31 @@ const char *out_of_spec = ""; const char *bad_index = ""; +/* + * Misc. util stuff + */ +static void dmi_system_boot_status(uint8_t code, char* array) +{ + static const char *status[]={ + "No errors detected", /* 0 */ + "No bootable media", + "Operating system failed to load", + "Firmware-detected hardware failure", + "Operating system-detected hardware failure", + "User-requested boot", + "System security violation", + "Previously-requested image", + "System watchdog timer expired" /* 8 */ + }; + + if (code<=8) + strncpy(array, status[code], SYSTEM_BOOT_STATUS_SIZE); + if (code>=128 && code<=191) + strncpy(array, "OEM-specific", SYSTEM_BOOT_STATUS_SIZE); + if (code>=192) + strncpy(array, "Product-specific", SYSTEM_BOOT_STATUS_SIZE); +} + void dmi_bios_runtime_size(uint32_t code, s_dmi *dmi) { if(code&0x000003FF) { @@ -585,6 +610,10 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16)); break; + case 32: /* 3.3.33 System Boot Information */ + if (h->length < 0x0B) break; + dmi_system_boot_status(data[0x0A], + dmi->system.system_boot_status); case 38: /* 3.3.39 IPMI Device Information */ if (h->length < 0x10) break; dmi->ipmi.filled=true; -- cgit v1.2.1 From b8c65deb103e5fb2b4f83e91d91ffe77c66cd9d0 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:09:30 -0700 Subject: hdt: Add System Boot Information to System output (dmi) (CLI) Output System Boot Information along System information, just like dmidecode does. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index f0b371e1..16dd61d1 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -108,6 +108,9 @@ static void show_dmi_system(int argc __unused, char** argv __unused, printf(" Wakeup Type : %s\n", hardware->dmi.system.wakeup_type); printf(" SKU Number : %s\n", hardware->dmi.system.sku_number); printf(" Family : %s\n", hardware->dmi.system.family); + + printf("System Boot Information\n"); + printf(" Status : %s\n", hardware->dmi.system.system_boot_status); } static void show_dmi_bios(int argc __unused, char** argv __unused, -- cgit v1.2.1 From 1e44e2761ab5781b09b900bfab7099feb0da4afc Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:11:45 -0700 Subject: gpllib: Remove extra \n in oem chassis information (dmi) Cleanup chassis oem information string. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/dmi/dmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 023159b2..f180d39a 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -483,7 +483,7 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) strcpy(dmi->chassis.thermal_state,dmi_chassis_state(data[0x0B])); strcpy(dmi->chassis.security_status,dmi_chassis_security_status(data[0x0C])); if(h->length<0x11) break; - sprintf(dmi->chassis.oem_information,"0x%08X\n",DWORD(data+0x0D)); + sprintf(dmi->chassis.oem_information,"0x%08X",DWORD(data+0x0D)); if(h->length<0x15) break; dmi->chassis.height=data[0x11]; dmi->chassis.nb_power_cords=data[0x12]; -- cgit v1.2.1 From f842f258dbaca7d0d56bbe4d1052fd9c8f58eabd Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:12:49 -0700 Subject: gpllib: Prevent overflow in memory type (dmi) We can store up to MAX_DMI_MEMORY_ITEMS memory modules information. Make sure we don't overflow. (Impact: bug fix) Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/dmi/dmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index f180d39a..d0e92a80 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -552,6 +552,7 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) case 17: /* 3.3.18 Memory Device */ if (h->length < 0x15) break; dmi->memory_count++; + if (dmi->memory_count > MAX_DMI_MEMORY_ITEMS) break; s_memory *mem = &dmi->memory[dmi->memory_count-1]; dmi->memory[dmi->memory_count-1].filled=true; dmi_memory_array_error_handle(WORD(data + 0x06),mem->error); -- cgit v1.2.1 From fda6fcb4b652492516477f7865a36d0e75626821 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:14:52 -0700 Subject: hdt: Be more specific in BIOS output (dmi) (CLI) Specify "Release Date" instead of "Release", as the latter may be confusing. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 16dd61d1..91d721d2 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -125,7 +125,7 @@ static void show_dmi_bios(int argc __unused, char** argv __unused, more_printf("BIOS\n"); more_printf(" Vendor : %s\n", hardware->dmi.bios.vendor); more_printf(" Version : %s\n", hardware->dmi.bios.version); - more_printf(" Release : %s\n", + more_printf(" Release Date : %s\n", hardware->dmi.bios.release_date); more_printf(" Bios Revision : %s\n", hardware->dmi.bios.bios_revision); -- cgit v1.2.1 From e3c38340f2ad936064f584d27ea7ad61d03ea81e Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:16:07 -0700 Subject: hdt: Only output Firmware Revision when present (dmi) (CLI) Do not print an empty string when Firmware Revision is not present. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 91d721d2..4f9c8505 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -129,8 +129,9 @@ static void show_dmi_bios(int argc __unused, char** argv __unused, hardware->dmi.bios.release_date); more_printf(" Bios Revision : %s\n", hardware->dmi.bios.bios_revision); - more_printf(" Firmware Revision : %s\n", - hardware->dmi.bios.firmware_revision); + if (strlen(hardware->dmi.bios.firmware_revision)) + more_printf(" Firmware Revision : %s\n", + hardware->dmi.bios.firmware_revision); more_printf(" Address : 0x%04X0\n", hardware->dmi.bios.address); more_printf(" Runtime address : %u %s\n", -- cgit v1.2.1 From 897f8349b7f231329d0059ffc6645074ec8ab903 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Thu, 14 May 2009 22:17:10 -0700 Subject: hdt: Fix build warning (dmi) (CLI) 'clear' does not appear to be used. (Impact: build cleanup) Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index 4f9c8505..3602ef8b 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -430,7 +430,7 @@ void main_show_dmi(int argc __unused, char **argv __unused, void show_dmi_memory_modules(int argc __unused, char** argv __unused, struct s_hardware *hardware) { - int clear = 1, show_free_banks = 1; + int show_free_banks = 1; /* Needed, if called by the memory mode */ detect_dmi(hardware); -- cgit v1.2.1 From ea1b802a5c3df6e4d1de81fc4c34a89feb5e45c3 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 20:11:17 -0700 Subject: gpllib: Add support for 3.3.13 System Configuration Options (Type 12) (dmi) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From SMBIOS spec (v.2.6.1): This structure contains information required to configure the base board’s Jumpers and Switches. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi_system.h | 2 ++ com32/gpllib/dmi/dmi.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/com32/gplinclude/dmi/dmi_system.h b/com32/gplinclude/dmi/dmi_system.h index d24f82a7..896c1e54 100644 --- a/com32/gplinclude/dmi/dmi_system.h +++ b/com32/gplinclude/dmi/dmi_system.h @@ -23,6 +23,7 @@ #define SYSTEM_FAMILY_SIZE 32 #define SYSTEM_BOOT_STATUS_SIZE 50 +#define SYSTEM_CONFIGURATION_OPTIONS_SIZE 50 typedef struct { char manufacturer[SYSTEM_MANUFACTURER_SIZE]; @@ -36,5 +37,6 @@ char family[SYSTEM_FAMILY_SIZE]; /* The filled field have to be set to true when the dmitable implement that item */ bool filled; char system_boot_status[SYSTEM_BOOT_STATUS_SIZE]; +char configuration_options[SYSTEM_CONFIGURATION_OPTIONS_SIZE]; } s_system; #endif diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 352483e9..7498b7fa 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -36,6 +36,21 @@ const char *bad_index = ""; /* * Misc. util stuff */ + +/* + * 3.3.13 System Configuration Options (Type 12) + */ +static void dmi_system_configuration_options(struct dmi_header *h, const char *prefix, s_dmi *dmi) +{ + uint8_t *p = h->data+4; + uint8_t count = p[0x00]; + int i; + + for (i=1; i<=count; i++) + snprintf(dmi->system.configuration_options, SYSTEM_CONFIGURATION_OPTIONS_SIZE, "%s %s %s\n", + dmi->system.configuration_options, prefix, dmi_string(h, i)); +} + static void dmi_system_boot_status(uint8_t code, char* array) { static const char *status[]={ @@ -563,6 +578,10 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) strcpy(dmi->cache[dmi->cache_count-1].associativity, dmi_cache_associativity(data[0x12])); break; + case 12: /* 3.3.13 System Configuration Options */ + if (h->length < 0x05) break; + dmi_system_configuration_options(h, "\t", dmi); + break; case 17: /* 3.3.18 Memory Device */ if (h->length < 0x15) break; dmi->memory_count++; -- cgit v1.2.1 From a98e2b4b62967ef972b6817d5a8a1ac064fcfb51 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 20:14:34 -0700 Subject: hdt: Add SMBIOS System Configuration Options (Type 12) (CLI) Add type 12, displayed in the system summary. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index af289d14..efe5f5fa 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -115,6 +115,11 @@ static void show_dmi_system(int argc __unused, char** argv __unused, printf(" SKU Number : %s\n", hardware->dmi.system.sku_number); printf(" Family : %s\n", hardware->dmi.system.family); + if (strlen(hardware->dmi.system.configuration_options)) { + printf("System Configuration Options\n"); + printf("%s\n", hardware->dmi.system.configuration_options); + } + printf("System Boot Information\n"); printf(" Status : %s\n", hardware->dmi.system.system_boot_status); } -- cgit v1.2.1 From ad1235725d17522fb10d34052fe7e118ab43b7fa Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 21:03:16 -0700 Subject: gpllib: Add support for 3.3.24 System Reset (Type 23) (dmi) From SMBIOS spec (v2.6.1): This structure describes whether Automatic System Reset functions enabled (Status). If the system has a watchdog Timer and the timer is not reset (Timer Reset) before the Interval elapses, an automatic system reset will occur. The system will re-boot according to the Boot Option. This function may repeat until the Limit is reached, at which time the system will re-boot according to the Boot Option at Limit. Note: This structure type was added for specification v2.2. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi_system.h | 11 +++++++++ com32/gpllib/dmi/dmi.c | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/com32/gplinclude/dmi/dmi_system.h b/com32/gplinclude/dmi/dmi_system.h index 896c1e54..218fa4f9 100644 --- a/com32/gplinclude/dmi/dmi_system.h +++ b/com32/gplinclude/dmi/dmi_system.h @@ -38,5 +38,16 @@ char family[SYSTEM_FAMILY_SIZE]; bool filled; char system_boot_status[SYSTEM_BOOT_STATUS_SIZE]; char configuration_options[SYSTEM_CONFIGURATION_OPTIONS_SIZE]; +struct { + bool filled; + uint8_t status; + uint8_t watchdog; + char boot_option[17]; + char boot_option_on_limit[17]; + char reset_count[8]; + char reset_limit[8]; + char timer_interval[8]; + char timeout[8]; +} system_reset; } s_system; #endif diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 7498b7fa..1f96c3a7 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -37,6 +37,39 @@ const char *bad_index = ""; * Misc. util stuff */ +/* + * 3.3.24 System Reset (Type 23) + */ + +static const char *dmi_system_reset_boot_option(uint8_t code) +{ + static const char *option[]={ + "Operating System", /* 0x1 */ + "System Utilities", + "Do Not Reboot" /* 0x3 */ + }; + + if (code >= 0x1) + return option[code-0x1]; + return out_of_spec; +} + +static void dmi_system_reset_count(uint16_t code, char* array) +{ + if (code == 0xFFFF) + strncpy(array, "Unknown", sizeof array); + else + snprintf(array, sizeof array, "%u", code); +} + +static void dmi_system_reset_timer(uint16_t code, char* array) +{ + if (code == 0xFFFF) + strncpy(array, "Unknown", sizeof array); + else + snprintf(array, sizeof array, "%u min", code); +} + /* * 3.3.13 System Configuration Options (Type 12) */ @@ -644,6 +677,24 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16)); break; + case 23: /* 3.3.24 System Reset */ + if(h->length<0x0D) break; + dmi->system.system_reset.filled = true; + dmi->system.system_reset.status = data[0x04]&(1<<0); + dmi->system.system_reset.watchdog = data[0x04]&(1<<5); + if (!(data[0x04]&(1<<5))) + break; + strncpy(dmi->system.system_reset.boot_option, + dmi_system_reset_boot_option((data[0x04]>>1)&0x3), + sizeof dmi->system.system_reset.boot_option); + strncpy(dmi->system.system_reset.boot_option_on_limit, + dmi_system_reset_boot_option((data[0x04]>>3)&0x3), + sizeof dmi->system.system_reset.boot_option_on_limit); + dmi_system_reset_count(WORD(data+0x05), dmi->system.system_reset.reset_count); + dmi_system_reset_count(WORD(data+0x07), dmi->system.system_reset.reset_limit); + dmi_system_reset_timer(WORD(data+0x09), dmi->system.system_reset.timer_interval); + dmi_system_reset_timer(WORD(data+0x0B), dmi->system.system_reset.timeout); + break; case 32: /* 3.3.33 System Boot Information */ if (h->length < 0x0B) break; dmi_system_boot_status(data[0x0A], -- cgit v1.2.1 From 7f338086371dae8c6b47ebeec6370b1b1fe16b79 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 21:05:01 -0700 Subject: hdt: Add SMBIOS System Reset (Type 23) (CLI) Add type 23, displayed in the system summary. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index efe5f5fa..acba60b9 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -120,6 +120,26 @@ static void show_dmi_system(int argc __unused, char** argv __unused, printf("%s\n", hardware->dmi.system.configuration_options); } + if (hardware->dmi.system.system_reset.filled) { + printf("System Reset\n"); + printf(" Status : %s\n", + (hardware->dmi.system.system_reset.status ? "Enabled" : "Disabled")); + printf(" Watchdog Timer : %s\n", + (hardware->dmi.system.system_reset.watchdog ? "Present" : "Not Present")); + if (strlen(hardware->dmi.system.system_reset.boot_option)) + printf(" Boot Option : %s\n", hardware->dmi.system.system_reset.boot_option); + if (strlen(hardware->dmi.system.system_reset.boot_option_on_limit)) + printf(" Boot Option On Limit : %s\n", hardware->dmi.system.system_reset.boot_option_on_limit); + if (strlen(hardware->dmi.system.system_reset.reset_count)) + printf(" Reset Count : %s\n", hardware->dmi.system.system_reset.reset_count); + if (strlen(hardware->dmi.system.system_reset.reset_limit)) + printf(" Reset Limit : %s\n", hardware->dmi.system.system_reset.reset_limit); + if (strlen(hardware->dmi.system.system_reset.timer_interval)) + printf(" Timer Interval : %s\n", hardware->dmi.system.system_reset.timer_interval); + if (strlen(hardware->dmi.system.system_reset.timeout)) + printf(" Timeout : %s\n", hardware->dmi.system.system_reset.timeout); + } + printf("System Boot Information\n"); printf(" Status : %s\n", hardware->dmi.system.system_boot_status); } -- cgit v1.2.1 From b42c01026ffd63b6f1ced67109c1fbd1133e569d Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 21:36:40 -0700 Subject: gpllib: Add support for 3.3.11 On Board Devices Information (Type 10, obsolete) (dmi) From SMBIOS spec (v2.6.1): The information in this structure defines the attributes of devices that are onboard (soldered onto) a system element, usually the baseboard. In general, an entry in this table implies that the BIOS has some level of control over the enabling of the associated device for use by the system. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi_base_board.h | 5 ++++ com32/gpllib/dmi/dmi.c | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/com32/gplinclude/dmi/dmi_base_board.h b/com32/gplinclude/dmi/dmi_base_board.h index 5b92b848..f12cc222 100644 --- a/com32/gplinclude/dmi/dmi_base_board.h +++ b/com32/gplinclude/dmi/dmi_base_board.h @@ -48,6 +48,11 @@ char type[BASE_BOARD_TYPE_SIZE]; s_base_board_features features; /* The filled field have to be set to true when the dmitable implement that item */ bool filled; +struct { + char type[16]; + uint8_t status; + char description[10]; +} devices_information[10]; } s_base_board; #endif diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 1f96c3a7..61b75696 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -37,6 +37,48 @@ const char *bad_index = ""; * Misc. util stuff */ +/* + * 3.3.11 On Board Devices Information (Type 10) + */ + +static const char *dmi_on_board_devices_type(uint8_t code) +{ + /* 3.3.11.1 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Video", + "SCSI Controller", + "Ethernet", + "Token Ring", + "Sound", + "PATA Controller", + "SATA Controller", + "SAS Controller" /* 0x0A */ + }; + + if (code>=0x01 && code<=0x0A) + return type[code-0x01]; + return out_of_spec; +} + +static void dmi_on_board_devices(struct dmi_header *h, s_dmi* dmi) +{ + uint8_t *p = h->data+4; + uint8_t count = (h->length-0x04)/2; + unsigned int i; + + for (i=0; ibase_board.devices_information/sizeof *dmi->base_board.devices_information; i++) { + strncpy(dmi->base_board.devices_information[i].type, + dmi_on_board_devices_type(p[2*i]&0x7F), + sizeof dmi->base_board.devices_information[i].type); + dmi->base_board.devices_information[i].status = p[2*i]&0x80; + strncpy(dmi->base_board.devices_information[i].description, + dmi_string(h, p[2*i+1]), + sizeof dmi->base_board.devices_information[i].description); + } +} + /* * 3.3.24 System Reset (Type 23) */ @@ -611,6 +653,9 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) strcpy(dmi->cache[dmi->cache_count-1].associativity, dmi_cache_associativity(data[0x12])); break; + case 10: /* 3.3.11 On Board Devices Information */ + dmi_on_board_devices(h, dmi); + break; case 12: /* 3.3.13 System Configuration Options */ if (h->length < 0x05) break; dmi_system_configuration_options(h, "\t", dmi); -- cgit v1.2.1 From 9d5d0a2460b02bb5c942bbec33dfc87e5ef6afb6 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 26 May 2009 21:38:01 -0700 Subject: hdt: Add SMBIOS On Board Devices Information (Type 10) (CLI) Add information about devices found on the baseboard. Note that this is displayed only if information about the baseboard itself can be retrieved via SMBIOS Type 2. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index acba60b9..f34539fe 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -95,6 +95,15 @@ static void show_dmi_base_board(int argc __unused, char** argv __unused, more_printf(" %s\n", base_board_features_strings[i]); } } + + for (unsigned int i=0; idmi.base_board.devices_information/sizeof *hardware->dmi.base_board.devices_information; i++) { + if (strlen(hardware->dmi.base_board.devices_information[i].type)) { + more_printf("On Board Device #%u Information\n", i) + more_printf(" Type : %s\n", hardware->dmi.base_board.devices_information[i].type); + more_printf(" Status : %s\n", hardware->dmi.base_board.devices_information[i].status ? "Enabled" : "Disabled"); + more_printf(" Description : %s\n", hardware->dmi.base_board.devices_information[i].description); + } + } } static void show_dmi_system(int argc __unused, char** argv __unused, -- cgit v1.2.1 From 2892315ca6843029765033a4283b0e22e979f5bd Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 12:53:34 -0700 Subject: gpllib: Add support for 3.3.12 OEM Strings (Type 11) (dmi) From SMBIOS spec (v2.6.1): This structure contains free form strings defined by the OEM. Examples of this are: Part Numbers for Reference Documents for the system, contact information for the manufacturer, etc. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 2 ++ com32/gpllib/dmi/dmi.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index f087df56..5ef09f92 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -15,6 +15,7 @@ #include #define MAX_DMI_MEMORY_ITEMS 32 #define MAX_DMI_CACHE_ITEMS 32 +#define OEM_STRINGS_SIZE 100 #define PAGE_SIZE 4096 @@ -74,6 +75,7 @@ typedef struct { int memory_count; int cache_count; dmi_table dmitable; + char oem_strings[OEM_STRINGS_SIZE]; } s_dmi; void to_dmi_header(struct dmi_header *h, uint8_t *data); diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 61b75696..731d6e62 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -112,6 +112,21 @@ static void dmi_system_reset_timer(uint16_t code, char* array) snprintf(array, sizeof array, "%u min", code); } +/* + * 3.3.12 OEM Strings (Type 11) + */ + +static void dmi_oem_strings(struct dmi_header *h, const char *prefix, s_dmi *dmi) +{ + uint8_t *p=h->data+4; + uint8_t count=p[0x00]; + int i; + + for(i=1; i<=count; i++) + snprintf(dmi->oem_strings, OEM_STRINGS_SIZE, "%s %s %s\n", + dmi->oem_strings, prefix, dmi_string(h, i)); +} + /* * 3.3.13 System Configuration Options (Type 12) */ @@ -656,6 +671,10 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) case 10: /* 3.3.11 On Board Devices Information */ dmi_on_board_devices(h, dmi); break; + case 11: /* 3.3.12 OEM Strings */ + if (h->length<0x05) break; + dmi_oem_strings(h, "\t", dmi); + break; case 12: /* 3.3.13 System Configuration Options */ if (h->length < 0x05) break; dmi_system_configuration_options(h, "\t", dmi); -- cgit v1.2.1 From 048ff4ad66f2effc7f6f20f8650619578832cb54 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 12:54:51 -0700 Subject: hdt: Add SMBIOS OEM Strings (Type 11) (CLI) Implements: dmi> show oem to get information about OEM specific strings. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 15 +++++++++++++++ com32/hdt/hdt-cli.h | 1 + 2 files changed, 16 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index f34539fe..db7d1543 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -69,6 +69,8 @@ static void show_dmi_modules(int argc __unused, char** argv __unused, printf("\t%s\n", CLI_DMI_IPMI); if (hardware->dmi.cache_count) printf("\t%s\n", CLI_DMI_CACHE); + if (strlen(hardware->dmi.oem_strings)) + more_printf("\t%s\n", CLI_DMI_OEM); } static void show_dmi_base_board(int argc __unused, char** argv __unused, @@ -566,6 +568,15 @@ usage: return; } +void show_dmi_oem_strings(int argc __unused, char** argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + + if (strlen(hardware->dmi.oem_strings)) + more_printf("OEM Strings\n%s", hardware->dmi.oem_strings); +} + struct cli_callback_descr list_dmi_show_modules[] = { { .name = CLI_DMI_BASE_BOARD, @@ -603,6 +614,10 @@ struct cli_callback_descr list_dmi_show_modules[] = { .name = CLI_DMI_SYSTEM, .exec = show_dmi_system, }, + { + .name = CLI_DMI_OEM, + .exec = show_dmi_oem_strings, + }, { .name = CLI_DMI_IPMI, .exec = show_dmi_ipmi, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 88999408..37313824 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -168,6 +168,7 @@ void main_show(char *item, struct s_hardware *hardware); #define CLI_DMI_SYSTEM "system" #define CLI_DMI_IPMI "ipmi" #define CLI_DMI_CACHE "cache" +#define CLI_DMI_OEM "oem" #define CLI_DMI_LIST CLI_SHOW_LIST void main_show_dmi(int argc, char **argv, struct s_hardware *hardware); void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware); -- cgit v1.2.1 From 248ae319fa0b58c6edce9f1f732a6f24f307df32 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 13:44:36 -0700 Subject: gpllib: Enlarge OEM Strings buffer (dmi) After some testing on a X200, it appears that the OEM Strings can be quite long (~200 chars on the X200). Let's be quite generous on that one. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index 5ef09f92..91986769 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -15,8 +15,7 @@ #include #define MAX_DMI_MEMORY_ITEMS 32 #define MAX_DMI_CACHE_ITEMS 32 -#define OEM_STRINGS_SIZE 100 - +#define OEM_STRINGS_SIZE 512 #define PAGE_SIZE 4096 extern const char *out_of_spec; -- cgit v1.2.1 From a5e1f00ba1dca6297dc12a3141fb1e2881a6ec5f Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 13:54:30 -0700 Subject: gpllib: Add support for 3.3.25 Hardware Security (Type 24) (dmi) From SMBIOS spec (v2.6.1): This structure describes the system-wide hardware security settings. Note: This structure type was added for specification v2.2. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 7 +++++++ com32/gpllib/dmi/dmi.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index 91986769..7bc58923 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -75,6 +75,13 @@ typedef struct { int cache_count; dmi_table dmitable; char oem_strings[OEM_STRINGS_SIZE]; + struct { + char power_on_passwd_status[HARDWARE_SECURITY_SIZE]; + char keyboard_passwd_status[HARDWARE_SECURITY_SIZE]; + char administrator_passwd_status[HARDWARE_SECURITY_SIZE]; + char front_panel_reset_status[HARDWARE_SECURITY_SIZE]; + bool filled; + } hardware_security; } s_dmi; void to_dmi_header(struct dmi_header *h, uint8_t *data); diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index 731d6e62..06f39923 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -112,6 +112,22 @@ static void dmi_system_reset_timer(uint16_t code, char* array) snprintf(array, sizeof array, "%u min", code); } +/* + * 3.3.25 Hardware Security (Type 24) + */ + +static const char *dmi_hardware_security_status(uint8_t code) +{ + static const char *status[]={ + "Disabled", /* 0x00 */ + "Enabled", + "Not Implemented", + "Unknown" /* 0x03 */ + }; + + return status[code]; +} + /* * 3.3.12 OEM Strings (Type 11) */ @@ -759,6 +775,22 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) dmi_system_reset_timer(WORD(data+0x09), dmi->system.system_reset.timer_interval); dmi_system_reset_timer(WORD(data+0x0B), dmi->system.system_reset.timeout); break; + case 24: /* 3.3.25 Hardware Security */ + if (h->length<0x05) break; + dmi->hardware_security.filled = true; + strncpy(dmi->hardware_security.power_on_passwd_status, + dmi_hardware_security_status(data[0x04]>>6), + sizeof dmi->hardware_security.power_on_passwd_status); + strncpy(dmi->hardware_security.keyboard_passwd_status, + dmi_hardware_security_status((data[0x04]>>4)&0x3), + sizeof dmi->hardware_security.keyboard_passwd_status); + strncpy(dmi->hardware_security.administrator_passwd_status, + dmi_hardware_security_status((data[0x04]>>2)&0x3), + sizeof dmi->hardware_security.administrator_passwd_status); + strncpy(dmi->hardware_security.front_panel_reset_status, + dmi_hardware_security_status(data[0x04]&0x3), + sizeof dmi->hardware_security.front_panel_reset_status); + break; case 32: /* 3.3.33 System Boot Information */ if (h->length < 0x0B) break; dmi_system_boot_status(data[0x0A], -- cgit v1.2.1 From 6f95409d4464cdb10802c8f1fb118681afb77c32 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 14:02:16 -0700 Subject: hdt: Add SMBIOS Hardware Security Information (Type 24) (CLI) Implements: dmi> show security to get information about the system-wide hardware security settings. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-dmi.c | 25 +++++++++++++++++++++++++ com32/hdt/hdt-cli.h | 1 + 2 files changed, 26 insertions(+) diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index db7d1543..fca94cdc 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -71,6 +71,8 @@ static void show_dmi_modules(int argc __unused, char** argv __unused, printf("\t%s\n", CLI_DMI_CACHE); if (strlen(hardware->dmi.oem_strings)) more_printf("\t%s\n", CLI_DMI_OEM); + if (hardware->dmi.hardware_security.filled) + printf("\t%s\n", CLI_DMI_SECURITY); } static void show_dmi_base_board(int argc __unused, char** argv __unused, @@ -577,6 +579,25 @@ void show_dmi_oem_strings(int argc __unused, char** argv __unused, more_printf("OEM Strings\n%s", hardware->dmi.oem_strings); } +void show_dmi_hardware_security(int argc __unused, char** argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + + if (!hardware->dmi.hardware_security.filled) + return; + + more_printf("Hardware Security\n"); + more_printf(" Power-On Password Status : %s\n", + hardware->dmi.hardware_security.power_on_passwd_status); + more_printf(" Keyboard Password Status : %s\n", + hardware->dmi.hardware_security.keyboard_passwd_status); + more_printf(" Administrator Password Status : %s\n", + hardware->dmi.hardware_security.administrator_passwd_status); + more_printf(" Front Panel Reset Status : %s\n", + hardware->dmi.hardware_security.front_panel_reset_status); +} + struct cli_callback_descr list_dmi_show_modules[] = { { .name = CLI_DMI_BASE_BOARD, @@ -618,6 +639,10 @@ struct cli_callback_descr list_dmi_show_modules[] = { .name = CLI_DMI_OEM, .exec = show_dmi_oem_strings, }, + { + .name = CLI_DMI_SECURITY, + .exec = show_dmi_hardware_security, + }, { .name = CLI_DMI_IPMI, .exec = show_dmi_ipmi, diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 37313824..651575d1 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -169,6 +169,7 @@ void main_show(char *item, struct s_hardware *hardware); #define CLI_DMI_IPMI "ipmi" #define CLI_DMI_CACHE "cache" #define CLI_DMI_OEM "oem" +#define CLI_DMI_SECURITY "security" #define CLI_DMI_LIST CLI_SHOW_LIST void main_show_dmi(int argc, char **argv, struct s_hardware *hardware); void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware); -- cgit v1.2.1 From a3a51af1381b1abbbf82484b3258955f7d1e79f8 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 27 May 2009 21:24:25 -0700 Subject: gpllib: Define HARDWARE_SECURITY_SIZE for Type 24 (dmi) Impact: fix build HARDWARE_SECURITY_SIZE is used by DMI Type 24. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/dmi/dmi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index 7bc58923..a2274c02 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -16,6 +16,8 @@ #define MAX_DMI_MEMORY_ITEMS 32 #define MAX_DMI_CACHE_ITEMS 32 #define OEM_STRINGS_SIZE 512 +#define HARDWARE_SECURITY_SIZE 16 + #define PAGE_SIZE 4096 extern const char *out_of_spec; -- cgit v1.2.1 From 5e45fe5a4284dd362bbccd71bebaa3838d77591b Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 2 Jun 2009 08:32:36 +0800 Subject: Convert the cache code to C and implement the core printf function for the cahce part, I do get the error message says that undefined reference to `getlinsec'. I'm abort to implement a C version one. for the printf function, it works somehow, but doesn't work well. With the test, it seems it can handle the format output correctly. And I haven't debugged it, so I have no idea for now. --- core/cache.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ core/cache.h | 27 ++++++++++ core/diskstart.inc | 1 + core/extern.inc | 3 ++ core/extlinux.asm | 16 +++--- core/ldlinux.asm | 10 ++-- core/printf.c | 27 ++++++++++ core/types.h | 17 +++++++ 8 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 core/cache.c create mode 100644 core/cache.h create mode 100644 core/printf.c create mode 100644 core/types.h diff --git a/core/cache.c b/core/cache.c new file mode 100644 index 00000000..aaa90007 --- /dev/null +++ b/core/cache.c @@ -0,0 +1,145 @@ +#include "core.h" + +#include "cache.h" +#include + + +/* + * Each CachePtr contains: + * - Block pointer + * - LRU previous pointer + * - LRU next pointer + * - Block data buffer address + * + * The cache buffer are pointed to by a cache_head structure. + */ + + +static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; +static __u8 cache_data[65536]; +static int cache_block_size; +static int cache_entries; + +/** + * cache_init: + * + * Initialize the cache data structres. + * regs->eax.l stores the block size + * + */ +void cache_init(com32sys_t * regs) +{ + struct cache_struct *prev, *cur; + __u8 *data = cache_data; + int block_size = regs->eax.l; + int i; + + cache_block_size = block_size; + cache_entries = sizeof cache_data / block_size; + if (cache_entries > MAX_CACHE_ENTRIES) + cache_entries = MAX_CACHE_ENTRIES; + + cache_head.prev = &cache[cache_entries-1]; + cache_head.prev->next = &cache_head; + prev = &cache_head; + + for (i = 0; i < cache_entries; i++) { + cur = &cache[i]; + cur->block = 0; + cur->prev = prev; + prev->next = cur; + cur->data = data; + data += block_size; + prev = cur++; + } +} + + +extern void getlinsec(void); + +void getoneblk(char *buf, __u32 block, int block_size) +{ + int sec_per_block = block_size / 512; /* 512==sector size */ + com32sys_t regs; + + + + regs.eax.l = block * sec_per_block; + regs.ebp.l = sec_per_block; + regs.es = SEG(buf); + regs.ebx.w[0] = OFFS(buf); + + call16(getlinsec, ®s, NULL); +} + + + +/** + * get_cache_block: + * + * Check for a particular BLOCK in the block cache, + * and if it is already there, just do nothing and return; + * otherwise load it and updata the relative cache + * structre with data pointer. + * + * it's a test version for my start of merging extlinux into core. + * and after I have figured out how to handle the relations between + * rm and pm, c and asm, we call call it from C file, so no need + * com32sys_t *regs any more. + * + * @return: the data stores at gs:si + * + */ +void get_cache_block(com32sys_t * regs) +{ + /* let's find it from the end, 'cause the endest is the freshest */ + struct cache_struct *cs = cache_head.prev; + struct cache_struct *head, *last; + __u32 block = regs->eax.l; + int i; + + if ( !block ) { + extern void myputs(const char *); + myputs("ERROR: we got a ZERO block number that's not we want!\n"); + return; + } + + /* it's aleardy the freshest, so nothing we need do , just return it */ + if ( cs->block == block ) + goto out; + + for ( i = 0; i < cache_entries; i ++ ) { + if ( cs->block == block ) + break; + else + cs = cs->prev; + } + + if ( i == cache_entries ) { + /* missed, so we need to load it */ + + /* store it at the head of real cache */ + cs = cache_head.next; + + cs->block = block; + getoneblk(cs->data, block, cache_block_size); + } + + /* remove cs from current position in list */ + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + + + /* add to just before head node */ + last = cache_head.prev; + head = &cache_head; + + last->next = cs; + cs->prev = last; + head->prev = cs; + cs->next = head; + + out: + regs->gs = SEG(cs->data); + regs->esi.w[0]= OFFS(cs->data); +} diff --git a/core/cache.h b/core/cache.h new file mode 100644 index 00000000..89892a00 --- /dev/null +++ b/core/cache.h @@ -0,0 +1,27 @@ +#ifndef _CACHE_H +#define _CACHE_H + +#include "types.h" +#include + + +#define MAX_CACHE_ENTRIES 0x064 /* I'm not sure it's the max */ + + + +/* The cache structure */ +struct cache_struct { + __u32 block; + struct cache_struct *prev; + struct cache_struct *next; + void *data; +}; + + + +/* functions defined in cache.c */ +void cache_init(com32sys_t *regs); + +void get_cache_block(com32sys_t *regs); + +#endif /* cache.h */ diff --git a/core/diskstart.inc b/core/diskstart.inc index b8047264..4b570bcc 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -252,6 +252,7 @@ getonesec: ; that is dead from that point; this saves space. However, please keep ; the order to dst,src to keep things sane. ; + global getlinsec getlinsec: add eax,[bsHidden] ; Add partition offset xor edx,edx ; Zero-extend LBA (eventually allow 64 bits) diff --git a/core/extern.inc b/core/extern.inc index f765cffe..e6321d16 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -12,4 +12,7 @@ ; hello.c extern hello + ; cache.c + extern cache_init, get_cache_block + %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 3a054b22..2273ae19 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -153,7 +153,8 @@ Files resb MAX_OPEN*open_file_t_size ; ; Initialize the metadata cache ; - call initcache + mov eax, [ClustSize] + pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more @@ -308,7 +309,7 @@ open_inode: add eax,edx pop edx and dx,SECTOR_SIZE-1 - call getcachesector ; Get the group descriptor + pm_call get_cache_block ; Get the group descriptor add si,dx mov esi,[gs:si+bg_inode_table] ; Get inode table block # pop eax ; Get inode within group @@ -327,7 +328,7 @@ open_inode: and dx,SECTOR_SIZE-1 mov [bx+file_in_off],dx - call getcachesector + pm_call get_cache_block add si,dx mov cx,EXT2_GOOD_OLD_INODE_SIZE >> 2 mov di,ThisInode @@ -693,7 +694,7 @@ linsector: push eax mov eax,[si+file_in_sec] mov bx,si - call getcachesector ; Get inode + pm_call get_cache_block ; Get inode add si,[bx+file_in_off] ; Get *our* inode pop eax lea ebx,[i_block+4*eax] @@ -724,7 +725,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -742,7 +743,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -757,7 +758,7 @@ linsector: mov ebp,[gs:si+bx] shl ebp,cl add eax,ebp - call getcachesector + pm_call get_cache_block pop bx and bx,(SECTOR_SIZE >> 2)-1 shl bx,2 @@ -874,7 +875,6 @@ build_curdir_str: %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output %include "strecpy.inc" ; strcpy with end pointer check -%include "cache.inc" ; Metadata disk cache %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- diff --git a/core/ldlinux.asm b/core/ldlinux.asm index c08799f4..45110091 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -211,7 +211,8 @@ getfattype: ; ; Initialize the metadata cache ; - call initcache + mov eax, [ClustSize] + pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more @@ -392,7 +393,7 @@ search_dos_dir: .scansector: ; EAX <- directory sector to scan - call getcachesector + pm_call get_cache_block ; GS:SI now points to this sector mov cx,SECTOR_SIZE/32 ; 32 == directory entry size @@ -745,7 +746,7 @@ readdir: cmp eax,0 jz .fail .fetch_cache: - call getcachesector + pm_call get_cache_block .move_current: add si,bx ; Resume last position in sector mov ecx,SECTOR_SIZE ; 0 out high part @@ -1358,7 +1359,7 @@ nextsector: ; getfatsector: add eax,[FAT] ; FAT starting address - jmp getcachesector + pm_call get_cache_block ; ----------------------------------------------------------------------------- ; Common modules @@ -1368,7 +1369,6 @@ getfatsector: %include "plaincon.inc" ; writechr %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output -%include "cache.inc" ; Metadata disk cache %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- diff --git a/core/printf.c b/core/printf.c new file mode 100644 index 00000000..3872e927 --- /dev/null +++ b/core/printf.c @@ -0,0 +1,27 @@ +#include +#include + + + + +#define BUF_SIZE 1024 + +char buf[BUF_SIZE]; + + +extern void myputs(const char *); + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = sprintf(buf, format, ap); + va_end(ap); + + myputs(buf); + + return rv; + +} diff --git a/core/types.h b/core/types.h new file mode 100644 index 00000000..4cd3902c --- /dev/null +++ b/core/types.h @@ -0,0 +1,17 @@ +#ifndef _TYPES_H +#define _TYPES_H + +typedef unsigned long long __u64; +typedef unsigned int __u32; +typedef unsigned short __u16; +typedef unsigned char __u8; + + +typedef int __s32; +typedef short __s16; +typedef char __s8; + + + + +#endif /* types.h */ -- cgit v1.2.1 From d0ce3937b75d491777e2c1f57ba0eaa20176b9f3 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 04:42:41 +0800 Subject: Successed in converting the cache code to C It works well for extlinux(seems broken with ldlinux). With the printf function can not work well in the format string, like %d, I introduced a new function itoa(), that convert the number to string, for debugging. --- core/Makefile | 1 - core/cache.c | 64 +++++++++++++++++++++++++++++++++++++++-------------- core/cache.h | 4 ++-- core/extlinux.asm | 2 +- core/hello.c | 20 +++++++++++++++-- core/include/core.h | 7 ++++++ core/layout.inc | 2 ++ core/ldlinux.asm | 2 +- 8 files changed, 79 insertions(+), 23 deletions(-) diff --git a/core/Makefile b/core/Makefile index df3310ed..2e28c930 100644 --- a/core/Makefile +++ b/core/Makefile @@ -34,7 +34,6 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ ldlinux.bss ldlinux.sys ldlinux.bin \ - pxelinux.0 isolinux.bin isolinux-debug.bin \ extlinux.bin extlinux.bss extlinux.sys # All primary source files for the main syslinux files diff --git a/core/cache.c b/core/cache.c index aaa90007..c2c7a917 100644 --- a/core/cache.c +++ b/core/cache.c @@ -1,7 +1,8 @@ #include "core.h" - #include "cache.h" + #include +#include /* @@ -16,7 +17,6 @@ static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; -static __u8 cache_data[65536]; static int cache_block_size; static int cache_entries; @@ -24,18 +24,18 @@ static int cache_entries; * cache_init: * * Initialize the cache data structres. - * regs->eax.l stores the block size + * regs->eax.l stores the block size(in bits not bytes) * */ void cache_init(com32sys_t * regs) { struct cache_struct *prev, *cur; - __u8 *data = cache_data; - int block_size = regs->eax.l; + char *data = core_cache_buf; + int block_size_shift = regs->eax.l; int i; - cache_block_size = block_size; - cache_entries = sizeof cache_data / block_size; + cache_block_size = 1 << block_size_shift; + cache_entries = sizeof(core_cache_buf) >> block_size_shift; if (cache_entries > MAX_CACHE_ENTRIES) cache_entries = MAX_CACHE_ENTRIES; @@ -49,20 +49,18 @@ void cache_init(com32sys_t * regs) cur->prev = prev; prev->next = cur; cur->data = data; - data += block_size; + data += cache_block_size; prev = cur++; } } -extern void getlinsec(void); - -void getoneblk(char *buf, __u32 block, int block_size) +void getoneblk(char *buf, uint32_t block, int block_size) { - int sec_per_block = block_size / 512; /* 512==sector size */ + int sec_per_block = block_size >> 9; /* 512==sector size */ com32sys_t regs; - + memset(®s, 0, sizeof(regs) ); regs.eax.l = block * sec_per_block; regs.ebp.l = sec_per_block; @@ -87,6 +85,11 @@ void getoneblk(char *buf, __u32 block, int block_size) * rm and pm, c and asm, we call call it from C file, so no need * com32sys_t *regs any more. * + * I just found that I was tring to do a stupid thing! + * I haven't change the fs code to c, so for now the cache is based + * on SECTOR SIZE but not block size. While we can fix it easily by + * make the block size be the sector size. + * * @return: the data stores at gs:si * */ @@ -95,11 +98,20 @@ void get_cache_block(com32sys_t * regs) /* let's find it from the end, 'cause the endest is the freshest */ struct cache_struct *cs = cache_head.prev; struct cache_struct *head, *last; - __u32 block = regs->eax.l; + uint32_t block = regs->eax.l; int i; + + static int total_read; + static int missed; + char buf[10]; +#if 0 + itoa(buf, block); + myputs(buf); + myputs(" this is what we are looking cache for block\n\r"); +#endif + if ( !block ) { - extern void myputs(const char *); myputs("ERROR: we got a ZERO block number that's not we want!\n"); return; } @@ -123,7 +135,23 @@ void get_cache_block(com32sys_t * regs) cs->block = block; getoneblk(cs->data, block, cache_block_size); + + missed ++; + } + + total_read ++; + +#if 0 /* testing how efficiency the cache is */ + if ( total_read % 5 == 0 ) { + itoa(buf, total_read); + myputs("total_read "); + myputs(buf); + myputs("\tmissed "); + itoa(buf, missed); + myputs(buf); + myputs("\n\r"); } +#endif /* remove cs from current position in list */ cs->prev->next = cs->next; @@ -140,6 +168,10 @@ void get_cache_block(com32sys_t * regs) cs->next = head; out: + /* in fact, that would never be happened */ + if ( (char *)(cs->data) > (char*)0x100000 ) + myputs("the buffer addres higher than 1M limit\n\r"); + regs->gs = SEG(cs->data); regs->esi.w[0]= OFFS(cs->data); -} +} diff --git a/core/cache.h b/core/cache.h index 89892a00..666863d1 100644 --- a/core/cache.h +++ b/core/cache.h @@ -1,7 +1,7 @@ #ifndef _CACHE_H #define _CACHE_H -#include "types.h" +#include #include @@ -11,7 +11,7 @@ /* The cache structure */ struct cache_struct { - __u32 block; + uint32_t block; struct cache_struct *prev; struct cache_struct *next; void *data; diff --git a/core/extlinux.asm b/core/extlinux.asm index 2273ae19..bdf1cdeb 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -153,7 +153,7 @@ Files resb MAX_OPEN*open_file_t_size ; ; Initialize the metadata cache ; - mov eax, [ClustSize] + mov eax, 9 ; for now, the cache is based on sector but not block pm_call cache_init ; diff --git a/core/hello.c b/core/hello.c index eb0069f0..1909de44 100644 --- a/core/hello.c +++ b/core/hello.c @@ -1,16 +1,32 @@ #include #include +#include +#include + +void itoa(char *str, int num) +{ + char buf[10]; + int i = 0; + + do { + buf[i++] = num % 10 + 0x30; + }while ( num /= 10 ); + + str[i] = '\0'; + for (; i > 0; i -- ) + *str++ = buf[i-1]; +} void myputchar(int c) { static com32sys_t ireg; - static uint16_t *vram = 0xb8000; + //static uint16_t *vram = 0xb8000; ireg.eax.b[1] = 0x02; ireg.edx.b[0] = c; __intcall(0x21, &ireg, NULL); - *vram++ = c + 0x1f00; + //*vram++ = c + 0x0700; } void myputs(const char *str) diff --git a/core/include/core.h b/core/include/core.h index 91bd2d83..620459ea 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -4,6 +4,13 @@ #include extern char core_xfer_buf[65536]; +extern char core_cache_buf[65536]; + +extern void getlinsec(void); + +extern void myputs(const char*); +extern void itoa(char *, int); + void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); int __cdecl core_cfarcall(uint32_t, const void *, uint32_t); diff --git a/core/layout.inc b/core/layout.inc index fe292b14..4af661a1 100644 --- a/core/layout.inc +++ b/core/layout.inc @@ -127,7 +127,9 @@ auxseg resb aux_size ; ISOLINUX doesn't have a block cache yet real_mode_seg equ 3000h %else + global cache_seg, core_cache_buf cache_seg equ 3000h ; 64K area for metadata cache +core_cache_buf equ cache_seg << 4 real_mode_seg equ 4000h pktbuf_seg equ cache_seg ; PXELINUX packet buffers diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 45110091..34eec933 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -211,7 +211,7 @@ getfattype: ; ; Initialize the metadata cache ; - mov eax, [ClustSize] + mov eax, 9 pm_call cache_init ; -- cgit v1.2.1 From e751e537459b681b4a0b56276e58f08296f9dc8f Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 07:38:19 +0800 Subject: printf error fixed and removed the itao function as the printf function works well now --- Makefile | 2 +- core/cache.c | 29 +++++++++++------------------ core/hello.c | 17 ++--------------- core/include/core.h | 1 - core/printf.c | 13 +++---------- 5 files changed, 17 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index de0d2fda..fb411e7a 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ BOBJECTS = $(BTARGET) \ # Note: libinstaller is both a BSUBDIR and an ISUBDIR. It contains # files that depend only on the B phase, but may have to be regenerated # for "make installer". -BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump gpxe sample \ +BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump sample \ libinstaller dos win32 ITARGET = IOBJECTS = $(ITARGET) dos/copybs.com \ diff --git a/core/cache.c b/core/cache.c index c2c7a917..dca85a7d 100644 --- a/core/cache.c +++ b/core/cache.c @@ -103,12 +103,9 @@ void get_cache_block(com32sys_t * regs) static int total_read; static int missed; - char buf[10]; - + #if 0 - itoa(buf, block); - myputs(buf); - myputs(" this is what we are looking cache for block\n\r"); + printf("we are looking for cache of %d\n", block); #endif if ( !block ) { @@ -139,19 +136,7 @@ void get_cache_block(com32sys_t * regs) missed ++; } - total_read ++; -#if 0 /* testing how efficiency the cache is */ - if ( total_read % 5 == 0 ) { - itoa(buf, total_read); - myputs("total_read "); - myputs(buf); - myputs("\tmissed "); - itoa(buf, missed); - myputs(buf); - myputs("\n\r"); - } -#endif /* remove cs from current position in list */ cs->prev->next = cs->next; @@ -168,9 +153,17 @@ void get_cache_block(com32sys_t * regs) cs->next = head; out: + + total_read ++; + +#if 0 /* testing how efficiency the cache is */ + if ( total_read % 5 == 0 ) + printf("total_read %d\tmissed %d\n", total_read, missed); +#endif + /* in fact, that would never be happened */ if ( (char *)(cs->data) > (char*)0x100000 ) - myputs("the buffer addres higher than 1M limit\n\r"); + printf("the buffer addres higher than 1M limit\n\r"); regs->gs = SEG(cs->data); regs->esi.w[0]= OFFS(cs->data); diff --git a/core/hello.c b/core/hello.c index ae75ced3..a1591111 100644 --- a/core/hello.c +++ b/core/hello.c @@ -3,19 +3,6 @@ #include #include -void itoa(char *str, int num) -{ - char buf[10]; - int i = 0; - - do { - buf[i++] = num % 10 + 0x30; - }while ( num /= 10 ); - - str[i] = '\0'; - for (; i > 0; i -- ) - *str++ = buf[i-1]; -} void myputchar(int c) { @@ -37,7 +24,7 @@ void myputs(const char *str) void hello(void) { - static char hello_str[] = "Hello, World! (hello.c)\n"; + static char hello_str[] = "Hello, World!"; - myputs(hello_str); + printf("%s from (%s)\n", hello_str, __FILE__); /* testing */ } diff --git a/core/include/core.h b/core/include/core.h index bd04feb0..8e7cd03c 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -12,7 +12,6 @@ extern void getlinsec(void); /* hello.c */ extern void myputs(const char*); -extern void itoa(char *, int); void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); diff --git a/core/printf.c b/core/printf.c index 3872e927..b1b0466b 100644 --- a/core/printf.c +++ b/core/printf.c @@ -1,23 +1,16 @@ #include #include - - - -#define BUF_SIZE 1024 - -char buf[BUF_SIZE]; - - -extern void myputs(const char *); +#include "core.h" int printf(const char *format, ...) { + char buf[1024]; va_list ap; int rv; va_start(ap, format); - rv = sprintf(buf, format, ap); + rv = vsnprintf(buf, sizeof buf, format, ap); va_end(ap); myputs(buf); -- cgit v1.2.1 From 7fc77159cc87c848e8c222951516731b433f9944 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 13:14:41 +0800 Subject: Convert the config load part to C For now, I added a temporary file load_config.c that would be merged into extlinux.c file later, which would make my later work be much easier. And in order to get rid of the conflict noisy message from the open function in ui.inc and the open function defined in the unistd.h, I changed the open in core to core_open. It may be ugly, but it works :) --- core/comboot.inc | 2 ++ core/conio.inc | 2 +- core/extern.inc | 3 +++ core/extlinux.asm | 10 +--------- core/getc.inc | 3 ++- core/include/core.h | 7 +++++++ core/ldlinux.asm | 6 +++--- core/parseconfig.inc | 2 +- core/ui.inc | 2 +- 9 files changed, 21 insertions(+), 16 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index 079b4761..0710b960 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -1051,5 +1051,7 @@ err_comlarge db 'COMBOOT image too large.', CR, LF, 0 section .bss16 alignb 4 DOSErrTramp resd 33 ; Error trampolines + + global ConfigName, CurrentDirName ConfigName resb FILENAME_MAX CurrentDirName resb FILENAME_MAX diff --git a/core/conio.inc b/core/conio.inc index 5209af1c..72443e27 100644 --- a/core/conio.inc +++ b/core/conio.inc @@ -208,7 +208,7 @@ msg_viewimage: mov si,VGAFileBuf mov di,VGAFileMBuf call mangle_name - call open + call core_open jz msg_putcharnext ; Not there call vgadisplayfile ; Fall through diff --git a/core/extern.inc b/core/extern.inc index e6321d16..0599c30b 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -15,4 +15,7 @@ ; cache.c extern cache_init, get_cache_block + ; load_config.c + extern load_config + %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index bdf1cdeb..f3223e42 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -185,15 +185,7 @@ Files resb MAX_OPEN*open_file_t_size ; ; Load configuration file ; -load_config: - mov si,config_name ; Save config file name - mov di,ConfigName - call strcpy - mov dword [CurrentDirName],CUR_DIR_DWORD ; Write './',0,0 to the CurrentDirName - call build_curdir_str - - mov di,ConfigName - call open + pm_call load_config jz no_config_file ; diff --git a/core/getc.inc b/core/getc.inc index a8d54c7f..e74fa12c 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -60,7 +60,8 @@ getc_file_lg2 equ 4 ; Size of getc_file as a power of 2 ; ; close: Output: CF set if nothing open ; -open: + global core_open +core_open: call searchdir jz openfd.ret openfd: diff --git a/core/include/core.h b/core/include/core.h index 8e7cd03c..574fd7af 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -7,9 +7,16 @@ extern char core_xfer_buf[65536]; extern char core_cache_buf[65536]; +extern char CurrentDirName[]; +extern char ConfigName[]; + + /* diskstart.inc */ extern void getlinsec(void); +/* getc.inc */ +extern void core_open(void); + /* hello.c */ extern void myputs(const char*); diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 34eec933..23bc5413 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -252,17 +252,17 @@ getfattype: mov [CurrentDir],eax ; ... the current directory mov di,syslinux_cfg1 push di - call open + call core_open pop di jnz .config_open mov di,syslinux_cfg2 push di - call open + call core_open pop di jnz .config_open mov di,syslinux_cfg3 push di - call open + call core_open pop di jz no_config_file .config_open: diff --git a/core/parseconfig.inc b/core/parseconfig.inc index 02bc4bf8..aecf4638 100644 --- a/core/parseconfig.inc +++ b/core/parseconfig.inc @@ -161,7 +161,7 @@ pc_opencmd: push ax ; Function to tailcall call pc_getline mov di,MNameBuf call mangle_name - call open + call core_open jnz .ok pop ax ; Drop the successor function .ok: ret ; Tailcall if OK, error return diff --git a/core/ui.inc b/core/ui.inc index 3e42a97d..5b055364 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -237,7 +237,7 @@ show_help: ; AX = func key # (0 = F1, 9 = F10, 11 = F12) xchg di,ax cmp byte [di+NULLOFFSET],NULLFILE je short fk_nofile ; Undefined F-key - call open + call core_open jz short fk_nofile ; File not found call crlf call get_msg_file -- cgit v1.2.1 From f0b750340a1d2dac0953b185b3ef48d1dc358e76 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 13:50:48 +0800 Subject: Wrap the getlinsec function Add a new function read_sectors, the only function will call getlinsec, so we can read sectors easily by calling read_sectors function --- core/cache.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/core/cache.c b/core/cache.c index dca85a7d..ebef5569 100644 --- a/core/cache.c +++ b/core/cache.c @@ -55,19 +55,27 @@ void cache_init(com32sys_t * regs) } -void getoneblk(char *buf, uint32_t block, int block_size) +void read_sectors(char *buf, int sector_num, int sectors) { - int sec_per_block = block_size >> 9; /* 512==sector size */ - com32sys_t regs; + com32sys_t regs; - memset(®s, 0, sizeof(regs) ); + memset(®s, 0, sizeof(regs) ); + regs.eax.l = sector_num; + regs.ebp.l = sectors; + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); + + call16(getlinsec, ®s, NULL); + + memcpy(buf, core_xfer_buf, sectors << 9); +} - regs.eax.l = block * sec_per_block; - regs.ebp.l = sec_per_block; - regs.es = SEG(buf); - regs.ebx.w[0] = OFFS(buf); - call16(getlinsec, ®s, NULL); +void getoneblk(char *buf, uint32_t block, int block_size) +{ + int sec_per_block = block_size >> 9; /* 512==sector size */ + + read_sectors(buf, block * sec_per_block, sec_per_block); } -- cgit v1.2.1 From 9177573efae59513b35ac3062ccf2e305946606d Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 14:56:09 +0800 Subject: extract the geting fs information code in asm to a C function fs_init we use fs_init to initialize the fs information --- core/Makefile | 1 - core/diskstart.inc | 1 + core/ext2.c | 42 ++++++++++++++++++++++++++++++++++++++++++ core/extern.inc | 3 +++ core/extlinux.asm | 37 ++++--------------------------------- core/include/core.h | 4 ++++ 6 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 core/ext2.c diff --git a/core/Makefile b/core/Makefile index 2e28c930..c41b423b 100644 --- a/core/Makefile +++ b/core/Makefile @@ -33,7 +33,6 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ - ldlinux.bss ldlinux.sys ldlinux.bin \ extlinux.bin extlinux.bss extlinux.sys # All primary source files for the main syslinux files diff --git a/core/diskstart.inc b/core/diskstart.inc index 4b570bcc..1b4d4d64 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -96,6 +96,7 @@ superblock_len_fat32 equ $-superblock+54 zb 54 ; Maximum needed size superblock_max equ $-superblock + global SecPerClust SecPerClust equ bxSecPerClust ; ; Note we don't check the constraints above now; we did that at install diff --git a/core/ext2.c b/core/ext2.c new file mode 100644 index 00000000..26da1446 --- /dev/null +++ b/core/ext2.c @@ -0,0 +1,42 @@ +#include +#include + +#include "core.h" +#include "ext2_fs.h" + + + +/** + * init. the fs meta data, return the block size in eax + */ +void init_fs(com32sys_t *regs) +{ + + extern uint16_t ClustByteShift, ClustShift; + extern uint32_t SecPerClust, ClustSize, ClustMask; + extern uint32_t PtrsPerBlock1, PtrsPerBlock2; + extern char SuperBlock[1024]; + + struct ext2_super_block *sb; + + + /* read the super block */ + read_sectors(SuperBlock, 2, 2); + sb = (struct ext2_super_block *) SuperBlock; + + ClustByteShift = sb->s_log_block_size + 10; + ClustSize = 1 << ClustByteShift; + ClustShift = ClustByteShift - 9; + + //DescPerBlock = blk_size / ( 1 << ext2_group_desc_lg2size); + //InodePerBlock = blk_size / sb->s_inode_size; + + SecPerClust = ClustSize >> 9; + ClustMask = SecPerClust - 1; + + PtrsPerBlock1 = 1 << ( ClustByteShift - 2 ); + PtrsPerBlock2 = 1 << ( (ClustByteShift - 2) * 2); + //PtrsPerBlock3 = 1 << ( (ClustByteShift - 2) * 3); + + regs->eax.l = 9; +} diff --git a/core/extern.inc b/core/extern.inc index 0599c30b..58c5c96e 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -18,4 +18,7 @@ ; load_config.c extern load_config + ; ext2.c + extern init_fs + %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index f3223e42..0c0b404b 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -93,6 +93,8 @@ trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h section .bss16 + global SuperBlock, ClustSize, ClustMask, PtrsPerBlock1 + global PtrsPerBlock2, ClustShift, ClustByteShift SuperBlock resb 1024 ; ext2 superblock ClustSize resd 1 ; Bytes/cluster ("block") ClustMask resd 1 ; Sectors/cluster - 1 @@ -116,44 +118,13 @@ Files resb MAX_OPEN*open_file_t_size %include "cpuinit.inc" ; -; Load the real (ext2) superblock; 1024 bytes long at offset 1024 +; Initialize the ext2 fs meta data ; - mov bx,SuperBlock - mov eax,1024 >> SECTOR_SHIFT - mov bp,ax - call getlinsec - -; -; Compute some values... -; - xor edx,edx - inc edx - - ; s_log_block_size = log2(blocksize) - 10 - mov cl,[SuperBlock+s_log_block_size] - add cl,10 - mov [ClustByteShift],cl - mov eax,edx - shl eax,cl - mov [ClustSize],eax - - sub cl,SECTOR_SHIFT - mov [ClustShift],cl - shr eax,SECTOR_SHIFT - mov [SecPerClust],eax - dec eax - mov [ClustMask],eax - - add cl,SECTOR_SHIFT-2 ; 4 bytes/pointer - shl edx,cl - mov [PtrsPerBlock1],edx - shl edx,cl - mov [PtrsPerBlock2],edx + pm_call init_fs ; will return the block size shift in eax(for now, is the sector shift) ; ; Initialize the metadata cache ; - mov eax, 9 ; for now, the cache is based on sector but not block pm_call cache_init ; diff --git a/core/include/core.h b/core/include/core.h index 574fd7af..b7f7edd7 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -20,6 +20,10 @@ extern void core_open(void); /* hello.c */ extern void myputs(const char*); +/* cache.c */ +extern void read_sectors(char *, int, int); +extern void get_cache_block(com32sys_t *); + void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); -- cgit v1.2.1 From b1262eb4e50937fe43a402e748baf07d5c583a55 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 15:26:27 +0800 Subject: fix the error code style and something --- core/cache.c | 50 +++++++++++++++++++++++++------------------------- core/ext2.c | 4 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/cache.c b/core/cache.c index ebef5569..0ddf9445 100644 --- a/core/cache.c +++ b/core/cache.c @@ -29,29 +29,29 @@ static int cache_entries; */ void cache_init(com32sys_t * regs) { - struct cache_struct *prev, *cur; - char *data = core_cache_buf; - int block_size_shift = regs->eax.l; - int i; - - cache_block_size = 1 << block_size_shift; - cache_entries = sizeof(core_cache_buf) >> block_size_shift; - if (cache_entries > MAX_CACHE_ENTRIES) - cache_entries = MAX_CACHE_ENTRIES; - - cache_head.prev = &cache[cache_entries-1]; - cache_head.prev->next = &cache_head; - prev = &cache_head; - - for (i = 0; i < cache_entries; i++) { - cur = &cache[i]; - cur->block = 0; - cur->prev = prev; - prev->next = cur; - cur->data = data; - data += cache_block_size; - prev = cur++; - } + struct cache_struct *prev, *cur; + char *data = core_cache_buf; + int block_size_shift = regs->eax.l; + int i; + + cache_block_size = 1 << block_size_shift; + cache_entries = sizeof(core_cache_buf) >> block_size_shift; + if (cache_entries > MAX_CACHE_ENTRIES) + cache_entries = MAX_CACHE_ENTRIES; + + cache_head.prev = &cache[cache_entries-1]; + cache_head.prev->next = &cache_head; + prev = &cache_head; + + for (i = 0; i < cache_entries; i++) { + cur = &cache[i]; + cur->block = 0; + cur->prev = prev; + prev->next = cur; + cur->data = data; + data += cache_block_size; + prev = cur++; + } } @@ -73,9 +73,9 @@ void read_sectors(char *buf, int sector_num, int sectors) void getoneblk(char *buf, uint32_t block, int block_size) { - int sec_per_block = block_size >> 9; /* 512==sector size */ + int sec_per_block = block_size >> 9; /* 512==sector size */ - read_sectors(buf, block * sec_per_block, sec_per_block); + read_sectors(buf, block * sec_per_block, sec_per_block); } diff --git a/core/ext2.c b/core/ext2.c index 26da1446..5491f811 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -28,8 +28,8 @@ void init_fs(com32sys_t *regs) ClustSize = 1 << ClustByteShift; ClustShift = ClustByteShift - 9; - //DescPerBlock = blk_size / ( 1 << ext2_group_desc_lg2size); - //InodePerBlock = blk_size / sb->s_inode_size; + //DescPerBlock = ClustSize >> ext2_group_desc_lg2size; + //InodePerBlock = ClustSize / sb->s_inode_size; SecPerClust = ClustSize >> 9; ClustMask = SecPerClust - 1; -- cgit v1.2.1 From b18b33e0f256138220934e44d6bf9b01ab7c2213 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 3 Jun 2009 15:29:25 +0800 Subject: add ext2 fs header file --- core/ext2_fs.h | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 core/ext2_fs.h diff --git a/core/ext2_fs.h b/core/ext2_fs.h new file mode 100644 index 00000000..d579eade --- /dev/null +++ b/core/ext2_fs.h @@ -0,0 +1,252 @@ +#ifndef __EXT2_FS_H +#define __EXT2_FS_H + +#include + +#define EXT2_SUPER_MAGIC 0xEF53 + +#define EXT2_GOOD_OLD_REV 0 // The good old (original) format +#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +// Special inode numbers +#define EXT2_BAD_INO 1 // Bad blocks inode +#define EXT2_ROOT_INO 2 // Root inode +#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode +#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode +#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode +#define EXT3_JOURNAL_INO 8 // Journal inode + +// We're readonly, so we only care about incompat features. +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff + +#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) + + +/* for EXT4 extent */ +#define EXT4_EXT_MAGIC 0xf30a +#define EXT4_EXTENTS_FLAG 0x00080000 + +/* + * File types and file modes + */ +#define S_IFDIR 0040000 // Directory +#define S_IFCHR 0020000 // Character device +#define S_IFBLK 0060000 // Block device +#define S_IFREG 0100000 // Regular file +#define S_IFIFO 0010000 // FIFO +#define S_IFLNK 0120000 // Symbolic link +#define S_IFSOCK 0140000 // Socket + +#define S_IFSHIFT 12 + +#define T_IFDIR (S_IFDIR >> S_IFSHIFT) +#define T_IFCHR (S_IFCHR >> S_IFSHIFT) +#define T_IFBLK (S_IFBLK >> S_IFSHIFT) +#define T_IFREG (S_IFREG >> S_IFSHIFT) +#define T_IFIFO (S_IFIFO >> S_IFSHIFT) +#define T_IFLNK (S_IFLNK >> S_IFSHIFT) +#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) + + +#define ext2_group_desc_lg2size 5 + + + +/* + * super block structure: + * include/linux/ext2_fs.h + */ +struct ext2_super_block { + uint32_t s_inodes_count; /* Inodes count */ + uint32_t s_blocks_count; /* Blocks count */ + uint32_t s_r_blocks_count; /* Reserved blocks count */ + uint32_t s_free_blocks_count; /* Free blocks count */ + uint32_t s_free_inodes_count; /* Free inodes count */ + uint32_t s_first_data_block; /* First Data Block */ + uint32_t s_log_block_size; /* Block size */ + uint32_t s_log_frag_size; /* Fragment size */ + uint32_t s_blocks_per_group; /* # Blocks per group */ + uint32_t s_frags_per_group; /* # Fragments per group */ + uint32_t s_inodes_per_group; /* # Inodes per group */ + uint32_t s_mtime; /* Mount time */ + uint32_t s_wtime; /* Write time */ + uint16_t s_mnt_count; /* Mount count */ + int16_t s_max_mnt_count; /* Maximal mount count */ + uint16_t s_magic; /* Magic signature */ + uint16_t s_state; /* File system state */ + uint16_t s_errors; /* Behaviour when detecting errors */ + uint16_t s_minor_rev_level; + uint32_t s_lastcheck; /* time of last check */ + uint32_t s_checkinterval; /* max. time between checks */ + uint32_t s_creator_os; /* OS */ + uint32_t s_rev_level; /* Revision level */ + uint16_t s_def_resuid; /* Default uid for reserved blocks */ + uint16_t s_def_resgid; /* Default gid for reserved blocks */ + + uint32_t s_first_ino; /* First non-reserved inode */ + uint16_t s_inode_size; /* size of inode structure */ + uint16_t s_block_group_nr; /* block group # of this superblock */ + uint32_t s_feature_compat; /* compatible feature set */ + uint32_t s_feature_incompat; /* incompatible feature set */ + uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ + uint8_t s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + uint32_t s_algorithm_usage_bitmap; /* For compression */ + uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + uint8_t s_prealloc_dir_blocks; + uint16_t s_padding1; + uint32_t s_reserved[204]; /* Padding to the end of the block */ +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_super_block_size != 1024 +#error ext2_super_block definition bogus +#endif +#endif +*******************************************************************************/ + +/* + * ext2 group desc structure: + */ +struct ext2_group_desc { + uint32_t bg_block_bitmap; /* Blocks bitmap block */ + uint32_t bg_inode_bitmap; /* Inodes bitmap block */ + uint32_t bg_inode_table; /* Inodes table block */ + uint16_t bg_free_blocks_count; /* Free blocks count */ + uint16_t bg_free_inodes_count; /* Free inodes count */ + uint16_t bg_used_dirs_count; /* Directories count */ + uint16_t bg_pad; + uint32_t bg_reserved[3]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_group_desc_size != 32 +#error ext2_group_desc definition bogus +#endif +#endif +*******************************************************************************/ + + +/* + * ext2 inode structure: + */ +struct ext2_inode { + uint16_t i_mode; /* File mode */ + uint16_t i_uid; /* Owner Uid */ + uint32_t i_size; /* 4: Size in bytes */ + uint32_t i_atime; /* Access time */ + uint32_t i_ctime; /* 12: Creation time */ + uint32_t i_mtime; /* Modification time */ + uint32_t i_dtime; /* 20: Deletion Time */ + uint16_t i_gid; /* Group Id */ + uint16_t i_links_count; /* 24: Links count */ + uint32_t i_blocks; /* Blocks count */ + uint32_t i_flags; /* 32: File flags */ + uint32_t l_i_reserved1; + uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ + uint32_t i_version; /* File version (for NFS) */ + uint32_t i_file_acl; /* File ACL */ + uint32_t i_dir_acl; /* Directory ACL */ + uint32_t i_faddr; /* Fragment address */ + uint8_t l_i_frag; /* Fragment number */ + uint8_t l_i_fsize; /* Fragment size */ + uint16_t i_pad1; + uint32_t l_i_reserved2[2]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_inode_size != 128 +#error ext2_inode definition bogus +#endif +#endif +*******************************************************************************/ + + +#define EXT2_NAME_LEN 255 +struct ext2_dir_entry { + unsigned int d_inode; /* Inode number */ + unsigned short d_rec_len; /* Directory entry length */ + unsigned char d_name_len; /* Name length */ + unsigned char d_file_type; + char d_name[EXT2_NAME_LEN]; /* File name */ +}; + +/******************************************************************************* +#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) +*******************************************************************************/ + + + + + + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +struct ext4_extent { + uint32_t ee_block; /* first logical block extent covers */ + uint16_t ee_len; /* number of blocks covered by extent */ + uint16_t ee_start_hi; /* high 16 bits of physical block */ + uint32_t ee_start_lo; /* low 32 bits of physical block */ +}; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +struct ext4_extent_idx { + uint32_t ei_block; /* index covers logical blocks from 'block' */ + uint32_t ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + uint16_t ei_leaf_hi; /* high 16 bits of physical block */ + uint16_t ei_unused; +}; + +/* + * Each block (leaves and indexes), even inode-stored has header. + */ +struct ext4_extent_header { + uint16_t eh_magic; /* probably will support different formats */ + uint16_t eh_entries; /* number of valid entries */ + uint16_t eh_max; /* capacity of store in entries */ + uint16_t eh_depth; /* has tree real underlying blocks? */ + uint32_t eh_generation; /* generation of the tree */ +}; + + + +#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) +#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) + + + + + + + +/* function declartion */ +/******************************************************************************* +extern struct open_file_t * ext2_read(char *); +extern int ext2_read(struct open_file_t *, char *, int); +*******************************************************************************/ + + +#endif /* ext2_fs.h */ -- cgit v1.2.1 From 3dff5c8ba164f7c244cf72a49ac5997efe06e07a Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 4 Jun 2009 04:50:06 +0800 Subject: CORE: Add two new file, disk.c, disk.h extract the sector read functions to disk.c, and add SECTOR_SHIFT, SECTOR_SIZE stuff in the disk.h as asked by hpa. --- core/cache.c | 49 ++++++++----------------------------------------- core/disk.c | 28 ++++++++++++++++++++++++++++ core/ext2.c | 13 +++++-------- core/include/disk.h | 11 +++++++++++ 4 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 core/disk.c create mode 100644 core/include/disk.h diff --git a/core/cache.c b/core/cache.c index 0ddf9445..debd5b58 100644 --- a/core/cache.c +++ b/core/cache.c @@ -1,11 +1,11 @@ #include "core.h" #include "cache.h" - +#include "disk.h" #include #include -/* +/** * Each CachePtr contains: * - Block pointer * - LRU previous pointer @@ -15,7 +15,6 @@ * The cache buffer are pointed to by a cache_head structure. */ - static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; static int cache_block_size; static int cache_entries; @@ -55,31 +54,6 @@ void cache_init(com32sys_t * regs) } -void read_sectors(char *buf, int sector_num, int sectors) -{ - com32sys_t regs; - - memset(®s, 0, sizeof(regs) ); - regs.eax.l = sector_num; - regs.ebp.l = sectors; - regs.es = SEG(core_xfer_buf); - regs.ebx.w[0] = OFFS(core_xfer_buf); - - call16(getlinsec, ®s, NULL); - - memcpy(buf, core_xfer_buf, sectors << 9); -} - - -void getoneblk(char *buf, uint32_t block, int block_size) -{ - int sec_per_block = block_size >> 9; /* 512==sector size */ - - read_sectors(buf, block * sec_per_block, sec_per_block); -} - - - /** * get_cache_block: * @@ -132,24 +106,19 @@ void get_cache_block(com32sys_t * regs) cs = cs->prev; } - if ( i == cache_entries ) { - /* missed, so we need to load it */ - + /* missed, so we need to load it */ + if ( i == cache_entries ) { /* store it at the head of real cache */ - cs = cache_head.next; - + cs = cache_head.next; cs->block = block; getoneblk(cs->data, block, cache_block_size); missed ++; } - - /* remove cs from current position in list */ cs->prev->next = cs->next; - cs->next->prev = cs->prev; - + cs->next->prev = cs->prev; /* add to just before head node */ last = cache_head.prev; @@ -158,13 +127,11 @@ void get_cache_block(com32sys_t * regs) last->next = cs; cs->prev = last; head->prev = cs; - cs->next = head; + cs->next = head; out: - - total_read ++; - #if 0 /* testing how efficiency the cache is */ + total_read ++; if ( total_read % 5 == 0 ) printf("total_read %d\tmissed %d\n", total_read, missed); #endif diff --git a/core/disk.c b/core/disk.c new file mode 100644 index 00000000..1a25d871 --- /dev/null +++ b/core/disk.c @@ -0,0 +1,28 @@ +#include +#include +#include "core.h" +#include "disk.h" + +void read_sectors(char *buf, int sector_num, int sectors) +{ + com32sys_t regs; + + memset(®s, 0, sizeof regs); + regs.eax.l = sector_num; + regs.ebp.l = sectors; + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); + call16(getlinsec, ®s, NULL); + + memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); +} + + +void getoneblk(char *buf, uint32_t block, int block_size) +{ + int sec_per_block = block_size >> SECTOR_SHIFT; + + read_sectors(buf, block * sec_per_block, sec_per_block); +} + + diff --git a/core/ext2.c b/core/ext2.c index 5491f811..3cd2782b 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -1,7 +1,7 @@ #include #include - #include "core.h" +#include "disk.h" #include "ext2_fs.h" @@ -11,14 +11,11 @@ */ void init_fs(com32sys_t *regs) { - extern uint16_t ClustByteShift, ClustShift; extern uint32_t SecPerClust, ClustSize, ClustMask; extern uint32_t PtrsPerBlock1, PtrsPerBlock2; extern char SuperBlock[1024]; - - struct ext2_super_block *sb; - + struct ext2_super_block *sb; /* read the super block */ read_sectors(SuperBlock, 2, 2); @@ -26,17 +23,17 @@ void init_fs(com32sys_t *regs) ClustByteShift = sb->s_log_block_size + 10; ClustSize = 1 << ClustByteShift; - ClustShift = ClustByteShift - 9; + ClustShift = ClustByteShift - SECTOR_SHIFT; //DescPerBlock = ClustSize >> ext2_group_desc_lg2size; //InodePerBlock = ClustSize / sb->s_inode_size; - SecPerClust = ClustSize >> 9; + SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; PtrsPerBlock1 = 1 << ( ClustByteShift - 2 ); PtrsPerBlock2 = 1 << ( (ClustByteShift - 2) * 2); //PtrsPerBlock3 = 1 << ( (ClustByteShift - 2) * 3); - regs->eax.l = 9; + regs->eax.l = SECTOR_SHIFT; } diff --git a/core/include/disk.h b/core/include/disk.h new file mode 100644 index 00000000..e99e3cb6 --- /dev/null +++ b/core/include/disk.h @@ -0,0 +1,11 @@ +#ifndef DISK_H +#define DISK_H + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) + + +extern void read_sectors(char *, int, int); +extern void get_cache_block(com32sys_t *); + +#endif /* DISK_H */ -- cgit v1.2.1 From 922943ba67a767c61bcc839c3a762d9cabc39741 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 4 Jun 2009 05:20:05 +0800 Subject: Core: add two new data types, sector_t and block_t and fixed some errors. --- core/cache.c | 3 +-- core/cache.h | 7 ++----- core/disk.c | 4 ++-- core/include/core.h | 4 ---- core/include/disk.h | 6 ++++-- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/core/cache.c b/core/cache.c index debd5b58..2e651725 100644 --- a/core/cache.c +++ b/core/cache.c @@ -1,6 +1,5 @@ #include "core.h" #include "cache.h" -#include "disk.h" #include #include @@ -80,7 +79,7 @@ void get_cache_block(com32sys_t * regs) /* let's find it from the end, 'cause the endest is the freshest */ struct cache_struct *cs = cache_head.prev; struct cache_struct *head, *last; - uint32_t block = regs->eax.l; + block_t block = regs->eax.l; int i; static int total_read; diff --git a/core/cache.h b/core/cache.h index 666863d1..b47cc5c5 100644 --- a/core/cache.h +++ b/core/cache.h @@ -3,22 +3,19 @@ #include #include - +#include "disk.h" #define MAX_CACHE_ENTRIES 0x064 /* I'm not sure it's the max */ - - /* The cache structure */ struct cache_struct { - uint32_t block; + block_t block; struct cache_struct *prev; struct cache_struct *next; void *data; }; - /* functions defined in cache.c */ void cache_init(com32sys_t *regs); diff --git a/core/disk.c b/core/disk.c index 1a25d871..71c51470 100644 --- a/core/disk.c +++ b/core/disk.c @@ -3,7 +3,7 @@ #include "core.h" #include "disk.h" -void read_sectors(char *buf, int sector_num, int sectors) +void read_sectors(char *buf, sector_t sector_num, int sectors) { com32sys_t regs; @@ -18,7 +18,7 @@ void read_sectors(char *buf, int sector_num, int sectors) } -void getoneblk(char *buf, uint32_t block, int block_size) +void getoneblk(char *buf, block_t block, int block_size) { int sec_per_block = block_size >> SECTOR_SHIFT; diff --git a/core/include/core.h b/core/include/core.h index b7f7edd7..574fd7af 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -20,10 +20,6 @@ extern void core_open(void); /* hello.c */ extern void myputs(const char*); -/* cache.c */ -extern void read_sectors(char *, int, int); -extern void get_cache_block(com32sys_t *); - void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); diff --git a/core/include/disk.h b/core/include/disk.h index e99e3cb6..44a425f8 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -4,8 +4,10 @@ #define SECTOR_SHIFT 9 #define SECTOR_SIZE (1 << SECTOR_SHIFT) +typedef unsigned int sector_t; +typedef unsigned int block_t; -extern void read_sectors(char *, int, int); -extern void get_cache_block(com32sys_t *); +extern void read_sectors(char *, sector_t, int); +extern void getoneblk(char *, block_t, int); #endif /* DISK_H */ -- cgit v1.2.1 From e14fe0d2fac879eb01a0667ed0fde69813fd06b8 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 4 Jun 2009 06:13:50 +0800 Subject: Core: use __lowmem for sector read buffer exchange inseatd of core_xfer_buf --- core/disk.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/disk.c b/core/disk.c index 71c51470..7d2c2664 100644 --- a/core/disk.c +++ b/core/disk.c @@ -6,15 +6,26 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) { com32sys_t regs; + static __lowmem char low_buf[65536]; + /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ + int high_addr = (buf + (sectors << SECTOR_SHIFT)) > (char *)0x100000; memset(®s, 0, sizeof regs); regs.eax.l = sector_num; regs.ebp.l = sectors; - regs.es = SEG(core_xfer_buf); - regs.ebx.w[0] = OFFS(core_xfer_buf); + + if (high_addr) { + regs.es = SEG(low_buf); + regs.ebx.w[0] = OFFS(low_buf); + } else { + regs.es = SEG(buf); + regs.ebx.w[0] = OFFS(buf); + } + call16(getlinsec, ®s, NULL); - memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); + if (high_addr) + memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); } -- cgit v1.2.1 From 3b11d44b71440a9fb1d531aa1013ead118fa570f Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 4 Jun 2009 06:18:46 +0800 Subject: Core: forget to clean core_xfer_buf stuff absolutely --- core/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/disk.c b/core/disk.c index 7d2c2664..8ec880c6 100644 --- a/core/disk.c +++ b/core/disk.c @@ -25,7 +25,7 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) call16(getlinsec, ®s, NULL); if (high_addr) - memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); + memcpy(buf, low_buf, sectors << SECTOR_SHIFT); } -- cgit v1.2.1 From 1a8ca75d7590c9b709af07030a30d7d718445942 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 5 Jun 2009 07:29:20 +0800 Subject: Core: Convert linsector and open_inode function to C The two functions are converted to C. And for another thing, I find that I haven't included the load_config.c file before(my fault), so added it here. --- core/cache.c | 10 +- core/cache.h | 2 +- core/ext2.c | 352 +++++++++++++++++++++++++++++++++++++++++++++++++++-- core/extern.inc | 4 +- core/extlinux.asm | 228 +--------------------------------- core/load_config.c | 26 ++++ 6 files changed, 382 insertions(+), 240 deletions(-) create mode 100644 core/load_config.c diff --git a/core/cache.c b/core/cache.c index 2e651725..b3f23163 100644 --- a/core/cache.c +++ b/core/cache.c @@ -74,12 +74,11 @@ void cache_init(com32sys_t * regs) * @return: the data stores at gs:si * */ -void get_cache_block(com32sys_t * regs) +struct cache_struct* get_cache_block(block_t block) { /* let's find it from the end, 'cause the endest is the freshest */ struct cache_struct *cs = cache_head.prev; struct cache_struct *head, *last; - block_t block = regs->eax.l; int i; static int total_read; @@ -90,8 +89,8 @@ void get_cache_block(com32sys_t * regs) #endif if ( !block ) { - myputs("ERROR: we got a ZERO block number that's not we want!\n"); - return; + printf("ERROR: we got a ZERO block number that's not we want!\n"); + return NULL; } /* it's aleardy the freshest, so nothing we need do , just return it */ @@ -139,6 +138,5 @@ void get_cache_block(com32sys_t * regs) if ( (char *)(cs->data) > (char*)0x100000 ) printf("the buffer addres higher than 1M limit\n\r"); - regs->gs = SEG(cs->data); - regs->esi.w[0]= OFFS(cs->data); + return cs; } diff --git a/core/cache.h b/core/cache.h index b47cc5c5..65df6cdc 100644 --- a/core/cache.h +++ b/core/cache.h @@ -19,6 +19,6 @@ struct cache_struct { /* functions defined in cache.c */ void cache_init(com32sys_t *regs); -void get_cache_block(com32sys_t *regs); +struct cache_struct* get_cache_block(block_t); #endif /* cache.h */ diff --git a/core/ext2.c b/core/ext2.c index 3cd2782b..28606eea 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -1,21 +1,357 @@ #include #include +#include "cache.h" #include "core.h" #include "disk.h" #include "ext2_fs.h" +#define MAX_OPEN_LG2 6 +#define MAX_OPEN (1 << MAX_OPEN_LG2) + +/* + * File structure, This holds the information for each currently open file + */ +struct open_file_t { + uint32_t file_bytesleft; /* Number of bytes left (0 = free) */ + uint32_t file_sector; /* Next linear sector to read */ + uint32_t file_in_sec; /* Sector where inode lives */ + uint16_t file_in_off; + uint16_t file_mode; +}; + +extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; + + +extern char ThisInode[128]; +struct ext2_inode *this_inode = ThisInode; + +extern uint16_t ClustByteShift, ClustShift; +extern uint32_t SecPerClust, ClustSize, ClustMask; +extern uint32_t PtrsPerBlock1, PtrsPerBlock2; +uint32_t PtrsPerBlock3; + +int DescPerBlock, InodePerBlock; + +struct ext2_super_block *sb; + + + +/** + * allocate_file: + * + * Allocate a file structure + * + * @return: if successful return the file pointer, or return NULL + * + */ +struct open_file_t *allocate_file() +{ + struct open_file_t *file = (struct open_file_t *)Files; + int i = 0; + + for (; i < MAX_OPEN; i ++) { + if (file->file_bytesleft == 0) /* found it */ + return file; + file ++; + } + + return NULL; /* not found */ +} + + +/** + * get_group_desc: + * + * get the group's descriptor of group_num + * + * @param: group_num, the group number; + * + * @return: the pointer of the group's descriptor + * + */ +struct ext2_group_desc *get_group_desc(uint32_t group_num) +{ + block_t block_num; + uint32_t offset; + struct ext2_group_desc *desc; + struct cache_struct *cs; + + block_num = group_num / DescPerBlock; + offset = group_num % DescPerBlock; + + block_num += sb->s_first_data_block + 1; + cs = get_cache_block(block_num); + + desc = (struct ext2_group_desc *)cs->data + offset; + + return desc; +} + + +/** + * read_inode: + * + * read the right inode structure to _dst_. + * + * @param: inode_offset, the inode offset within a group; + * @prarm: dst, wher we will store the inode structure; + * @param: desc, the pointer to the group's descriptor + * @param: block, a pointer used for retruning the blk number for file structure + * @param: offset, same as block + * + */ +void read_inode(uint32_t inode_offset, + struct ext2_inode *dst, struct ext2_group_desc *desc, + block_t *block, uint32_t *offset) +{ + struct cache_struct *cs; + struct ext2_inode *inode; + + *block = inode_offset / InodePerBlock + desc->bg_inode_table; + *offset = inode_offset % InodePerBlock; + + cs = get_cache_block(*block); + + /* well, in EXT4, the inode structure usually be 256 */ + inode = (struct ext2_inode *)(cs->data + (*offset * (sb->s_inode_size))); + memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE); + + /* for file structure */ + *offset = (inode_offset * sb->s_inode_size) % ClustSize; +} + + +/** + * open_inode: + * + * open a file indicated by an inode number in INR + * + * @param : regs, regs->eax stores the inode number + * @return: a open_file_t structure pointer, stores in regs->esi + * file length in bytes, stores in regs->eax + * the first 128 bytes of the inode, stores in ThisInode + * + */ +void open_inode(com32sys_t *regs) +{ + uint32_t inr = regs->eax.l; + uint32_t file_len; + + struct open_file_t *file; + struct ext2_group_desc *desc; + + uint32_t inode_group, inode_offset; + block_t block_num; + uint32_t block_off; + + file = allocate_file(); + if (!file) + goto err; + + file->file_sector = 0; + + inr --; + inode_group = inr / sb->s_inodes_per_group; + + /* get the group desc */ + desc = get_group_desc(inode_group); + + inode_offset = inr % sb->s_inodes_per_group; + read_inode(inode_offset, this_inode, desc, &block_num, &block_off); + + /* Finally, we need to convet it to sector for now */ + file->file_in_sec = (block_num<>SECTOR_SHIFT); + file->file_in_off = block_off & (SECTOR_SIZE - 1); + file->file_mode = this_inode->i_mode; + file_len = file->file_bytesleft = this_inode->i_size; + + if (file_len == 0) + goto err; + + regs->esi.w[0] = file; + regs->eax.l = file_len; + return; + + err: + regs->eax.l = 0; +} + + + +struct ext4_extent_header * +ext4_find_leaf (struct ext4_extent_header *eh, block_t block) +{ + struct ext4_extent_idx *index; + struct cache_struct *cs; + uint64_t blk; + int i; + + while (1) { + if (eh->eh_magic != EXT4_EXT_MAGIC) + return NULL; + + /* got it */ + if (eh->eh_depth == 0) + return eh; + + index = EXT4_FIRST_INDEX(eh); + for ( i = 0; i < eh->eh_entries; i++ ) { + if ( block < index[i].ei_block ) + break; + } + if ( --i < 0 ) + return NULL; + + blk = index[i].ei_leaf_hi; + blk = (blk << 32) + index[i].ei_leaf_lo; + + /* read the blk to memeory */ + cs = get_cache_block(blk); + eh = (struct ext4_extent_header *)(cs->data); + } +} + +/* handle the ext4 extents to get the phsical block number */ +uint64_t linsector_extent(block_t block, struct ext2_inode *inode) +{ + struct ext4_extent_header *leaf; + struct ext4_extent *ext; + int i; + uint64_t start; + + leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_block,block); + if (! leaf) { + printf("ERROR, extent leaf not found\n"); + return 0; + } + + ext = EXT4_FIRST_EXTENT(leaf); + for ( i = 0; i < leaf->eh_entries; i++ ) { + if ( block < ext[i].ee_block) + break; + } + if ( --i < 0 ) { + printf("ERROR, not find the right block\n"); + return 0; + } + + + /* got it */ + block -= ext[i].ee_block; + if ( block >= ext[i].ee_len) + return 0; + + start = ext[i].ee_start_hi; + start = (start << 32) + ext[i].ee_start_lo; + + return start + block; +} + + +/** + * linsector_direct: + * + * @param: block, the block index + * @param: inode, the inode structure + * + * @return: the physic block number + */ +block_t linsector_direct(block_t block, struct ext2_inode *inode) +{ + struct cache_struct *cs; + + /* direct blocks */ + if (block < EXT2_NDIR_BLOCKS) + return inode->i_block[block]; + + + /* indirect blocks */ + block -= EXT2_NDIR_BLOCKS; + if (block < PtrsPerBlock1) { + block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; + cs = get_cache_block(ind_block); + + return ((block_t *)cs->data)[block]; + } + + /* double indirect blocks */ + block -= PtrsPerBlock1; + if (block < PtrsPerBlock2) { + block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; + cs = get_cache_block(dou_block); + + dou_block = ((block_t *)cs->data)[block / PtrsPerBlock1]; + cs = get_cache_block(dou_block); + + return ((block_t*)cs->data)[block % PtrsPerBlock1]; + } + + /* triple indirect block */ + block -= PtrsPerBlock2; + if (block < PtrsPerBlock3) { + block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; + cs = get_cache_block(tri_block); + + tri_block = ((block_t *)cs->data)[block / PtrsPerBlock2]; + cs = get_cache_block(tri_block); + + tri_block = ((block_t *)cs->data)[block % PtrsPerBlock2]; + cs = get_cache_block(tri_block); + + return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; + } + + /* File too big, can not handle */ + printf("ERROR, file too big\n"); + return 0; +} + + +/** + * linsector: + * + * Convert a linear sector index in a file to linear sector number + * + * well, alought this function converts a linear sector number to + * physic sector number, it uses block cache in the implemention. + * + * @param: lin_sector, the lineral sector index + * + * @return: physic sector number + */ +void linsector(com32sys_t *regs) +{ + sector_t lin_sector = regs->eax.l; + block_t block = lin_sector >> ClustShift; + struct ext2_inode *inode; + + /* well, this is what I think the variable this_inode used for */ + inode = this_inode; + + if (inode->i_flags & EXT4_EXTENTS_FLAG) + block = linsector_extent(block, inode); + else + block = (uint32_t)linsector_direct(block, inode); + + if (!block) { + printf("ERROR: something error happend at linsector..\n"); + regs->eax.l = 0; + return; + } + + /* finally convert it to sector */ + regs->eax.l = ((block << ClustShift) + (lin_sector & ClustMask)); +} + + /** * init. the fs meta data, return the block size in eax */ void init_fs(com32sys_t *regs) { - extern uint16_t ClustByteShift, ClustShift; - extern uint32_t SecPerClust, ClustSize, ClustMask; - extern uint32_t PtrsPerBlock1, PtrsPerBlock2; extern char SuperBlock[1024]; - struct ext2_super_block *sb; /* read the super block */ read_sectors(SuperBlock, 2, 2); @@ -25,15 +361,15 @@ void init_fs(com32sys_t *regs) ClustSize = 1 << ClustByteShift; ClustShift = ClustByteShift - SECTOR_SHIFT; - //DescPerBlock = ClustSize >> ext2_group_desc_lg2size; - //InodePerBlock = ClustSize / sb->s_inode_size; + DescPerBlock = ClustSize >> ext2_group_desc_lg2size; + InodePerBlock = ClustSize / sb->s_inode_size; SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; PtrsPerBlock1 = 1 << ( ClustByteShift - 2 ); PtrsPerBlock2 = 1 << ( (ClustByteShift - 2) * 2); - //PtrsPerBlock3 = 1 << ( (ClustByteShift - 2) * 3); + PtrsPerBlock3 = 1 << ( (ClustByteShift - 2) * 3); - regs->eax.l = SECTOR_SHIFT; + regs->eax.l = ClustByteShift; } diff --git a/core/extern.inc b/core/extern.inc index 58c5c96e..c8288fe7 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -13,12 +13,12 @@ extern hello ; cache.c - extern cache_init, get_cache_block + extern cache_init ; load_config.c extern load_config ; ext2.c - extern init_fs + extern init_fs, linsector, open_inode %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 0c0b404b..e4e0fed7 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -104,6 +104,7 @@ ClustShift resb 1 ; Shift count for sectors/cluster ClustByteShift resb 1 ; Shift count for bytes/cluster alignb open_file_t_size + global Files Files resb MAX_OPEN*open_file_t_size ; @@ -194,123 +195,11 @@ getlinsec_ext: jnz getlinsec_ext ret -; -; allocate_file: Allocate a file structure -; -; If successful: -; ZF set -; BX = file pointer -; In unsuccessful: -; ZF clear -; -allocate_file: - TRACER 'a' - push cx - mov bx,Files - mov cx,MAX_OPEN -.check: cmp dword [bx], byte 0 - je .found - add bx,open_file_t_size ; ZF = 0 - loop .check - ; ZF = 0 if we fell out of the loop -.found: pop cx - ret -; -; open_inode: -; Open a file indicated by an inode number in EAX -; -; NOTE: This file considers finding a zero-length file an -; error. This is so we don't have to deal with that special -; case elsewhere in the program (most loops have the test -; at the end). -; -; If successful: -; ZF clear -; SI = file pointer -; EAX = file length in bytes -; ThisInode = the first 128 bytes of the inode -; If unsuccessful -; ZF set -; -; Assumes CS == DS == ES. -; -open_inode.allocate_failure: - xor eax,eax - pop bx - pop di - ret - -open_inode: - push di - push bx - call allocate_file - jnz .allocate_failure - - push cx - push gs - ; First, get the appropriate inode group and index - dec eax ; There is no inode 0 - xor edx,edx - mov [bx+file_sector],edx - div dword [SuperBlock+s_inodes_per_group] - ; EAX = inode group; EDX = inode within group - push edx - ; Now, we need the block group descriptor. - ; To get that, we first need the relevant descriptor block. - - shl eax, ext2_group_desc_lg2size ; Get byte offset in desc table - xor edx,edx - div dword [ClustSize] - ; eax = block #, edx = offset in block - add eax,dword [SuperBlock+s_first_data_block] - inc eax ; s_first_data_block+1 - mov cl,[ClustShift] - shl eax,cl - push edx - shr edx,SECTOR_SHIFT - add eax,edx - pop edx - and dx,SECTOR_SIZE-1 - pm_call get_cache_block ; Get the group descriptor - add si,dx - mov esi,[gs:si+bg_inode_table] ; Get inode table block # - pop eax ; Get inode within group - movzx edx, word [SuperBlock+s_inode_size] - mul edx - ; edx:eax = byte offset in inode table - div dword [ClustSize] - ; eax = block # versus inode table, edx = offset in block - add eax,esi - shl eax,cl ; Turn into sector - push dx - shr edx,SECTOR_SHIFT - add eax,edx - mov [bx+file_in_sec],eax - pop dx - and dx,SECTOR_SIZE-1 - mov [bx+file_in_off],dx - - pm_call get_cache_block - add si,dx - mov cx,EXT2_GOOD_OLD_INODE_SIZE >> 2 - mov di,ThisInode - gs rep movsd - - mov ax,[ThisInode+i_mode] - mov [bx+file_mode],ax - mov eax,[ThisInode+i_size] - mov [bx+file_bytesleft],eax - mov si,bx - and eax,eax ; ZF clear unless zero-length file - pop gs - pop cx - pop bx - pop di - ret section .bss16 alignb 4 + global ThisInode ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode section .text16 @@ -365,7 +254,7 @@ searchdir: .open: push eax ; Save directory inode - call open_inode + pm_call open_inode jz .missing ; If error, done mov cx,[si+file_mode] @@ -635,113 +524,6 @@ kaboom2: .noreg: jmp short .noreg ; Nynorsk -; -; linsector: Convert a linear sector index in a file to a linear sector number -; EAX -> linear sector number -; DS:SI -> open_file_t -; -; Returns next sector number in EAX; CF on EOF (not an error!) -; -linsector: - push gs - push ebx - push esi - push edi - push ecx - push edx - push ebp - - push eax ; Save sector index - mov cl,[ClustShift] - shr eax,cl ; Convert to block number - push eax - mov eax,[si+file_in_sec] - mov bx,si - pm_call get_cache_block ; Get inode - add si,[bx+file_in_off] ; Get *our* inode - pop eax - lea ebx,[i_block+4*eax] - cmp eax,EXT2_NDIR_BLOCKS - jb .direct - mov ebx,i_block+4*EXT2_IND_BLOCK - sub eax,EXT2_NDIR_BLOCKS - mov ebp,[PtrsPerBlock1] - cmp eax,ebp - jb .ind1 - mov ebx,i_block+4*EXT2_DIND_BLOCK - sub eax,ebp - mov ebp,[PtrsPerBlock2] - cmp eax,ebp - jb .ind2 - mov ebx,i_block+4*EXT2_TIND_BLOCK - sub eax,ebp - -.ind3: - ; Triple indirect; eax contains the block no - ; with respect to the start of the tind area; - ; ebx contains the pointer to the tind block. - xor edx,edx - div dword [PtrsPerBlock2] - ; EAX = which dind block, EDX = pointer within dind block - push ax - shr eax,SECTOR_SHIFT-2 - mov ebp,[gs:si+bx] - shl ebp,cl - add eax,ebp - pm_call get_cache_block - pop bx - and bx,(SECTOR_SIZE >> 2)-1 - shl bx,2 - mov eax,edx ; The ind2 code wants the remainder... - -.ind2: - ; Double indirect; eax contains the block no - ; with respect to the start of the dind area; - ; ebx contains the pointer to the dind block. - xor edx,edx - div dword [PtrsPerBlock1] - ; EAX = which ind block, EDX = pointer within ind block - push ax - shr eax,SECTOR_SHIFT-2 - mov ebp,[gs:si+bx] - shl ebp,cl - add eax,ebp - pm_call get_cache_block - pop bx - and bx,(SECTOR_SIZE >> 2)-1 - shl bx,2 - mov eax,edx ; The int1 code wants the remainder... - -.ind1: - ; Single indirect; eax contains the block no - ; with respect to the start of the ind area; - ; ebx contains the pointer to the ind block. - push ax - shr eax,SECTOR_SHIFT-2 - mov ebp,[gs:si+bx] - shl ebp,cl - add eax,ebp - pm_call get_cache_block - pop bx - and bx,(SECTOR_SIZE >> 2)-1 - shl bx,2 - -.direct: - mov ebx,[gs:bx+si] ; Get the pointer - - pop eax ; Get the sector index again - shl ebx,cl ; Convert block number to sector - and eax,[ClustMask] ; Add offset within block - add eax,ebx - - pop ebp - pop edx - pop ecx - pop edi - pop esi - pop ebx - pop gs - ret ; ; getfssec: Get multiple sectors from a file @@ -774,7 +556,7 @@ getfssec: .getfragment: mov eax,[si+file_sector] ; Current start index mov edi,eax - call linsector + pm_call linsector push eax ; Fragment start sector mov edx,eax xor ebp,ebp ; Fragment sector count @@ -794,7 +576,7 @@ getfssec: inc edi ; Sector index inc edx ; Linearly next sector mov eax,edi - call linsector + pm_call linsector ; jc .do_read cmp edx,eax je .getseccnt diff --git a/core/load_config.c b/core/load_config.c new file mode 100644 index 00000000..2c81946d --- /dev/null +++ b/core/load_config.c @@ -0,0 +1,26 @@ +#include +#include + +#include "core.h" + + +void load_config(com32sys_t *regs) +{ + char *config_name = "extlinux.conf"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + *(uint32_t *)CurrentDirName = 0x00002f2e; + + regs->edi.w[0] = ConfigName; + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); + + regs->eax.w[0] = out_regs.eax.w[0]; + +#if 0 + printf("the zero flag is %s\n", regs->eax.w[0] ? \ + "CLEAR, means we found the config file" : + "SET, menas we didn't find the config file"); +#endif +} -- cgit v1.2.1 From 1be29e2cdba4e406e3a7ca78e3959caacb925e75 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 5 Jun 2009 09:29:13 +0800 Subject: Core: Convert the searchdir function to C for now, almost all the stuff related to EXT have been converted to C, and fow my (limit) test, it works well. The getfssec function haven't converted to C, because it also be called from asm file, and I find it's a bit hard to convert it to C. But however, it's my next plan. --- core/comboot.inc | 6 +- core/diskstart.inc | 1 + core/ext2.c | 317 ++++++++++++++++++++++++++++++++++++++++++++++++--- core/extern.inc | 2 +- core/extlinux.asm | 223 +----------------------------------- core/getc.inc | 2 +- core/include/core.h | 3 + core/parseconfig.inc | 2 +- core/runkernel.inc | 2 +- core/ui.inc | 2 +- 10 files changed, 315 insertions(+), 245 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index 0710b960..1cb5ac6e 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -519,7 +519,7 @@ comapi_open: mov di,InitRD call mangle_name pop ds - call searchdir + pm_call searchdir jz comapi_err mov P_EAX,eax mov P_CX,SECTOR_SIZE @@ -750,7 +750,7 @@ comapi_runkernel: mov di,KernelName call mangle_name pop ds - call searchdir + pm_call searchdir jz comapi_err ; The kernel image was found, so we can load it... @@ -906,7 +906,7 @@ comapi_opendir: mov di,InitRD call mangle_name pop ds - call searchdir + pm_call searchdir jnz comapi_err ; Didn't find a directory cmp eax,0 jz comapi_err ; Found nothing diff --git a/core/diskstart.inc b/core/diskstart.inc index 1b4d4d64..38222e00 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -489,6 +489,7 @@ ADVSectors dw 0 ; Additional sectors for ADVs LDLDwords dd 0 ; Total dwords starting at ldlinux_sys, CheckSum dd 0 ; Checksum starting at ldlinux_sys ; value = LDLINUX_MAGIC - [sum of dwords] + global CurrentDir CurrentDir dd 2 ; "Current" directory inode number (EXTLINUX) SecPtrOffset dw SectorPtrs - ldlinux_sys SecPtrCnt dw (SectorPtrsEnd - SectorPtrs) >> 2 diff --git a/core/ext2.c b/core/ext2.c index 28606eea..b7f61419 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -33,9 +33,37 @@ uint32_t PtrsPerBlock3; int DescPerBlock, InodePerBlock; -struct ext2_super_block *sb; +struct ext2_super_block *sb; +extern char trackbuf[8192]; + +#define MAX_SYMLINKS 64 +#define SYMLINK_SECTORS 2 +extern char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; + + + +/** + * strecpy: + * + * just like the function strcpy(), except it returns non-zero if overflow. + * + * well, in Syslinux, strcpy() will advance both the dst and src string pointer. + * + */ +int strecpy(char *dst, char *src, char *end) +{ + while ( *src != '\0' ) + *dst++ = *src++; + *dst = '\0'; + + if ( dst > end ) + return 1; + else + return 0; +} + /** * allocate_file: @@ -60,6 +88,21 @@ struct open_file_t *allocate_file() } +/** + * close_file: + * + * Deallocates a file structure point by FILE + * + * @param: file, the file structure we want deallocate + * + */ +void close_file(struct open_file_t *file) +{ + if (file) + file->file_bytesleft = 0; +} + + /** * get_group_desc: * @@ -127,17 +170,14 @@ void read_inode(uint32_t inode_offset, * * open a file indicated by an inode number in INR * - * @param : regs, regs->eax stores the inode number - * @return: a open_file_t structure pointer, stores in regs->esi - * file length in bytes, stores in regs->eax + * @param : inr, the inode number + * @return: a open_file_t structure pointer + * file length in bytes * the first 128 bytes of the inode, stores in ThisInode * */ -void open_inode(com32sys_t *regs) +struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) { - uint32_t inr = regs->eax.l; - uint32_t file_len; - struct open_file_t *file; struct ext2_group_desc *desc; @@ -147,7 +187,7 @@ void open_inode(com32sys_t *regs) file = allocate_file(); if (!file) - goto err; + return NULL; file->file_sector = 0; @@ -164,17 +204,12 @@ void open_inode(com32sys_t *regs) file->file_in_sec = (block_num<>SECTOR_SHIFT); file->file_in_off = block_off & (SECTOR_SIZE - 1); file->file_mode = this_inode->i_mode; - file_len = file->file_bytesleft = this_inode->i_size; - - if (file_len == 0) - goto err; + *file_len = file->file_bytesleft = this_inode->i_size; - regs->esi.w[0] = file; - regs->eax.l = file_len; - return; + if (*file_len == 0) + return NULL; - err: - regs->eax.l = 0; + return file; } @@ -345,6 +380,252 @@ void linsector(com32sys_t *regs) } +/* + * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure. + * + * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller. + */ +static inline int ext2_match_entry (const char * const name, + struct ext2_dir_entry * de) +{ + if (!de->d_inode) + return 0; + return !strncmp(name, de->d_name, de->d_name_len); +} + + +/* + * p is at least 6 bytes before the end of page + */ +inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) +{ + return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); +} + + +void getfssec_ext(char *buf, struct open_file_t *file, + int sectors, int *have_more) +{ + com32sys_t regs, out_regs; + + memset(®s, 0, sizeof regs); + memset(&out_regs, 0, sizeof out_regs); + + /* + * for now, the buf and file structure are stored at low + * address, so we can reference it safely by SEG() and + * OFFS() operation. + * + * !find we can't use SEG stuff here, say the address of buf + * is 0x800(found in debug), the addres would be broken like + * this: es = 0x80, bx = 0, while that's not the getfssec + * function need, the one that still be asm code now. + * + * so we just do like: + * regs.ebx.w[0] = buf; + */ + regs.ebx.w[0] = buf; + regs.esi.w[0] = file; + regs.ecx.w[0] = sectors; + + call16(getfssec, ®s, &out_regs); + + *have_more = 1; + + /* the file is closed ? */ + if( !out_regs.esi.w[0] ) + *have_more = 0; +} + + +/** + * find_dir_entry: + * + * find a dir entry, if find return it or return NULL + * + */ +struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) +{ + int have_more; + char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; + struct ext2_dir_entry *de; + + /* read a clust at a time */ + getfssec_ext(trackbuf, file, SecPerClust, &have_more); + de = (struct ext2_dir_entry *)trackbuf; + + while ( 1 ) { + if ( (char *)de >= (char *)EndBlock ) { + if (have_more) { + getfssec_ext(trackbuf, file,SecPerClust,&have_more); + de = (struct ext2_dir_entry *)trackbuf; + } else + return NULL; + } + + /* Zero inode == void entry */ + if ( de->d_inode == 0 ) { + de = ext2_next_entry(de); + continue; + } + + if ( ext2_match_entry (filename, de) ) { + filename += de->d_name_len; + if ( (*filename == 0) || (*filename == '/') ) + return de; /* got it */ + + /* not match, restore the filename then try next */ + filename -= de->d_name_len; + } + + de = ext2_next_entry(de); + } +} + + +char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) +{ + int flag, have_more; + + char *SymlinkTmpBuf = trackbuf; + char *lnk_end; + char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + + flag = this_inode->i_file_acl ? SecPerClust : 0; + + if ( this_inode->i_blocks == flag ) { + /* fast symlink */ + close_file(file); /* we've got all we need */ + memcpy(SymlinkTmpBuf, this_inode->i_block, file_len); + lnk_end = SymlinkTmpBuf + file_len; + + } else { + /* slow symlink */ + getfssec_ext(SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); + lnk_end = SymlinkTmpBuf + file_len; + } + + /* + * well, this happens like: + * "/boot/xxx/y/z.abc" where xxx is a symlink to "/other/here" + * so, we should get a new path name like: + * "/other/here/y/z.abc" + */ + if ( *filename != 0 ) + *lnk_end++ = '/'; + + if ( strecpy(lnk_end, filename, SymlinkTmpBufEnd) ) + return NULL; /* buffer overflow */ + + /* + * now copy it to the "real" buffer; we need to have + * two buffers so we avoid overwriting the tail on + * the next copy. + */ + strcpy(SymlinkBuf, SymlinkTmpBuf); + + /* return the new path */ + return SymlinkBuf; +} + + + + +/** + * searchdir: + * + * Search the root directory for a pre-mangle filename in FILENAME. + * + * @param: filename, the filename we want to search. + * + * @out : a file pointer + * @out : file lenght in bytes + * + */ +void searchdir(com32sys_t * regs) +{ + extern int CurrentDir; + + struct open_file_t *file; + struct ext2_dir_entry *de; + uint8_t file_mode; + uint8_t SymlinkCtr = MAX_SYMLINKS; + uint32_t inr = CurrentDir; + uint32_t ThisDir; + uint32_t file_len; + char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + + begin_path: + while ( *filename == '/' ) { /* Absolute filename */ + inr = EXT2_ROOT_INO; + filename ++; + } + open: + if ( (file = open_inode(inr, &file_len) ) == NULL ) + goto err_noclose; + + file_mode = file->file_mode >> S_IFSHIFT; + + /* It's a file */ + if ( file_mode == T_IFREG ) { + if ( *filename == '\0' ) + goto done; + else + goto err; + } + + + /* It's a directory */ + if ( file_mode == T_IFDIR ) { + ThisDir = inr; + + if ( *filename == 0 ) + goto err; + while ( *filename == '/' ) + filename ++; + + de = find_dir_entry(file, filename); + if ( !de ) + goto err; + + inr = de->d_inode; + filename += de->d_name_len; + close_file(file); + goto open; + } + + + /* + * It's a symlink. We have to determine if it's a fast symlink + * (data stored in the inode) or not (data stored as a regular + * file.) Either which way, we start from the directory + * which we just visited if relative, or from the root directory + * if absolute, and append any remaining part of the path. + */ + if ( file_mode == T_IFLNK ) { + if ( --SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) + goto err; /* too many links or symlink too long */ + + filename = do_symlink(file, file_len, filename); + if ( !filename ) + goto err_noclose;/* buffer overflow */ + + inr = ThisDir; + goto begin_path; /* we got a new path, so search it again */ + } + + /* Otherwise, something bad ... */ + err: + close_file(file); + err_noclose: + file_len = 0; + file = NULL; + done: + + regs->eax.l = file_len; + regs->esi.w[0] = file; +} + /** * init. the fs meta data, return the block size in eax diff --git a/core/extern.inc b/core/extern.inc index c8288fe7..e8e0a697 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -19,6 +19,6 @@ extern load_config ; ext2.c - extern init_fs, linsector, open_inode + extern init_fs, linsector, searchdir %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index e4e0fed7..9e9b6521 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -88,6 +88,7 @@ file_mode resw 1 ; Memory below this point is reserved for the BIOS and the MBR ; section .earlybss + global trackbuf trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h @@ -215,229 +216,12 @@ close_file: xor si,si .closed: ret -; -; searchdir: -; Search the root directory for a pre-mangled filename in DS:DI. -; -; NOTE: This file considers finding a zero-length file an -; error. This is so we don't have to deal with that special -; case elsewhere in the program (most loops have the test -; at the end). -; -; If successful: -; ZF clear -; SI = file pointer -; DX:AX = EAX = file length in bytes -; If unsuccessful -; ZF set -; -; Assumes CS == DS == ES; *** IS THIS CORRECT ***? -; -searchdir: - push bx - push cx - push bp - mov byte [SymlinkCtr],MAX_SYMLINKS - - mov eax,[CurrentDir] -.begin_path: -.leadingslash: - cmp byte [di],'/' ; Absolute filename? - jne .gotdir - mov eax,EXT2_ROOT_INO - inc di ; Skip slash - jmp .leadingslash -.gotdir: - - ; At this point, EAX contains the directory inode, - ; and DS:DI contains a pathname tail. -.open: - push eax ; Save directory inode - - pm_call open_inode - jz .missing ; If error, done - - mov cx,[si+file_mode] - shr cx,S_IFSHIFT ; Get file type - - cmp cx,T_IFDIR - je .directory - - add sp,4 ; Drop directory inode - - cmp cx,T_IFREG - je .file - cmp cx,T_IFLNK - je .symlink - - ; Otherwise, something bad... -.err: - call close_file -.err_noclose: - xor eax,eax - xor si,si - cwd ; DX <- 0 - -.done: - and eax,eax ; Set/clear ZF - pop bp - pop cx - pop bx - ret - -.missing: - add sp,4 ; Drop directory inode - jmp .done - - ; - ; It's a file. - ; -.file: - cmp byte [di],0 ; End of path? - je .done ; If so, done - jmp .err ; Otherwise, error - - ; - ; It's a directory. - ; -.directory: - pop dword [ThisDir] ; Remember what directory we're searching - - cmp byte [di],0 ; More path? - je .err ; If not, bad - -.skipslash: ; Skip redundant slashes - cmp byte [di],'/' - jne .readdir - inc di - jmp .skipslash - -.readdir: - mov cx,[SecPerClust] - push cx - shl cx,SECTOR_SHIFT - mov bx,trackbuf - add cx,bx - mov [EndBlock],cx - pop cx - push bx - call getfssec - pop bx - pushf ; Save EOF flag - push si ; Save filesystem pointer -.getent: - cmp bx,[EndBlock] - jae .endblock - - push di - cmp dword [bx+d_inode],0 ; Zero inode = void entry - je .nope - - movzx cx,byte [bx+d_name_len] - lea si,[bx+d_name] - repe cmpsb - je .maybe -.nope: - pop di - add bx,[bx+d_rec_len] - jmp .getent - -.endblock: - pop si - popf - jnc .readdir ; There is more - jmp .err ; Otherwise badness... - -.maybe: - mov eax,[bx+d_inode] - - ; Does this match the end of the requested filename? - cmp byte [di],0 - je .finish - cmp byte [di],'/' - jne .nope - - ; We found something; now we need to open the file -.finish: - pop bx ; Adjust stack (di) - pop si - call close_file ; Close directory - pop bx ; Adjust stack (flags) - jmp .open - - ; - ; It's a symlink. We have to determine if it's a fast symlink - ; (data stored in the inode) or not (data stored as a regular - ; file.) Either which way, we start from the directory - ; which we just visited if relative, or from the root directory - ; if absolute, and append any remaining part of the path. - ; -.symlink: - dec byte [SymlinkCtr] - jz .err ; Too many symlink references - - cmp eax,SYMLINK_SECTORS*SECTOR_SIZE - jae .err ; Symlink too long - - ; Computation for fast symlink, as defined by ext2/3 spec - xor ecx,ecx - cmp [ThisInode+i_file_acl],ecx - setne cl ; ECX <- i_file_acl ? 1 : 0 - cmp [ThisInode+i_blocks],ecx - jne .slow_symlink - - ; It's a fast symlink -.fast_symlink: - call close_file ; We've got all we need - mov si,ThisInode+i_block - - push di - mov di,SymlinkTmpBuf - mov ecx,eax - rep movsb - pop si - -.symlink_finish: - cmp byte [si],0 - je .no_slash - mov al,'/' - stosb -.no_slash: - mov bp,SymlinkTmpBufEnd - call strecpy - jc .err_noclose ; Buffer overflow - - ; Now copy it to the "real" buffer; we need to have - ; two buffers so we avoid overwriting the tail on the - ; next copy - mov si,SymlinkTmpBuf - mov di,SymlinkBuf - push di - call strcpy - pop di - mov eax,[ThisDir] ; Resume searching previous directory - jmp .begin_path - -.slow_symlink: - mov bx,SymlinkTmpBuf - mov cx,SYMLINK_SECTORS - call getfssec - ; The EOF closed the file - - mov si,di ; SI = filename tail - mov di,SymlinkTmpBuf - add di,ax ; AX = file length - jmp .symlink_finish - - section .bss16 alignb 4 + global SymlinkBuf SymlinkBuf resb SYMLINK_SECTORS*SECTOR_SIZE+64 -SymlinkTmpBuf equ trackbuf -SymlinkTmpBufEnd equ trackbuf+SYMLINK_SECTORS*SECTOR_SIZE+64 ThisDir resd 1 -EndBlock resw 1 -SymlinkCtr resb 1 + section .text16 ; @@ -538,6 +322,7 @@ kaboom2: ; On return ECX = number of bytes read ; All arguments are advanced to reflect data read. ; + global getfssec getfssec: push ebp push eax diff --git a/core/getc.inc b/core/getc.inc index e74fa12c..b40a4200 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -62,7 +62,7 @@ getc_file_lg2 equ 4 ; Size of getc_file as a power of 2 ; global core_open core_open: - call searchdir + pm_call searchdir jz openfd.ret openfd: push bx diff --git a/core/include/core.h b/core/include/core.h index 574fd7af..a57dac29 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -14,6 +14,9 @@ extern char ConfigName[]; /* diskstart.inc */ extern void getlinsec(void); +/* extlinux.asm */ +extern void getfssec(void); + /* getc.inc */ extern void core_open(void); diff --git a/core/parseconfig.inc b/core/parseconfig.inc index aecf4638..f8cead0a 100644 --- a/core/parseconfig.inc +++ b/core/parseconfig.inc @@ -148,7 +148,7 @@ pc_filecmd: push ax ; Function to tailcall call pc_getline mov di,MNameBuf call mangle_name - call searchdir + pm_call searchdir jnz .ok pop ax ; Drop the successor function .ok: ret ; Tailcall if OK, error return diff --git a/core/runkernel.inc b/core/runkernel.inc index 8d0f2968..71302108 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -589,7 +589,7 @@ loadinitrd: sub di,InitRDCName mov [InitRDCNameLen],di mov di,InitRD - call searchdir ; Look for it in directory + pm_call searchdir ; Look for it in directory pop edi jz .notthere diff --git a/core/ui.inc b/core/ui.inc index 5b055364..15ae4493 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -448,7 +448,7 @@ get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/e mov bx,exten_table .search_loop: push bx mov di,KernelName ; Search on disk - call searchdir + pm_call searchdir pop bx jnz kernel_good mov eax,[bx] ; Try a different extension -- cgit v1.2.1 From 1e1622cb4377e7ac5ba7b9164891df5a121c2720 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 6 Jun 2009 05:54:00 +0800 Subject: Core:EXTLINUX: convert the getfssec function to C the main file read function (getfssec) has been converted to C. Fow now, abort 90% stuff have been converted to C. The next is to clean the code and convert the rest. --- core/comboot.inc | 4 +- core/ext2.c | 164 ++++++++++++++++++++++++++++++++++++++-------------- core/extern.inc | 2 +- core/extlinux.asm | 114 ------------------------------------ core/getc.inc | 2 +- core/include/core.h | 3 - core/loadhigh.inc | 2 +- core/runkernel.inc | 2 +- 8 files changed, 128 insertions(+), 165 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index 1cb5ac6e..dee8405b 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -126,7 +126,7 @@ is_comboot_image: mov bx,100h ; Load at :0100h mov cx,10000h >> SECTOR_SHIFT ; Absolute maximum # of sectors - call getfssec + pm_call getfssec cmp ecx,65536-256-2 ; Maximum size ja comboot_too_large @@ -535,7 +535,7 @@ comapi_read: mov bx,P_BX mov si,P_SI mov cx,P_CX - call getfssec + pm_call getfssec jnc .noteof xor si,si ; SI <- 0 on EOF, CF <- 0 .noteof: mov P_SI,si diff --git a/core/ext2.c b/core/ext2.c index b7f61419..709c1f4e 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -5,9 +5,10 @@ #include "disk.h" #include "ext2_fs.h" - #define MAX_OPEN_LG2 6 #define MAX_OPEN (1 << MAX_OPEN_LG2) +#define MAX_SYMLINKS 64 +#define SYMLINK_SECTORS 2 /* * File structure, This holds the information for each currently open file @@ -21,25 +22,17 @@ struct open_file_t { }; extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; - - extern char ThisInode[128]; struct ext2_inode *this_inode = ThisInode; +struct ext2_super_block *sb; extern uint16_t ClustByteShift, ClustShift; extern uint32_t SecPerClust, ClustSize, ClustMask; extern uint32_t PtrsPerBlock1, PtrsPerBlock2; uint32_t PtrsPerBlock3; - int DescPerBlock, InodePerBlock; -struct ext2_super_block *sb; - - -extern char trackbuf[8192]; - -#define MAX_SYMLINKS 64 -#define SYMLINK_SECTORS 2 +extern char trackbuf[8192]; extern char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; @@ -355,9 +348,8 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) * * @return: physic sector number */ -void linsector(com32sys_t *regs) +sector_t linsector(sector_t lin_sector) { - sector_t lin_sector = regs->eax.l; block_t block = lin_sector >> ClustShift; struct ext2_inode *inode; @@ -371,12 +363,11 @@ void linsector(com32sys_t *regs) if (!block) { printf("ERROR: something error happend at linsector..\n"); - regs->eax.l = 0; - return; + return 0; } /* finally convert it to sector */ - regs->eax.l = ((block << ClustShift) + (lin_sector & ClustMask)); + return ((block << ClustShift) + (lin_sector & ClustMask)); } @@ -402,24 +393,122 @@ inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); } +/** + * getlinsec_ext: + * + * same as getlinsec, except load any sector from the zero + * block as all zeros; use to load any data derived from + * n ext2 block pointer, i.e. anything *except the superblock + * + */ +void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) +{ + int ext_cnt = 0; + + if ( sector < SecPerClust ) { + ext_cnt = SecPerClust - sector; + memset(buf, 0, ext_cnt << SECTOR_SHIFT); + buf += ext_cnt << SECTOR_SHIFT; + } + + sector += ext_cnt; + sector_cnt -= ext_cnt; + read_sectors(buf, sector, sector_cnt); +} + +/** + * getfssec: + * + * Get multiple sectors from a file + * + * Alought we have made the buffer data based on block size, + * we use sector for implemention; because reading multiple + * sectors (then can be multiple blocks) is what the function + * do. So, let it be based on sectors. + * + * This function can be called from C function, and either from + * ASM function. + * + * @param: ES:BX(of regs), the buffer to store data + * @param: DS:SI(of regs), the pointer to open_file_t + * @param: CX(of regs), number of sectors to read + * + * @return: ECX(of regs), number of bytes read + * + */ +void getfssec(com32sys_t *regs) +{ + int sector_left, next_sector, sector_idx; + int frag_start, con_sec_cnt; + int sectors = regs->ecx.w[0]; + int bytes_read = sectors << SECTOR_SHIFT; + char *buf; + struct open_file_t *file; + + buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); + file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); + + sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; + if ( sectors > sector_left ) + sectors = sector_left; + + while (sectors) { + /* + * get the frament + */ + sector_idx = file->file_sector; + next_sector = frag_start = linsector(sector_idx); + con_sec_cnt = 0; + + /* get the consective sectors count */ + do { + con_sec_cnt ++; + sectors --; + if ( sectors <= 0 ) + break; + + /* if sectors >= the sectors left in the 64K block, break and read */ + if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1) ) + break; + + sector_idx ++; + next_sector ++; + }while( next_sector == linsector(sectors) ); + +#if 0 + printf("You are reading stores at sector --0x%x--0x%x\n", + frag_start, frag_start + con_sec_cnt -1); +#endif + getlinsec_ext(buf, frag_start, con_sec_cnt); + buf += con_sec_cnt << 9; + file->file_sector += con_sec_cnt; /* next sector index */ + }while(sectors); + + if ( bytes_read >= file->file_bytesleft ) + bytes_read = file->file_bytesleft; + file->file_bytesleft -= bytes_read; + + regs->ecx.l = bytes_read; +} + + +/* This is the gefssec function that should be called from C function */ void getfssec_ext(char *buf, struct open_file_t *file, int sectors, int *have_more) { - com32sys_t regs, out_regs; + com32sys_t regs; memset(®s, 0, sizeof regs); - memset(&out_regs, 0, sizeof out_regs); - + /* - * for now, the buf and file structure are stored at low - * address, so we can reference it safely by SEG() and - * OFFS() operation. + * for now, even though the buf and file structure are stored + * at low address, BUT find: * - * !find we can't use SEG stuff here, say the address of buf - * is 0x800(found in debug), the addres would be broken like + * we can't use SEG stuff here, say the address of buf + * is 0x800(found in debug), the address would be broken like * this: es = 0x80, bx = 0, while that's not the getfssec - * function need, the one that still be asm code now. + * function need. * * so we just do like: * regs.ebx.w[0] = buf; @@ -427,13 +516,12 @@ void getfssec_ext(char *buf, struct open_file_t *file, regs.ebx.w[0] = buf; regs.esi.w[0] = file; regs.ecx.w[0] = sectors; - - call16(getfssec, ®s, &out_regs); + getfssec(®s); *have_more = 1; /* the file is closed ? */ - if( !out_regs.esi.w[0] ) + if( !file->file_bytesleft ) *have_more = 0; } @@ -456,11 +544,10 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) while ( 1 ) { if ( (char *)de >= (char *)EndBlock ) { - if (have_more) { - getfssec_ext(trackbuf, file,SecPerClust,&have_more); - de = (struct ext2_dir_entry *)trackbuf; - } else + if (!have_more) return NULL; + getfssec_ext(trackbuf, file,SecPerClust,&have_more); + de = (struct ext2_dir_entry *)trackbuf; } /* Zero inode == void entry */ @@ -491,8 +578,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) char *lnk_end; char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; - flag = this_inode->i_file_acl ? SecPerClust : 0; - + flag = this_inode->i_file_acl ? SecPerClust : 0; if ( this_inode->i_blocks == flag ) { /* fast symlink */ close_file(file); /* we've got all we need */ @@ -505,12 +591,6 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) lnk_end = SymlinkTmpBuf + file_len; } - /* - * well, this happens like: - * "/boot/xxx/y/z.abc" where xxx is a symlink to "/other/here" - * so, we should get a new path name like: - * "/other/here/y/z.abc" - */ if ( *filename != 0 ) *lnk_end++ = '/'; @@ -538,8 +618,8 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) * * @param: filename, the filename we want to search. * - * @out : a file pointer - * @out : file lenght in bytes + * @out : a file pointer, stores in DS:SI ( NOTE, DS == 0) + * @out : file lenght in bytes, stores in eax * */ void searchdir(com32sys_t * regs) diff --git a/core/extern.inc b/core/extern.inc index e8e0a697..255a91f8 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -19,6 +19,6 @@ extern load_config ; ext2.c - extern init_fs, linsector, searchdir + extern init_fs, searchdir, getfssec %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 9e9b6521..4a4d8ac2 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -167,36 +167,6 @@ Files resb MAX_OPEN*open_file_t_size ; %include "ui.inc" -; -; getlinsec_ext: same as getlinsec, except load any sector from the zero -; block as all zeros; use to load any data derived -; from an ext2 block pointer, i.e. anything *except the -; superblock.* -; -getonesec_ext: - mov bp,1 - -getlinsec_ext: - cmp eax,[SecPerClust] - jae getlinsec ; Nothing fancy - - ; If we get here, at least part of what we want is in the - ; zero block. Zero one sector at a time and loop. - push eax - push cx - xchg di,bx - xor eax,eax - mov cx,SECTOR_SIZE >> 2 - rep stosd - xchg di,bx - pop cx - pop eax - inc eax - dec bp - jnz getlinsec_ext - ret - - section .bss16 alignb 4 @@ -309,90 +279,6 @@ kaboom2: -; -; getfssec: Get multiple sectors from a file -; -; Same as above, except SI is a pointer to a open_file_t -; -; ES:BX -> Buffer -; DS:SI -> Pointer to open_file_t -; CX -> Sector count (0FFFFh = until end of file) -; Must not exceed the ES segment -; Returns CF=1 on EOF (not necessarily error) -; On return ECX = number of bytes read -; All arguments are advanced to reflect data read. -; - global getfssec -getfssec: - push ebp - push eax - push edx - push edi - - movzx ecx,cx - push ecx ; Sectors requested read - mov eax,[si+file_bytesleft] - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - cmp ecx,eax ; Number of sectors left - jbe .lenok - mov cx,ax -.lenok: -.getfragment: - mov eax,[si+file_sector] ; Current start index - mov edi,eax - pm_call linsector - push eax ; Fragment start sector - mov edx,eax - xor ebp,ebp ; Fragment sector count -.getseccnt: - inc bp - dec cx - jz .do_read - xor eax,eax - mov ax,es - shl ax,4 - add ax,bx ; Now DI = how far into 64K block we are - not ax ; Bytes left in 64K block - inc eax - shr eax,SECTOR_SHIFT ; Sectors left in 64K block - cmp bp,ax - jnb .do_read ; Unless there is at least 1 more sector room... - inc edi ; Sector index - inc edx ; Linearly next sector - mov eax,edi - pm_call linsector - ; jc .do_read - cmp edx,eax - je .getseccnt -.do_read: - pop eax ; Linear start sector - pushad - call getlinsec_ext - popad - push bp - shl bp,9 - add bx,bp ; Adjust buffer pointer - pop bp - add [si+file_sector],ebp ; Next sector index - jcxz .done - jnz .getfragment - ; Fall through -.done: - pop ecx ; Sectors requested read - shl ecx,SECTOR_SHIFT - sub [si+file_bytesleft],ecx - jnbe .noteof ; CF=0 in this case - add ecx,[si+file_bytesleft] ; Actual number of bytes read - call close_file - stc ; We hit EOF -.noteof: - pop edi - pop edx - pop eax - pop ebp - ret - build_curdir_str: ret diff --git a/core/getc.inc b/core/getc.inc index b40a4200..a8b49549 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -136,7 +136,7 @@ getc: mov [di+gc_bufbytes],si ; In case SI == 0 jz .empty mov cx,bytes_per_getc >> SECTOR_SHIFT - call getfssec + pm_call getfssec mov [di+gc_bufbytes],cx mov [di+gc_file],si jcxz .empty diff --git a/core/include/core.h b/core/include/core.h index a57dac29..574fd7af 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -14,9 +14,6 @@ extern char ConfigName[]; /* diskstart.inc */ extern void getlinsec(void); -/* extlinux.asm */ -extern void getfssec(void); - /* getc.inc */ extern void core_open(void); diff --git a/core/loadhigh.inc b/core/loadhigh.inc index 5c9969f6..63ab0010 100644 --- a/core/loadhigh.inc +++ b/core/loadhigh.inc @@ -69,7 +69,7 @@ load_high: push edi ; Target buffer mov cx,ax xor bx,bx ; ES:0 - call getfssec ; Load the data into xfer_buf_seg + pm_call getfssec ; Load the data into xfer_buf_seg pop edi ; Target buffer pushf ; EOF status lea ebx,[edi+ecx] ; End of data diff --git a/core/runkernel.inc b/core/runkernel.inc index 71302108..65c19932 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -58,7 +58,7 @@ is_linux_kernel: mov cx,8000h >> SECTOR_SHIFT ; Half a moby (32K) xor bx,bx pop si ; file pointer - call getfssec + pm_call getfssec cmp cx,1024 jb kernel_corrupt cmp word [es:bs_bootsign],0AA55h -- cgit v1.2.1 From 7a7f69e1524d7e1ee3c6a9e9d56428edaf785e3d Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 6 Jun 2009 06:04:16 +0800 Subject: Core: move close_file function in getc.inc because (I think) all the close_file are the same. --- core/extlinux.asm | 12 ------------ core/getc.inc | 13 +++++++++++++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/extlinux.asm b/core/extlinux.asm index 4a4d8ac2..55ae3631 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -173,18 +173,6 @@ Files resb MAX_OPEN*open_file_t_size global ThisInode ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode - section .text16 -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -close_file: - and si,si - jz .closed - mov dword [si],0 ; First dword == file_bytesleft - xor si,si -.closed: ret section .bss16 alignb 4 diff --git a/core/getc.inc b/core/getc.inc index a8b49549..0aa140b9 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -87,6 +87,19 @@ openfd: xor ax,ax ; ZF <- 1 pop bx ret + +; +; close_file: +; Deallocates a file structure (pointer in SI) +; Assumes CS == DS. +; +close_file: + and si,si + jz .closed + mov dword [si],0 ; First dword == file_bytesleft + xor si,si +.closed: ret + getc: push bx -- cgit v1.2.1 From bd8a47b12aa5d10d99147b75f1bb80d6bf07d48e Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 7 Jun 2009 06:44:06 +0800 Subject: Core:EXTLINUX: convert mangle name to C --- core/comboot.inc | 6 +++--- core/conio.inc | 2 +- core/ext2.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ core/extern.inc | 2 +- core/extlinux.asm | 49 ------------------------------------------------- core/parseconfig.inc | 10 +++++----- core/runkernel.inc | 2 +- core/ui.inc | 2 +- 8 files changed, 56 insertions(+), 61 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index dee8405b..8a7d95c4 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -517,7 +517,7 @@ comapi_open: mov ds,P_ES mov si,P_SI mov di,InitRD - call mangle_name + pm_call mangle_name pop ds pm_call searchdir jz comapi_err @@ -748,7 +748,7 @@ comapi_runkernel: mov ds,P_DS mov si,P_SI mov di,KernelName - call mangle_name + pm_call mangle_name pop ds pm_call searchdir jz comapi_err @@ -904,7 +904,7 @@ comapi_opendir: mov ds,P_ES mov si,P_SI mov di,InitRD - call mangle_name + pm_call mangle_name pop ds pm_call searchdir jnz comapi_err ; Didn't find a directory diff --git a/core/conio.inc b/core/conio.inc index 72443e27..835359fb 100644 --- a/core/conio.inc +++ b/core/conio.inc @@ -207,7 +207,7 @@ msg_viewimage: mov byte [si],0 ; Zero-terminate filename mov si,VGAFileBuf mov di,VGAFileMBuf - call mangle_name + pm_call mangle_name call core_open jz msg_putcharnext ; Not there call vgadisplayfile diff --git a/core/ext2.c b/core/ext2.c index 709c1f4e..835b3ffc 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -5,6 +5,8 @@ #include "disk.h" #include "ext2_fs.h" +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define MAX_OPEN_LG2 6 #define MAX_OPEN (1 << MAX_OPEN_LG2) #define MAX_SYMLINKS 64 @@ -96,6 +98,48 @@ void close_file(struct open_file_t *file) } +/** + * mangle_name: + * + * Mangle a filename pointed to by DS:SI(of regs) into a + * buffer pointed to by ES:DI(of regs); ends on encountering + * any whitespace. + * + */ +void mangle_name(com32sys_t *regs) +{ + char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); + char *p = dst; + int i = FILENAME_MAX -1; + + while(*src > ' ') { + if ( *src == '/' ) { + if ( *(src+1) == '/' ) { + src ++; + i --; + continue; + } + } + i --; + *dst++ = *src++; + } + + while ( 1 ) { + if ( dst >= p ) + break; + if ( *(dst-1) != '/' ) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i -- ) + *dst++ = '\0'; +} + /** * get_group_desc: * diff --git a/core/extern.inc b/core/extern.inc index 255a91f8..086f1dd9 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -19,6 +19,6 @@ extern load_config ; ext2.c - extern init_fs, searchdir, getfssec + extern init_fs, searchdir, getfssec, mangle_name %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 55ae3631..741566c1 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -183,55 +183,6 @@ ThisDir resd 1 section .text16 ; -; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace. -; DI is preserved. -; -; This verifies that a filename is < FILENAME_MAX characters, -; doesn't contain whitespace, zero-pads the output buffer, -; and removes redundant slashes, -; so "repe cmpsb" can do a compare, and the -; path-searching routine gets a bit of an easier job. -; -; FIX: we may want to support \-escapes here (and this would -; be the place.) -; -mangle_name: - push di - push bx - xor ax,ax - mov cx,FILENAME_MAX-1 - mov bx,di - -.mn_loop: - lodsb - cmp al,' ' ; If control or space, end - jna .mn_end - cmp al,ah ; Repeated slash? - je .mn_skip - xor ah,ah - cmp al,'/' - jne .mn_ok - mov ah,al -.mn_ok stosb -.mn_skip: loop .mn_loop -.mn_end: - cmp bx,di ; At the beginning of the buffer? - jbe .mn_zero - cmp byte [di-1],'/' ; Terminal slash? - jne .mn_zero -.mn_kill: dec di ; If so, remove it - inc cx - jmp short .mn_end -.mn_zero: - inc cx ; At least one null byte - xor ax,ax ; Zero-fill name - rep stosb - pop bx - pop di - ret ; Done - -; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled ; filename to the conventional representation. This is needed ; for the BOOT_IMAGE= parameter for the kernel. diff --git a/core/parseconfig.inc b/core/parseconfig.inc index f8cead0a..37091c99 100644 --- a/core/parseconfig.inc +++ b/core/parseconfig.inc @@ -104,7 +104,7 @@ pc_kernel: cmp byte [VKernel],0 mov [VKernelBuf+vk_type],al call pc_getline mov di,VKernelBuf+vk_rname - call mangle_name + pm_call mangle_name .err: ret ; @@ -147,7 +147,7 @@ pc_setint16: pc_filecmd: push ax ; Function to tailcall call pc_getline mov di,MNameBuf - call mangle_name + pm_call mangle_name pm_call searchdir jnz .ok pop ax ; Drop the successor function @@ -160,7 +160,7 @@ pc_filecmd: push ax ; Function to tailcall pc_opencmd: push ax ; Function to tailcall call pc_getline mov di,MNameBuf - call mangle_name + pm_call mangle_name call core_open jnz .ok pop ax ; Drop the successor function @@ -289,7 +289,7 @@ pc_serial: call getint pc_filename: push ax call pc_getline pop di - call mangle_name ; Mangle file name + pm_call mangle_name ; Mangle file name ret ; @@ -314,7 +314,7 @@ pc_label: call commit_vk ; Commit any current vkernel mov byte [VKernel],1 ; We've seen a "label" statement mov si,VKernelBuf+vk_vname ; By default, rname == mangled vname mov di,VKernelBuf+vk_rname - call mangle_name + pm_call mangle_name mov si,AppendBuf ; Default append==global append mov di,VKernelBuf+vk_append mov cx,[AppendLen] diff --git a/core/runkernel.inc b/core/runkernel.inc index 65c19932..f44e8b35 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -538,7 +538,7 @@ parse_load_initrd: push di mov di,InitRD ; Target buffer for mangled name - call mangle_name + pm_call mangle_name pop di call loadinitrd diff --git a/core/ui.inc b/core/ui.inc index 15ae4493..508a6f28 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -318,7 +318,7 @@ load_kernel: ; Load the kernel now mov si,command_line mov di,KernelName push si - call mangle_name + pm_call mangle_name pop si ; ; Fast-forward to first option (we start over from the beginning, since -- cgit v1.2.1 From ed632dd30b6d49e80ddf4320b7646782567e9c8f Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 7 Jun 2009 07:43:32 +0800 Subject: Core:EXTLINUX: clean the code --- core/cache.c | 14 +++++----- core/ext2.c | 90 ++++++++++++++++++++++++++++++------------------------------ 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/core/cache.c b/core/cache.c index b3f23163..41984203 100644 --- a/core/cache.c +++ b/core/cache.c @@ -88,24 +88,24 @@ struct cache_struct* get_cache_block(block_t block) printf("we are looking for cache of %d\n", block); #endif - if ( !block ) { + if (!block) { printf("ERROR: we got a ZERO block number that's not we want!\n"); return NULL; } /* it's aleardy the freshest, so nothing we need do , just return it */ - if ( cs->block == block ) + if (cs->block == block) goto out; - for ( i = 0; i < cache_entries; i ++ ) { - if ( cs->block == block ) + for (i = 0; i < cache_entries; i ++) { + if (cs->block == block) break; else cs = cs->prev; } /* missed, so we need to load it */ - if ( i == cache_entries ) { + if (i == cache_entries) { /* store it at the head of real cache */ cs = cache_head.next; cs->block = block; @@ -130,12 +130,12 @@ struct cache_struct* get_cache_block(block_t block) out: #if 0 /* testing how efficiency the cache is */ total_read ++; - if ( total_read % 5 == 0 ) + if (total_read % 5 == 0) printf("total_read %d\tmissed %d\n", total_read, missed); #endif /* in fact, that would never be happened */ - if ( (char *)(cs->data) > (char*)0x100000 ) + if ((char *)(cs->data) > (char*)0x100000) printf("the buffer addres higher than 1M limit\n\r"); return cs; diff --git a/core/ext2.c b/core/ext2.c index 835b3ffc..657acc0e 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -49,11 +49,11 @@ extern char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; */ int strecpy(char *dst, char *src, char *end) { - while ( *src != '\0' ) + while (*src != '\0') *dst++ = *src++; *dst = '\0'; - if ( dst > end ) + if (dst > end) return 1; else return 0; @@ -114,8 +114,8 @@ void mangle_name(com32sys_t *regs) int i = FILENAME_MAX -1; while(*src > ' ') { - if ( *src == '/' ) { - if ( *(src+1) == '/' ) { + if (*src == '/') { + if (*(src+1) == '/') { src ++; i --; continue; @@ -125,10 +125,10 @@ void mangle_name(com32sys_t *regs) *dst++ = *src++; } - while ( 1 ) { - if ( dst >= p ) + while (1) { + if (dst == p) break; - if ( *(dst-1) != '/' ) + if (*(dst-1) != '/') break; dst --; @@ -136,7 +136,7 @@ void mangle_name(com32sys_t *regs) } i ++; - for (; i > 0; i -- ) + for (; i > 0; i --) *dst++ = '\0'; } @@ -268,11 +268,11 @@ ext4_find_leaf (struct ext4_extent_header *eh, block_t block) return eh; index = EXT4_FIRST_INDEX(eh); - for ( i = 0; i < eh->eh_entries; i++ ) { - if ( block < index[i].ei_block ) + for (i = 0; i < eh->eh_entries; i++) { + if (block < index[i].ei_block) break; } - if ( --i < 0 ) + if (--i < 0) return NULL; blk = index[i].ei_leaf_hi; @@ -299,11 +299,11 @@ uint64_t linsector_extent(block_t block, struct ext2_inode *inode) } ext = EXT4_FIRST_EXTENT(leaf); - for ( i = 0; i < leaf->eh_entries; i++ ) { - if ( block < ext[i].ee_block) + for (i = 0; i < leaf->eh_entries; i++) { + if (block < ext[i].ee_block) break; } - if ( --i < 0 ) { + if (--i < 0) { printf("ERROR, not find the right block\n"); return 0; } @@ -311,7 +311,7 @@ uint64_t linsector_extent(block_t block, struct ext2_inode *inode) /* got it */ block -= ext[i].ee_block; - if ( block >= ext[i].ee_len) + if (block >= ext[i].ee_len) return 0; start = ext[i].ee_start_hi; @@ -449,7 +449,7 @@ void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) { int ext_cnt = 0; - if ( sector < SecPerClust ) { + if (sector < SecPerClust) { ext_cnt = SecPerClust - sector; memset(buf, 0, ext_cnt << SECTOR_SHIFT); buf += ext_cnt << SECTOR_SHIFT; @@ -493,7 +493,7 @@ void getfssec(com32sys_t *regs) file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; - if ( sectors > sector_left ) + if (sectors > sector_left) sectors = sector_left; while (sectors) { @@ -508,16 +508,16 @@ void getfssec(com32sys_t *regs) do { con_sec_cnt ++; sectors --; - if ( sectors <= 0 ) + if (sectors <= 0) break; /* if sectors >= the sectors left in the 64K block, break and read */ - if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1) ) + if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1)) break; sector_idx ++; next_sector ++; - }while( next_sector == linsector(sectors) ); + }while(next_sector == linsector(sectors)); #if 0 printf("You are reading stores at sector --0x%x--0x%x\n", @@ -528,7 +528,7 @@ void getfssec(com32sys_t *regs) file->file_sector += con_sec_cnt; /* next sector index */ }while(sectors); - if ( bytes_read >= file->file_bytesleft ) + if (bytes_read >= file->file_bytesleft) bytes_read = file->file_bytesleft; file->file_bytesleft -= bytes_read; @@ -565,7 +565,7 @@ void getfssec_ext(char *buf, struct open_file_t *file, *have_more = 1; /* the file is closed ? */ - if( !file->file_bytesleft ) + if(!file->file_bytesleft) *have_more = 0; } @@ -586,8 +586,8 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) getfssec_ext(trackbuf, file, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; - while ( 1 ) { - if ( (char *)de >= (char *)EndBlock ) { + while (1) { + if ((char *)de >= (char *)EndBlock) { if (!have_more) return NULL; getfssec_ext(trackbuf, file,SecPerClust,&have_more); @@ -595,14 +595,14 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) } /* Zero inode == void entry */ - if ( de->d_inode == 0 ) { + if (de->d_inode == 0) { de = ext2_next_entry(de); continue; } - if ( ext2_match_entry (filename, de) ) { + if (ext2_match_entry (filename, de)) { filename += de->d_name_len; - if ( (*filename == 0) || (*filename == '/') ) + if ((*filename == 0) || (*filename == '/')) return de; /* got it */ /* not match, restore the filename then try next */ @@ -623,7 +623,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; flag = this_inode->i_file_acl ? SecPerClust : 0; - if ( this_inode->i_blocks == flag ) { + if (this_inode->i_blocks == flag) { /* fast symlink */ close_file(file); /* we've got all we need */ memcpy(SymlinkTmpBuf, this_inode->i_block, file_len); @@ -635,10 +635,10 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) lnk_end = SymlinkTmpBuf + file_len; } - if ( *filename != 0 ) + if (*filename != 0) *lnk_end++ = '/'; - if ( strecpy(lnk_end, filename, SymlinkTmpBufEnd) ) + if (strecpy(lnk_end, filename, SymlinkTmpBufEnd)) return NULL; /* buffer overflow */ /* @@ -662,7 +662,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) * * @param: filename, the filename we want to search. * - * @out : a file pointer, stores in DS:SI ( NOTE, DS == 0) + * @out : a file pointer, stores in DS:SI (NOTE, DS == 0) * @out : file lenght in bytes, stores in eax * */ @@ -680,19 +680,19 @@ void searchdir(com32sys_t * regs) char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); begin_path: - while ( *filename == '/' ) { /* Absolute filename */ + while (*filename == '/') { /* Absolute filename */ inr = EXT2_ROOT_INO; filename ++; } open: - if ( (file = open_inode(inr, &file_len) ) == NULL ) + if ((file = open_inode(inr, &file_len)) == NULL) goto err_noclose; file_mode = file->file_mode >> S_IFSHIFT; /* It's a file */ - if ( file_mode == T_IFREG ) { - if ( *filename == '\0' ) + if (file_mode == T_IFREG) { + if (*filename == '\0') goto done; else goto err; @@ -700,16 +700,16 @@ void searchdir(com32sys_t * regs) /* It's a directory */ - if ( file_mode == T_IFDIR ) { + if (file_mode == T_IFDIR) { ThisDir = inr; - if ( *filename == 0 ) + if (*filename == 0) goto err; - while ( *filename == '/' ) + while (*filename == '/') filename ++; de = find_dir_entry(file, filename); - if ( !de ) + if (!de) goto err; inr = de->d_inode; @@ -726,12 +726,12 @@ void searchdir(com32sys_t * regs) * which we just visited if relative, or from the root directory * if absolute, and append any remaining part of the path. */ - if ( file_mode == T_IFLNK ) { - if ( --SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) + if (file_mode == T_IFLNK) { + if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) goto err; /* too many links or symlink too long */ filename = do_symlink(file, file_len, filename); - if ( !filename ) + if (!filename) goto err_noclose;/* buffer overflow */ inr = ThisDir; @@ -772,9 +772,9 @@ void init_fs(com32sys_t *regs) SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; - PtrsPerBlock1 = 1 << ( ClustByteShift - 2 ); - PtrsPerBlock2 = 1 << ( (ClustByteShift - 2) * 2); - PtrsPerBlock3 = 1 << ( (ClustByteShift - 2) * 3); + PtrsPerBlock1 = 1 << (ClustByteShift - 2); + PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2); + PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3); regs->eax.l = ClustByteShift; } -- cgit v1.2.1 From b3325d1ef92e9cfd172581d734122be9e00ff638 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 9 Jun 2009 09:25:42 +0800 Subject: Core:EXTLINUX: fix bug with lots of dots and searchdir The bug hpa said in the email that prints lots of dots when loading a kernel fixed. And with my test, I found that the searchdir couldn't return correctly while not find what we wanna find.(In asm, the asm code use ZF flag to test if we successed. And I thought regs->esi.w[0] = file(be zero on fail) will set ZF flag). Well, It's a good thing that I found the reg structure has the eflags filed. then it works; nice thing! --- core/ext2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/ext2.c b/core/ext2.c index 657acc0e..cc60bf9b 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -528,8 +528,10 @@ void getfssec(com32sys_t *regs) file->file_sector += con_sec_cnt; /* next sector index */ }while(sectors); - if (bytes_read >= file->file_bytesleft) + if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; + regs->esi.w[0] = NULL; /* do close the file for asm function*/ + } file->file_bytesleft -= bytes_read; regs->ecx.l = bytes_read; @@ -744,6 +746,7 @@ void searchdir(com32sys_t * regs) err_noclose: file_len = 0; file = NULL; + regs->eflags.l |= EFLAGS_ZF; done: regs->eax.l = file_len; -- cgit v1.2.1 From 5bae1d2de9f1f271750d9c0479ec5a68effa2da6 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 10 Jun 2009 06:05:04 +0800 Subject: Core:EXTLINUX: clean the WARNINGs --- core/ext2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index cc60bf9b..7980930b 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -25,7 +25,7 @@ struct open_file_t { extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; extern char ThisInode[128]; -struct ext2_inode *this_inode = ThisInode; +struct ext2_inode *this_inode = (struct ext2_inode *)ThisInode; struct ext2_super_block *sb; extern uint16_t ClustByteShift, ClustShift; @@ -530,7 +530,7 @@ void getfssec(com32sys_t *regs) if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; - regs->esi.w[0] = NULL; /* do close the file for asm function*/ + regs->esi.w[0] = 0; /* do close the file for asm function*/ } file->file_bytesleft -= bytes_read; @@ -559,8 +559,8 @@ void getfssec_ext(char *buf, struct open_file_t *file, * so we just do like: * regs.ebx.w[0] = buf; */ - regs.ebx.w[0] = buf; - regs.esi.w[0] = file; + regs.ebx.w[0] = OFFS_WRT(buf, 0); + regs.esi.w[0] = OFFS_WRT(file, 0); regs.ecx.w[0] = sectors; getfssec(®s); @@ -677,7 +677,7 @@ void searchdir(com32sys_t * regs) uint8_t file_mode; uint8_t SymlinkCtr = MAX_SYMLINKS; uint32_t inr = CurrentDir; - uint32_t ThisDir; + uint32_t ThisDir = CurrentDir; uint32_t file_len; char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); @@ -750,7 +750,7 @@ void searchdir(com32sys_t * regs) done: regs->eax.l = file_len; - regs->esi.w[0] = file; + regs->esi.w[0] = OFFS_WRT(file, 0); } -- cgit v1.2.1 From 03fa0653f5546b01c793126359bb8e56838e711c Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 11 Jun 2009 10:47:04 +0800 Subject: Core: add the skeleton fo VFS-like system Two new files added; they are: fs.h defines some basic vfs objects fs.c defines the basic functions Note: for now, it's just a skeleton, in another word, it can't compiled. --- core/fs.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ core/include/fs.h | 76 +++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 core/fs.c create mode 100644 core/include/fs.h diff --git a/core/fs.c b/core/fs.c new file mode 100644 index 00000000..f0946900 --- /dev/null +++ b/core/fs.c @@ -0,0 +1,123 @@ +#include +#include +#include "fs.h" +#include "cache.h" + + +/* The this pointer */ +struct fs_info *this_fs; +struct fs_info fs; +struct device dev; + + +void load_config(com32sys_t *regs) +{ + this_fs->fs_ops->load_config(regs); +} + +void mangle_name(com32sys_t *regs) +{ + char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); + + this_fs->fs_ops->mangle_name(dst, src); +} + +/**** +void unmangle_name(com32sys_t *regs) +{ + +} +****/ + +void getfssec(com32sys_t *regs) +{ + int sectors; + int have_more; + uint32_t bytes_read; + char *buf; + struct file file; + + sectors = regs->ecx.w[0]; + buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); + file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); + file.fs = this_fs; + + bytes_read = this_fs->fs_ops->getfssec(buf, file.open_file, sectors, &have_more); + + /* if we reach the EOF, set the si to be NULL */ + if (!have_more) + regs->esi.w[0] = 0; + + regs->ecx.l = bytes_read; +} + + +void searchdir(com32sys_t *regs) +{ + char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + struct file file; + + memset(&file, 0, sizeof file); + file.fs = this_fs; + + this_fs->fs_ops->searchdir(filename, &file); + regs->esi.w[0] = OFFS_WRT(file.open_file, 0); + regs->eax.l = file.file_len; +} + +/* + * initialize the device structure + */ +void device_init(struct device *dev, uint8_t drive_num, + uint8_t type, sector_t offset) +{ + dev->device_number = drive_num; + dev->part_start = offset; + dev->type = type; + + /* + * check if we use cache or not, for now I just know ISO fs + * does not use the cache, and I hope the USE_CACHE can detect + * it correctly. + * + */ + if ( USE_CACHE(dev->device_number) ) { + static __lowmem char cache_buf[65536]; + dev->cache_data = cache_buf; + } else + dev->cache_data = NULL; + + /* I just considered the floppy and disk now */ + dev->read_sectors = read_sectors; +} + + +/* + * it will do: + * initialize the device structure; + * set up the vfs fs structure; + * invoke the fs-specific init function; + * finally, initialize the cache + * + */ +void fs_init(com32sys_t *regs) +{ + int blk_shift; + struct fs_ops *ops = (struct fs_ops*)regs->eax.l; + + device_init(&dev, regs->edx.b[0], regs->edx.b[1], regs->ecx.l); + + /* set up the fs stucture */ + fs.fs_name = ops->fs_name; + fs.fs_ops = ops; + fs.fs_dev = &dev; + this_fs = &fs; + + /* invoke the fs-specific init code */ + blk_shift = fs.fs_ops->fs_init(); + + /* initialize the cache */ + if (dev.cache_data) + cache_init(&dev, blk_shift); +} diff --git a/core/include/fs.h b/core/include/fs.h new file mode 100644 index 00000000..6805b3b9 --- /dev/null +++ b/core/include/fs.h @@ -0,0 +1,76 @@ +#ifndef FS_H +#define FS_H + +#include +#include "core.h" +#include "disk.h" + +#define USE_CACHE(device_num) (device_num > 0x00 && device_num < 0xfe) + + +struct fs_info { + char *fs_name; + struct fs_ops *fs_ops; + struct device *fs_dev; +}; + +struct file{ + void* open_file; /* points to the fs-specific open_file_t */ + struct fs_info *fs; + uint32_t file_len; +}; + + +struct fs_ops { + /* in fact, we use fs_ops structure to find the right fs */ + char *fs_name; + + int (*fs_init)(void); + void (*searchdir)(char *, struct file *); + uint32_t (*getfssec)(char *, void * , int, int *); + void (*mangle_name)(char *, char *); + void (*unmangle_name)(void); + void (*load_config)(com32sys_t *); +}; + +//enum dev_type {CHS, EDD}; + +/* + * Struct device should have all the information about a specific disk + * structure, and contain either a pointer to the metadata cache or + * actually contain the cache itself. + * + * All the information in this case is stuff like BIOS device number, + * type of access (CHS, EDD, ...), geometry, partition offset, and + * sector size. + * + * It would be usefull and much easier to implement the C version getlinsec + * later(I have not much time to implement it now, so I will leave it for + * a while, maybe a long while). + */ +struct device { + /* the device numger (in BIOS style ) */ + uint8_t device_number; + + /* type of access (CHS or EDD ) */ + uint8_t type; + + /* the sector size, 512B for disk and floppy, 2048B for CD */ + uint16_t sector_size; + + /* the start address of this partition(in sectors) */ + sector_t part_start; + + void (*read_sectors)(char *, sector_t, int ); + + /* + * I think we still need the cache_data filed here, 'cause hpa said + * different device has diffrent cache buffer + */ + void *cache_data; + struct cache_struct *cache_head; +}; + + + +#endif /* FS_H */ -- cgit v1.2.1 From 543c6543392cc81f9f35904c7b814112b2eb5b97 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 11 Jun 2009 15:54:43 +0800 Subject: Core: make vfs do the work it works, but it broke somewhere; it can't display the menu correctly. --- core/cache.c | 66 +++++++++++------- core/cache.h | 9 +-- core/diskstart.inc | 28 +++++++- core/ext2.c | 191 +++++++++++++++++++++++++++-------------------------- core/extern.inc | 10 +-- core/extlinux.asm | 15 ----- core/fs.c | 74 +++++++++++++++++---- core/include/fs.h | 17 +++-- core/load_config.c | 26 -------- 9 files changed, 242 insertions(+), 194 deletions(-) delete mode 100644 core/load_config.c diff --git a/core/cache.c b/core/cache.c index 41984203..b0fbee7e 100644 --- a/core/cache.c +++ b/core/cache.c @@ -14,10 +14,6 @@ * The cache buffer are pointed to by a cache_head structure. */ -static struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; -static int cache_block_size; -static int cache_entries; - /** * cache_init: * @@ -25,29 +21,30 @@ static int cache_entries; * regs->eax.l stores the block size(in bits not bytes) * */ -void cache_init(com32sys_t * regs) +void cache_init(struct device *dev, int block_size_shift) { struct cache_struct *prev, *cur; - char *data = core_cache_buf; - int block_size_shift = regs->eax.l; + char *data = dev->cache_data; + static __lowmem struct cache_struct cache_head, cache[MAX_CACHE_ENTRIES]; int i; + + dev->cache_head = &cache_head; + dev->cache_block_size = 1 << block_size_shift; + dev->cache_entries = dev->cache_size >> block_size_shift; + if (dev->cache_entries > MAX_CACHE_ENTRIES) + dev->cache_entries = MAX_CACHE_ENTRIES; - cache_block_size = 1 << block_size_shift; - cache_entries = sizeof(core_cache_buf) >> block_size_shift; - if (cache_entries > MAX_CACHE_ENTRIES) - cache_entries = MAX_CACHE_ENTRIES; - - cache_head.prev = &cache[cache_entries-1]; + cache_head.prev = &cache[dev->cache_entries-1]; cache_head.prev->next = &cache_head; prev = &cache_head; - for (i = 0; i < cache_entries; i++) { + for (i = 0; i < dev->cache_entries; i++) { cur = &cache[i]; cur->block = 0; cur->prev = prev; prev->next = cur; cur->data = data; - data += cache_block_size; + data += dev->cache_block_size; prev = cur++; } } @@ -74,10 +71,10 @@ void cache_init(com32sys_t * regs) * @return: the data stores at gs:si * */ -struct cache_struct* get_cache_block(block_t block) +struct cache_struct* get_cache_block(struct device *dev, block_t block) { /* let's find it from the end, 'cause the endest is the freshest */ - struct cache_struct *cs = cache_head.prev; + struct cache_struct *cs = dev->cache_head->prev; struct cache_struct *head, *last; int i; @@ -97,7 +94,7 @@ struct cache_struct* get_cache_block(block_t block) if (cs->block == block) goto out; - for (i = 0; i < cache_entries; i ++) { + for (i = 0; i < dev->cache_entries; i ++) { if (cs->block == block) break; else @@ -105,11 +102,11 @@ struct cache_struct* get_cache_block(block_t block) } /* missed, so we need to load it */ - if (i == cache_entries) { + if (i == dev->cache_entries) { /* store it at the head of real cache */ - cs = cache_head.next; + cs = dev->cache_head->next; cs->block = block; - getoneblk(cs->data, block, cache_block_size); + getoneblk(cs->data, block, dev->cache_block_size); missed ++; } @@ -119,8 +116,8 @@ struct cache_struct* get_cache_block(block_t block) cs->next->prev = cs->prev; /* add to just before head node */ - last = cache_head.prev; - head = &cache_head; + last = dev->cache_head->prev; + head = dev->cache_head; last->next = cs; cs->prev = last; @@ -128,15 +125,34 @@ struct cache_struct* get_cache_block(block_t block) cs->next = head; out: -#if 0 /* testing how efficiency the cache is */ total_read ++; +#if 0 /* testing how efficiency the cache is */ if (total_read % 5 == 0) printf("total_read %d\tmissed %d\n", total_read, missed); #endif /* in fact, that would never be happened */ if ((char *)(cs->data) > (char*)0x100000) - printf("the buffer addres higher than 1M limit\n\r"); + printf("the buffer addres higher than 1M limit\n"); return cs; } + + +/** + * Just print the sector, and according the LRU algorithm, + * Left most value is the most least secotr, and Right most + * value is the most Recent sector. I see it's a Left Right Used + * (LRU) algorithm; Just kidding:) + */ +void print_cache(struct device *dev) +{ + int i = 0; + struct cache_struct *cs = dev->cache_head; + for (; i < dev->cache_entries; i++) { + cs = cs->next; + printf("%d(%p) ", cs->block, cs->data); + } + + printf("\n"); +} diff --git a/core/cache.h b/core/cache.h index 65df6cdc..7518bc84 100644 --- a/core/cache.h +++ b/core/cache.h @@ -4,8 +4,9 @@ #include #include #include "disk.h" +#include "fs.h" -#define MAX_CACHE_ENTRIES 0x064 /* I'm not sure it's the max */ +#define MAX_CACHE_ENTRIES 0x10 /* I find even this is enough:) */ /* The cache structure */ struct cache_struct { @@ -17,8 +18,8 @@ struct cache_struct { /* functions defined in cache.c */ -void cache_init(com32sys_t *regs); - -struct cache_struct* get_cache_block(block_t); +void cache_init(struct device *, int); +struct cache_struct* get_cache_block(struct device *, block_t); +void print_cache(struct device *); #endif /* cache.h */ diff --git a/core/diskstart.inc b/core/diskstart.inc index 38222e00..a08aa281 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -706,6 +706,30 @@ expand_super: stosd ; Store expanded byte loop .loop + ; -; Fall through to the mainline code... -; +; Common initialization code +; +%include "init.inc" +%include "cpuinit.inc" + + +%if IS_PXELINUX + extern pxe_fs_ops + mov eax,pxe_fs_ops +%else + %if IS_EXTLINUX + extern ext2_fs_ops + mov eax,ext2_fs_ops + %elif IS_SYSLINUX + extern vfat_fs_ops + mov eax,vfat_fs_ops + %elif IS_ISOLINUX + extern iso_fs_ops + mov eax,iso_fs_ops + %endif + mov dl,[DriveNumber] + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] +%endif + pm_call fs_init diff --git a/core/ext2.c b/core/ext2.c index 7980930b..b89541c4 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -4,6 +4,7 @@ #include "core.h" #include "disk.h" #include "ext2_fs.h" +#include "fs.h" #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) @@ -106,10 +107,8 @@ void close_file(struct open_file_t *file) * any whitespace. * */ -void mangle_name(com32sys_t *regs) +void ext2_mangle_name(char *dst, char *src) { - char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); char *p = dst; int i = FILENAME_MAX -1; @@ -150,7 +149,7 @@ void mangle_name(com32sys_t *regs) * @return: the pointer of the group's descriptor * */ -struct ext2_group_desc *get_group_desc(uint32_t group_num) +struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) { block_t block_num; uint32_t offset; @@ -161,7 +160,7 @@ struct ext2_group_desc *get_group_desc(uint32_t group_num) offset = group_num % DescPerBlock; block_num += sb->s_first_data_block + 1; - cs = get_cache_block(block_num); + cs = get_cache_block(fs->fs_dev, block_num); desc = (struct ext2_group_desc *)cs->data + offset; @@ -181,7 +180,7 @@ struct ext2_group_desc *get_group_desc(uint32_t group_num) * @param: offset, same as block * */ -void read_inode(uint32_t inode_offset, +void read_inode(struct fs_info *fs, uint32_t inode_offset, struct ext2_inode *dst, struct ext2_group_desc *desc, block_t *block, uint32_t *offset) { @@ -191,7 +190,7 @@ void read_inode(uint32_t inode_offset, *block = inode_offset / InodePerBlock + desc->bg_inode_table; *offset = inode_offset % InodePerBlock; - cs = get_cache_block(*block); + cs = get_cache_block(fs->fs_dev, *block); /* well, in EXT4, the inode structure usually be 256 */ inode = (struct ext2_inode *)(cs->data + (*offset * (sb->s_inode_size))); @@ -213,7 +212,7 @@ void read_inode(uint32_t inode_offset, * the first 128 bytes of the inode, stores in ThisInode * */ -struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) +struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) { struct open_file_t *file; struct ext2_group_desc *desc; @@ -232,10 +231,10 @@ struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) inode_group = inr / sb->s_inodes_per_group; /* get the group desc */ - desc = get_group_desc(inode_group); + desc = get_group_desc(fs, inode_group); inode_offset = inr % sb->s_inodes_per_group; - read_inode(inode_offset, this_inode, desc, &block_num, &block_off); + read_inode(fs, inode_offset, this_inode, desc, &block_num, &block_off); /* Finally, we need to convet it to sector for now */ file->file_in_sec = (block_num<>SECTOR_SHIFT); @@ -252,7 +251,7 @@ struct open_file_t * open_inode(uint32_t inr, uint32_t *file_len) struct ext4_extent_header * -ext4_find_leaf (struct ext4_extent_header *eh, block_t block) +ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) { struct ext4_extent_idx *index; struct cache_struct *cs; @@ -279,20 +278,20 @@ ext4_find_leaf (struct ext4_extent_header *eh, block_t block) blk = (blk << 32) + index[i].ei_leaf_lo; /* read the blk to memeory */ - cs = get_cache_block(blk); + cs = get_cache_block(fs->fs_dev, blk); eh = (struct ext4_extent_header *)(cs->data); } } /* handle the ext4 extents to get the phsical block number */ -uint64_t linsector_extent(block_t block, struct ext2_inode *inode) +uint64_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct ext4_extent_header *leaf; struct ext4_extent *ext; int i; uint64_t start; - leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_block,block); + leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); if (! leaf) { printf("ERROR, extent leaf not found\n"); return 0; @@ -329,7 +328,7 @@ uint64_t linsector_extent(block_t block, struct ext2_inode *inode) * * @return: the physic block number */ -block_t linsector_direct(block_t block, struct ext2_inode *inode) +block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct cache_struct *cs; @@ -342,7 +341,7 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= EXT2_NDIR_BLOCKS; if (block < PtrsPerBlock1) { block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; - cs = get_cache_block(ind_block); + cs = get_cache_block(fs->fs_dev, ind_block); return ((block_t *)cs->data)[block]; } @@ -351,10 +350,10 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= PtrsPerBlock1; if (block < PtrsPerBlock2) { block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; - cs = get_cache_block(dou_block); + cs = get_cache_block(fs->fs_dev, dou_block); dou_block = ((block_t *)cs->data)[block / PtrsPerBlock1]; - cs = get_cache_block(dou_block); + cs = get_cache_block(fs->fs_dev, dou_block); return ((block_t*)cs->data)[block % PtrsPerBlock1]; } @@ -363,13 +362,13 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) block -= PtrsPerBlock2; if (block < PtrsPerBlock3) { block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); tri_block = ((block_t *)cs->data)[block / PtrsPerBlock2]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); tri_block = ((block_t *)cs->data)[block % PtrsPerBlock2]; - cs = get_cache_block(tri_block); + cs = get_cache_block(fs->fs_dev, tri_block); return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; } @@ -392,7 +391,7 @@ block_t linsector_direct(block_t block, struct ext2_inode *inode) * * @return: physic sector number */ -sector_t linsector(sector_t lin_sector) +sector_t linsector(struct fs_info *fs, sector_t lin_sector) { block_t block = lin_sector >> ClustShift; struct ext2_inode *inode; @@ -401,9 +400,9 @@ sector_t linsector(sector_t lin_sector) inode = this_inode; if (inode->i_flags & EXT4_EXTENTS_FLAG) - block = linsector_extent(block, inode); + block = linsector_extent(fs, block, inode); else - block = (uint32_t)linsector_direct(block, inode); + block = (uint32_t)linsector_direct(fs, block, inode); if (!block) { printf("ERROR: something error happend at linsector..\n"); @@ -480,17 +479,13 @@ void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) * @return: ECX(of regs), number of bytes read * */ -void getfssec(com32sys_t *regs) +uint32_t ext2_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) { int sector_left, next_sector, sector_idx; int frag_start, con_sec_cnt; - int sectors = regs->ecx.w[0]; int bytes_read = sectors << SECTOR_SHIFT; - char *buf; - struct open_file_t *file; - - buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); - file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); + struct open_file_t *file = (struct open_file_t *)open_file; sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; if (sectors > sector_left) @@ -501,7 +496,7 @@ void getfssec(com32sys_t *regs) * get the frament */ sector_idx = file->file_sector; - next_sector = frag_start = linsector(sector_idx); + next_sector = frag_start = linsector(fs, sector_idx); con_sec_cnt = 0; /* get the consective sectors count */ @@ -517,7 +512,7 @@ void getfssec(com32sys_t *regs) sector_idx ++; next_sector ++; - }while(next_sector == linsector(sectors)); + }while(next_sector == linsector(fs, sectors)); #if 0 printf("You are reading stores at sector --0x%x--0x%x\n", @@ -528,49 +523,17 @@ void getfssec(com32sys_t *regs) file->file_sector += con_sec_cnt; /* next sector index */ }while(sectors); - if (bytes_read >= file->file_bytesleft) { + if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; - regs->esi.w[0] = 0; /* do close the file for asm function*/ - } + *have_more = 0; + } else + *have_more = 1; file->file_bytesleft -= bytes_read; - - regs->ecx.l = bytes_read; -} - - -/* This is the gefssec function that should be called from C function */ -void getfssec_ext(char *buf, struct open_file_t *file, - int sectors, int *have_more) -{ - com32sys_t regs; - - memset(®s, 0, sizeof regs); - - /* - * for now, even though the buf and file structure are stored - * at low address, BUT find: - * - * we can't use SEG stuff here, say the address of buf - * is 0x800(found in debug), the address would be broken like - * this: es = 0x80, bx = 0, while that's not the getfssec - * function need. - * - * so we just do like: - * regs.ebx.w[0] = buf; - */ - regs.ebx.w[0] = OFFS_WRT(buf, 0); - regs.esi.w[0] = OFFS_WRT(file, 0); - regs.ecx.w[0] = sectors; - getfssec(®s); - - *have_more = 1; - - /* the file is closed ? */ - if(!file->file_bytesleft) - *have_more = 0; + return bytes_read; } - + + /** * find_dir_entry: @@ -578,21 +541,21 @@ void getfssec_ext(char *buf, struct open_file_t *file, * find a dir entry, if find return it or return NULL * */ -struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) +struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) { int have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; struct ext2_dir_entry *de; /* read a clust at a time */ - getfssec_ext(trackbuf, file, SecPerClust, &have_more); + ext2_getfssec(fs, trackbuf, file, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; while (1) { if ((char *)de >= (char *)EndBlock) { if (!have_more) return NULL; - getfssec_ext(trackbuf, file,SecPerClust,&have_more); + ext2_getfssec(fs, trackbuf, file,SecPerClust,&have_more); de = (struct ext2_dir_entry *)trackbuf; } @@ -616,7 +579,8 @@ struct ext2_dir_entry* find_dir_entry(struct open_file_t *file, char *filename) } -char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) +char* do_symlink(struct fs_info *fs, struct open_file_t *file, + uint32_t file_len, char *filename) { int flag, have_more; @@ -633,7 +597,7 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) } else { /* slow symlink */ - getfssec_ext(SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); + ext2_getfssec(fs, SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); lnk_end = SymlinkTmpBuf + file_len; } @@ -668,29 +632,28 @@ char* do_symlink(struct open_file_t *file, uint32_t file_len, char *filename) * @out : file lenght in bytes, stores in eax * */ -void searchdir(com32sys_t * regs) +void ext2_searchdir(char *filename, struct file *file) { extern int CurrentDir; - struct open_file_t *file; + struct open_file_t *open_file; struct ext2_dir_entry *de; uint8_t file_mode; uint8_t SymlinkCtr = MAX_SYMLINKS; uint32_t inr = CurrentDir; uint32_t ThisDir = CurrentDir; uint32_t file_len; - char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); - + begin_path: while (*filename == '/') { /* Absolute filename */ inr = EXT2_ROOT_INO; filename ++; } open: - if ((file = open_inode(inr, &file_len)) == NULL) + if ((open_file = open_inode(file->fs, inr, &file_len)) == NULL) goto err_noclose; - file_mode = file->file_mode >> S_IFSHIFT; + file_mode = open_file->file_mode >> S_IFSHIFT; /* It's a file */ if (file_mode == T_IFREG) { @@ -710,13 +673,13 @@ void searchdir(com32sys_t * regs) while (*filename == '/') filename ++; - de = find_dir_entry(file, filename); + de = find_dir_entry(file->fs, open_file, filename); if (!de) goto err; inr = de->d_inode; filename += de->d_name_len; - close_file(file); + close_file(open_file); goto open; } @@ -732,7 +695,7 @@ void searchdir(com32sys_t * regs) if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) goto err; /* too many links or symlink too long */ - filename = do_symlink(file, file_len, filename); + filename = do_symlink(file->fs, open_file, file_len, filename); if (!filename) goto err_noclose;/* buffer overflow */ @@ -742,22 +705,52 @@ void searchdir(com32sys_t * regs) /* Otherwise, something bad ... */ err: - close_file(file); + close_file(open_file); err_noclose: file_len = 0; - file = NULL; - regs->eflags.l |= EFLAGS_ZF; + open_file = NULL; done: - regs->eax.l = file_len; - regs->esi.w[0] = OFFS_WRT(file, 0); + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 1 + if (open_file) { + printf("file bytesleft: %d\n", open_file->file_bytesleft); + printf("file sector : %d\n", open_file->file_sector); + printf("file in sector: %d\n", open_file->file_in_sec); + printf("file offsector: %d\n", open_file->file_in_off); + } +#endif + +} + +void ext2_load_config(com32sys_t *regs) +{ + char *config_name = "extlinux.conf"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + *(uint32_t *)CurrentDirName = 0x00002f2e; + + regs->edi.w[0] = ConfigName; + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); + + regs->eax.w[0] = out_regs.eax.w[0]; + +#if 0 + printf("the zero flag is %s\n", regs->eax.w[0] ? \ + "CLEAR, means we found the config file" : + "SET, menas we didn't find the config file"); +#endif } /** - * init. the fs meta data, return the block size in eax + * init. the fs meta data, return the block size bits. */ -void init_fs(com32sys_t *regs) +int ext2_fs_init(void) { extern char SuperBlock[1024]; @@ -779,5 +772,15 @@ void init_fs(com32sys_t *regs) PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2); PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3); - regs->eax.l = ClustByteShift; + return ClustByteShift; } + +const struct fs_ops ext2_fs_ops = { + .fs_name = "ext2", + .fs_init = ext2_fs_init, + .searchdir = ext2_searchdir, + .getfssec = ext2_getfssec, + .mangle_name = ext2_mangle_name, + .unmangle_name = NULL, + .load_config = ext2_load_config +}; diff --git a/core/extern.inc b/core/extern.inc index 086f1dd9..fdbe2643 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -12,13 +12,7 @@ ; hello.c extern hello - ; cache.c - extern cache_init - - ; load_config.c - extern load_config - - ; ext2.c - extern init_fs, searchdir, getfssec, mangle_name + ; fs.c + extern fs_init, searchdir, getfssec, mangle_name, load_config %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 741566c1..be256cf5 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -113,21 +113,6 @@ Files resb MAX_OPEN*open_file_t_size ; %include "diskstart.inc" -; -; Common initialization code -; -%include "init.inc" -%include "cpuinit.inc" - -; -; Initialize the ext2 fs meta data -; - pm_call init_fs ; will return the block size shift in eax(for now, is the sector shift) - -; -; Initialize the metadata cache -; - pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more diff --git a/core/fs.c b/core/fs.c index f0946900..18f03377 100644 --- a/core/fs.c +++ b/core/fs.c @@ -4,7 +4,7 @@ #include "cache.h" -/* The this pointer */ +/* The this fs pointer */ struct fs_info *this_fs; struct fs_info fs; struct device dev; @@ -43,7 +43,7 @@ void getfssec(com32sys_t *regs) file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); file.fs = this_fs; - bytes_read = this_fs->fs_ops->getfssec(buf, file.open_file, sectors, &have_more); + bytes_read = this_fs->fs_ops->getfssec(file.fs, buf, file.open_file, sectors, &have_more); /* if we reach the EOF, set the si to be NULL */ if (!have_more) @@ -58,33 +58,68 @@ void searchdir(com32sys_t *regs) char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); struct file file; + printf("filename: %s\n", filename); + memset(&file, 0, sizeof file); file.fs = this_fs; this_fs->fs_ops->searchdir(filename, &file); regs->esi.w[0] = OFFS_WRT(file.open_file, 0); regs->eax.l = file.file_len; + if (!file.file_len) + regs->eflags.l |= EFLAGS_ZF; +} + +/* + * well, I find that in the diskstart.inc, there's no room fow us to + * get the edd check result, so we implement a new one here. + */ +uint8_t detect_edd(uint8_t device_num) +{ + com32sys_t iregs, oregs; + + /* Sending int 13h func 41h to query EBIOS information */ + memset(&iregs, 0, sizeof iregs); + memset(&oregs, 0, sizeof oregs); + + /* Get EBIOS support */ + iregs.eax.w[0] = 0x4100; + iregs.ebx.w[0] = 0x55aa; + iregs.edx.b[0] = device_num; + iregs.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &iregs, &oregs); + + /* Detecting EDD support */ + if (!(oregs.eflags.l & EFLAGS_CF) && + oregs.ebx.w[0] == 0xaa55 && (oregs.ecx.b[0] & 1)) + return 1; + else + return 0; } /* * initialize the device structure */ -void device_init(struct device *dev, uint8_t drive_num, - uint8_t type, sector_t offset) +void device_init(struct device *dev, uint8_t device_num, sector_t offset) { - dev->device_number = drive_num; + dev->device_number = device_num; dev->part_start = offset; - dev->type = type; - + + dev->type = detect_edd(device_num); + /* * check if we use cache or not, for now I just know ISO fs * does not use the cache, and I hope the USE_CACHE can detect * it correctly. * - */ + */ if ( USE_CACHE(dev->device_number) ) { - static __lowmem char cache_buf[65536]; - dev->cache_data = cache_buf; + /* I can't use __lowmem here, 'cause it will cause the error: + "auxseg/lowmem region collides with xfer_buf_seg" */ + //static __lowmem char cache_buf[65536]; + dev->cache_data = core_cache_buf; + dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; @@ -93,6 +128,17 @@ void device_init(struct device *dev, uint8_t drive_num, } +/* debug function */ +void dump_dev(struct device *dev) +{ + printf("device type:%s\n", dev->type ? "CHS" : "EDD"); + printf("cache_data: %p\n", dev->cache_data); + printf("cache_head: %p\n", dev->cache_head); + printf("cache_block_size: %d\n", dev->cache_block_size); + printf("cache_entries: %d\n", dev->cache_entries); + printf("cache_size: %d\n", dev->cache_size); +} + /* * it will do: * initialize the device structure; @@ -106,7 +152,7 @@ void fs_init(com32sys_t *regs) int blk_shift; struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - device_init(&dev, regs->edx.b[0], regs->edx.b[1], regs->ecx.l); + device_init(&dev, regs->edx.b[0], regs->ecx.l); /* set up the fs stucture */ fs.fs_name = ops->fs_name; @@ -115,9 +161,9 @@ void fs_init(com32sys_t *regs) this_fs = &fs; /* invoke the fs-specific init code */ - blk_shift = fs.fs_ops->fs_init(); - + blk_shift = fs.fs_ops->fs_init(); + /* initialize the cache */ if (dev.cache_data) - cache_init(&dev, blk_shift); + cache_init(&dev, blk_shift); } diff --git a/core/include/fs.h b/core/include/fs.h index 6805b3b9..0cb1bfc6 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -5,7 +5,8 @@ #include "core.h" #include "disk.h" -#define USE_CACHE(device_num) (device_num > 0x00 && device_num < 0xfe) +/* I don't know it's right or not */ +#define USE_CACHE(device_num) (device_num >= 0x00 && device_num < 0xfe) struct fs_info { @@ -27,13 +28,13 @@ struct fs_ops { int (*fs_init)(void); void (*searchdir)(char *, struct file *); - uint32_t (*getfssec)(char *, void * , int, int *); + uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); void (*mangle_name)(char *, char *); void (*unmangle_name)(void); void (*load_config)(com32sys_t *); }; -//enum dev_type {CHS, EDD}; +enum dev_type {CHS, EDD}; /* * Struct device should have all the information about a specific disk @@ -65,10 +66,14 @@ struct device { /* * I think we still need the cache_data filed here, 'cause hpa said - * different device has diffrent cache buffer + * different device has diffrent cache buffer, and the following filed + * are quite for cache parts. */ - void *cache_data; - struct cache_struct *cache_head; + char* cache_data; + struct cache_struct *cache_head; + uint16_t cache_block_size; + uint16_t cache_entries; + uint32_t cache_size; }; diff --git a/core/load_config.c b/core/load_config.c deleted file mode 100644 index 2c81946d..00000000 --- a/core/load_config.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -#include "core.h" - - -void load_config(com32sys_t *regs) -{ - char *config_name = "extlinux.conf"; - com32sys_t out_regs; - - strcpy(ConfigName, config_name); - *(uint32_t *)CurrentDirName = 0x00002f2e; - - regs->edi.w[0] = ConfigName; - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); - - regs->eax.w[0] = out_regs.eax.w[0]; - -#if 0 - printf("the zero flag is %s\n", regs->eax.w[0] ? \ - "CLEAR, means we found the config file" : - "SET, menas we didn't find the config file"); -#endif -} -- cgit v1.2.1 From e717ad300fae15ac8357c67fad90c0cdcb191b96 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 12 Jun 2009 06:51:10 +0800 Subject: Core: fix the menu display error Well, it's a 'bug' that can be fixed easily fixed, that's just disable the debug output. vesamenu.c32 will be messed up with the outputs. --- core/ext2.c | 2 +- core/fs.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index b89541c4..f6217b87 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -714,7 +714,7 @@ void ext2_searchdir(char *filename, struct file *file) file->file_len = file_len; file->open_file = (void*)open_file; -#if 1 +#if 0 if (open_file) { printf("file bytesleft: %d\n", open_file->file_bytesleft); printf("file sector : %d\n", open_file->file_sector); diff --git a/core/fs.c b/core/fs.c index 18f03377..cbb20800 100644 --- a/core/fs.c +++ b/core/fs.c @@ -57,8 +57,10 @@ void searchdir(com32sys_t *regs) { char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); struct file file; - + +#if 0 printf("filename: %s\n", filename); +#endif memset(&file, 0, sizeof file); file.fs = this_fs; -- cgit v1.2.1 From e67a28c273880755946de097a24bf6d739bd3c5a Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 12 Jun 2009 15:45:52 +0800 Subject: Core: fix the not found error when type the kernel name without the extent. it will not clear the zf flag when not found the right file, so it will give the next file search(searching for a different filename extentsion the wrong answer, so we need do it after every file searching. well, in fact we should use EAX(the file lenght in bytes) or si(the open_file_t structure pointer) to indicate if we have successfully found the file or not. --- core/fs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/fs.c b/core/fs.c index cbb20800..617e3e5e 100644 --- a/core/fs.c +++ b/core/fs.c @@ -68,7 +68,9 @@ void searchdir(com32sys_t *regs) this_fs->fs_ops->searchdir(filename, &file); regs->esi.w[0] = OFFS_WRT(file.open_file, 0); regs->eax.l = file.file_len; - if (!file.file_len) + if (file.file_len) + regs->eflags.l &= ~EFLAGS_ZF; + else regs->eflags.l |= EFLAGS_ZF; } -- cgit v1.2.1 From 8732ef9b7c9ded79c525ac50932660e73dff7cc0 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 13 Jun 2009 05:56:55 +0800 Subject: Core:EXTLINUX: move the header file in core into core/include --- core/cache.h | 25 ----- core/ext2_fs.h | 252 ------------------------------------------------- core/include/cache.h | 25 +++++ core/include/ext2_fs.h | 252 +++++++++++++++++++++++++++++++++++++++++++++++++ core/types.h | 17 ---- 5 files changed, 277 insertions(+), 294 deletions(-) delete mode 100644 core/cache.h delete mode 100644 core/ext2_fs.h create mode 100644 core/include/cache.h create mode 100644 core/include/ext2_fs.h delete mode 100644 core/types.h diff --git a/core/cache.h b/core/cache.h deleted file mode 100644 index 7518bc84..00000000 --- a/core/cache.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _CACHE_H -#define _CACHE_H - -#include -#include -#include "disk.h" -#include "fs.h" - -#define MAX_CACHE_ENTRIES 0x10 /* I find even this is enough:) */ - -/* The cache structure */ -struct cache_struct { - block_t block; - struct cache_struct *prev; - struct cache_struct *next; - void *data; -}; - - -/* functions defined in cache.c */ -void cache_init(struct device *, int); -struct cache_struct* get_cache_block(struct device *, block_t); -void print_cache(struct device *); - -#endif /* cache.h */ diff --git a/core/ext2_fs.h b/core/ext2_fs.h deleted file mode 100644 index d579eade..00000000 --- a/core/ext2_fs.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef __EXT2_FS_H -#define __EXT2_FS_H - -#include - -#define EXT2_SUPER_MAGIC 0xEF53 - -#define EXT2_GOOD_OLD_REV 0 // The good old (original) format -#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes -#define EXT2_GOOD_OLD_INODE_SIZE 128 - -// Special inode numbers -#define EXT2_BAD_INO 1 // Bad blocks inode -#define EXT2_ROOT_INO 2 // Root inode -#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode -#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode -#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode -#define EXT3_JOURNAL_INO 8 // Journal inode - -// We're readonly, so we only care about incompat features. -#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 -#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 -#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 -#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - -#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) - - -/* for EXT4 extent */ -#define EXT4_EXT_MAGIC 0xf30a -#define EXT4_EXTENTS_FLAG 0x00080000 - -/* - * File types and file modes - */ -#define S_IFDIR 0040000 // Directory -#define S_IFCHR 0020000 // Character device -#define S_IFBLK 0060000 // Block device -#define S_IFREG 0100000 // Regular file -#define S_IFIFO 0010000 // FIFO -#define S_IFLNK 0120000 // Symbolic link -#define S_IFSOCK 0140000 // Socket - -#define S_IFSHIFT 12 - -#define T_IFDIR (S_IFDIR >> S_IFSHIFT) -#define T_IFCHR (S_IFCHR >> S_IFSHIFT) -#define T_IFBLK (S_IFBLK >> S_IFSHIFT) -#define T_IFREG (S_IFREG >> S_IFSHIFT) -#define T_IFIFO (S_IFIFO >> S_IFSHIFT) -#define T_IFLNK (S_IFLNK >> S_IFSHIFT) -#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) - - -#define ext2_group_desc_lg2size 5 - - - -/* - * super block structure: - * include/linux/ext2_fs.h - */ -struct ext2_super_block { - uint32_t s_inodes_count; /* Inodes count */ - uint32_t s_blocks_count; /* Blocks count */ - uint32_t s_r_blocks_count; /* Reserved blocks count */ - uint32_t s_free_blocks_count; /* Free blocks count */ - uint32_t s_free_inodes_count; /* Free inodes count */ - uint32_t s_first_data_block; /* First Data Block */ - uint32_t s_log_block_size; /* Block size */ - uint32_t s_log_frag_size; /* Fragment size */ - uint32_t s_blocks_per_group; /* # Blocks per group */ - uint32_t s_frags_per_group; /* # Fragments per group */ - uint32_t s_inodes_per_group; /* # Inodes per group */ - uint32_t s_mtime; /* Mount time */ - uint32_t s_wtime; /* Write time */ - uint16_t s_mnt_count; /* Mount count */ - int16_t s_max_mnt_count; /* Maximal mount count */ - uint16_t s_magic; /* Magic signature */ - uint16_t s_state; /* File system state */ - uint16_t s_errors; /* Behaviour when detecting errors */ - uint16_t s_minor_rev_level; - uint32_t s_lastcheck; /* time of last check */ - uint32_t s_checkinterval; /* max. time between checks */ - uint32_t s_creator_os; /* OS */ - uint32_t s_rev_level; /* Revision level */ - uint16_t s_def_resuid; /* Default uid for reserved blocks */ - uint16_t s_def_resgid; /* Default gid for reserved blocks */ - - uint32_t s_first_ino; /* First non-reserved inode */ - uint16_t s_inode_size; /* size of inode structure */ - uint16_t s_block_group_nr; /* block group # of this superblock */ - uint32_t s_feature_compat; /* compatible feature set */ - uint32_t s_feature_incompat; /* incompatible feature set */ - uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ - uint8_t s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ - uint32_t s_algorithm_usage_bitmap; /* For compression */ - uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - uint8_t s_prealloc_dir_blocks; - uint16_t s_padding1; - uint32_t s_reserved[204]; /* Padding to the end of the block */ -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_super_block_size != 1024 -#error ext2_super_block definition bogus -#endif -#endif -*******************************************************************************/ - -/* - * ext2 group desc structure: - */ -struct ext2_group_desc { - uint32_t bg_block_bitmap; /* Blocks bitmap block */ - uint32_t bg_inode_bitmap; /* Inodes bitmap block */ - uint32_t bg_inode_table; /* Inodes table block */ - uint16_t bg_free_blocks_count; /* Free blocks count */ - uint16_t bg_free_inodes_count; /* Free inodes count */ - uint16_t bg_used_dirs_count; /* Directories count */ - uint16_t bg_pad; - uint32_t bg_reserved[3]; -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_group_desc_size != 32 -#error ext2_group_desc definition bogus -#endif -#endif -*******************************************************************************/ - - -/* - * ext2 inode structure: - */ -struct ext2_inode { - uint16_t i_mode; /* File mode */ - uint16_t i_uid; /* Owner Uid */ - uint32_t i_size; /* 4: Size in bytes */ - uint32_t i_atime; /* Access time */ - uint32_t i_ctime; /* 12: Creation time */ - uint32_t i_mtime; /* Modification time */ - uint32_t i_dtime; /* 20: Deletion Time */ - uint16_t i_gid; /* Group Id */ - uint16_t i_links_count; /* 24: Links count */ - uint32_t i_blocks; /* Blocks count */ - uint32_t i_flags; /* 32: File flags */ - uint32_t l_i_reserved1; - uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ - uint32_t i_version; /* File version (for NFS) */ - uint32_t i_file_acl; /* File ACL */ - uint32_t i_dir_acl; /* Directory ACL */ - uint32_t i_faddr; /* Fragment address */ - uint8_t l_i_frag; /* Fragment number */ - uint8_t l_i_fsize; /* Fragment size */ - uint16_t i_pad1; - uint32_t l_i_reserved2[2]; -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_inode_size != 128 -#error ext2_inode definition bogus -#endif -#endif -*******************************************************************************/ - - -#define EXT2_NAME_LEN 255 -struct ext2_dir_entry { - unsigned int d_inode; /* Inode number */ - unsigned short d_rec_len; /* Directory entry length */ - unsigned char d_name_len; /* Name length */ - unsigned char d_file_type; - char d_name[EXT2_NAME_LEN]; /* File name */ -}; - -/******************************************************************************* -#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) -*******************************************************************************/ - - - - - - -/* - * This is the extent on-disk structure. - * It's used at the bottom of the tree. - */ -struct ext4_extent { - uint32_t ee_block; /* first logical block extent covers */ - uint16_t ee_len; /* number of blocks covered by extent */ - uint16_t ee_start_hi; /* high 16 bits of physical block */ - uint32_t ee_start_lo; /* low 32 bits of physical block */ -}; - -/* - * This is index on-disk structure. - * It's used at all the levels except the bottom. - */ -struct ext4_extent_idx { - uint32_t ei_block; /* index covers logical blocks from 'block' */ - uint32_t ei_leaf_lo; /* pointer to the physical block of the next * - * level. leaf or next index could be there */ - uint16_t ei_leaf_hi; /* high 16 bits of physical block */ - uint16_t ei_unused; -}; - -/* - * Each block (leaves and indexes), even inode-stored has header. - */ -struct ext4_extent_header { - uint16_t eh_magic; /* probably will support different formats */ - uint16_t eh_entries; /* number of valid entries */ - uint16_t eh_max; /* capacity of store in entries */ - uint16_t eh_depth; /* has tree real underlying blocks? */ - uint32_t eh_generation; /* generation of the tree */ -}; - - - -#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) -#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) - - - - - - - -/* function declartion */ -/******************************************************************************* -extern struct open_file_t * ext2_read(char *); -extern int ext2_read(struct open_file_t *, char *, int); -*******************************************************************************/ - - -#endif /* ext2_fs.h */ diff --git a/core/include/cache.h b/core/include/cache.h new file mode 100644 index 00000000..7518bc84 --- /dev/null +++ b/core/include/cache.h @@ -0,0 +1,25 @@ +#ifndef _CACHE_H +#define _CACHE_H + +#include +#include +#include "disk.h" +#include "fs.h" + +#define MAX_CACHE_ENTRIES 0x10 /* I find even this is enough:) */ + +/* The cache structure */ +struct cache_struct { + block_t block; + struct cache_struct *prev; + struct cache_struct *next; + void *data; +}; + + +/* functions defined in cache.c */ +void cache_init(struct device *, int); +struct cache_struct* get_cache_block(struct device *, block_t); +void print_cache(struct device *); + +#endif /* cache.h */ diff --git a/core/include/ext2_fs.h b/core/include/ext2_fs.h new file mode 100644 index 00000000..d579eade --- /dev/null +++ b/core/include/ext2_fs.h @@ -0,0 +1,252 @@ +#ifndef __EXT2_FS_H +#define __EXT2_FS_H + +#include + +#define EXT2_SUPER_MAGIC 0xEF53 + +#define EXT2_GOOD_OLD_REV 0 // The good old (original) format +#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +// Special inode numbers +#define EXT2_BAD_INO 1 // Bad blocks inode +#define EXT2_ROOT_INO 2 // Root inode +#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode +#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode +#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode +#define EXT3_JOURNAL_INO 8 // Journal inode + +// We're readonly, so we only care about incompat features. +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff + +#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) + + +/* for EXT4 extent */ +#define EXT4_EXT_MAGIC 0xf30a +#define EXT4_EXTENTS_FLAG 0x00080000 + +/* + * File types and file modes + */ +#define S_IFDIR 0040000 // Directory +#define S_IFCHR 0020000 // Character device +#define S_IFBLK 0060000 // Block device +#define S_IFREG 0100000 // Regular file +#define S_IFIFO 0010000 // FIFO +#define S_IFLNK 0120000 // Symbolic link +#define S_IFSOCK 0140000 // Socket + +#define S_IFSHIFT 12 + +#define T_IFDIR (S_IFDIR >> S_IFSHIFT) +#define T_IFCHR (S_IFCHR >> S_IFSHIFT) +#define T_IFBLK (S_IFBLK >> S_IFSHIFT) +#define T_IFREG (S_IFREG >> S_IFSHIFT) +#define T_IFIFO (S_IFIFO >> S_IFSHIFT) +#define T_IFLNK (S_IFLNK >> S_IFSHIFT) +#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) + + +#define ext2_group_desc_lg2size 5 + + + +/* + * super block structure: + * include/linux/ext2_fs.h + */ +struct ext2_super_block { + uint32_t s_inodes_count; /* Inodes count */ + uint32_t s_blocks_count; /* Blocks count */ + uint32_t s_r_blocks_count; /* Reserved blocks count */ + uint32_t s_free_blocks_count; /* Free blocks count */ + uint32_t s_free_inodes_count; /* Free inodes count */ + uint32_t s_first_data_block; /* First Data Block */ + uint32_t s_log_block_size; /* Block size */ + uint32_t s_log_frag_size; /* Fragment size */ + uint32_t s_blocks_per_group; /* # Blocks per group */ + uint32_t s_frags_per_group; /* # Fragments per group */ + uint32_t s_inodes_per_group; /* # Inodes per group */ + uint32_t s_mtime; /* Mount time */ + uint32_t s_wtime; /* Write time */ + uint16_t s_mnt_count; /* Mount count */ + int16_t s_max_mnt_count; /* Maximal mount count */ + uint16_t s_magic; /* Magic signature */ + uint16_t s_state; /* File system state */ + uint16_t s_errors; /* Behaviour when detecting errors */ + uint16_t s_minor_rev_level; + uint32_t s_lastcheck; /* time of last check */ + uint32_t s_checkinterval; /* max. time between checks */ + uint32_t s_creator_os; /* OS */ + uint32_t s_rev_level; /* Revision level */ + uint16_t s_def_resuid; /* Default uid for reserved blocks */ + uint16_t s_def_resgid; /* Default gid for reserved blocks */ + + uint32_t s_first_ino; /* First non-reserved inode */ + uint16_t s_inode_size; /* size of inode structure */ + uint16_t s_block_group_nr; /* block group # of this superblock */ + uint32_t s_feature_compat; /* compatible feature set */ + uint32_t s_feature_incompat; /* incompatible feature set */ + uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ + uint8_t s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + uint32_t s_algorithm_usage_bitmap; /* For compression */ + uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + uint8_t s_prealloc_dir_blocks; + uint16_t s_padding1; + uint32_t s_reserved[204]; /* Padding to the end of the block */ +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_super_block_size != 1024 +#error ext2_super_block definition bogus +#endif +#endif +*******************************************************************************/ + +/* + * ext2 group desc structure: + */ +struct ext2_group_desc { + uint32_t bg_block_bitmap; /* Blocks bitmap block */ + uint32_t bg_inode_bitmap; /* Inodes bitmap block */ + uint32_t bg_inode_table; /* Inodes table block */ + uint16_t bg_free_blocks_count; /* Free blocks count */ + uint16_t bg_free_inodes_count; /* Free inodes count */ + uint16_t bg_used_dirs_count; /* Directories count */ + uint16_t bg_pad; + uint32_t bg_reserved[3]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_group_desc_size != 32 +#error ext2_group_desc definition bogus +#endif +#endif +*******************************************************************************/ + + +/* + * ext2 inode structure: + */ +struct ext2_inode { + uint16_t i_mode; /* File mode */ + uint16_t i_uid; /* Owner Uid */ + uint32_t i_size; /* 4: Size in bytes */ + uint32_t i_atime; /* Access time */ + uint32_t i_ctime; /* 12: Creation time */ + uint32_t i_mtime; /* Modification time */ + uint32_t i_dtime; /* 20: Deletion Time */ + uint16_t i_gid; /* Group Id */ + uint16_t i_links_count; /* 24: Links count */ + uint32_t i_blocks; /* Blocks count */ + uint32_t i_flags; /* 32: File flags */ + uint32_t l_i_reserved1; + uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ + uint32_t i_version; /* File version (for NFS) */ + uint32_t i_file_acl; /* File ACL */ + uint32_t i_dir_acl; /* Directory ACL */ + uint32_t i_faddr; /* Fragment address */ + uint8_t l_i_frag; /* Fragment number */ + uint8_t l_i_fsize; /* Fragment size */ + uint16_t i_pad1; + uint32_t l_i_reserved2[2]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_inode_size != 128 +#error ext2_inode definition bogus +#endif +#endif +*******************************************************************************/ + + +#define EXT2_NAME_LEN 255 +struct ext2_dir_entry { + unsigned int d_inode; /* Inode number */ + unsigned short d_rec_len; /* Directory entry length */ + unsigned char d_name_len; /* Name length */ + unsigned char d_file_type; + char d_name[EXT2_NAME_LEN]; /* File name */ +}; + +/******************************************************************************* +#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) +*******************************************************************************/ + + + + + + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +struct ext4_extent { + uint32_t ee_block; /* first logical block extent covers */ + uint16_t ee_len; /* number of blocks covered by extent */ + uint16_t ee_start_hi; /* high 16 bits of physical block */ + uint32_t ee_start_lo; /* low 32 bits of physical block */ +}; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +struct ext4_extent_idx { + uint32_t ei_block; /* index covers logical blocks from 'block' */ + uint32_t ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + uint16_t ei_leaf_hi; /* high 16 bits of physical block */ + uint16_t ei_unused; +}; + +/* + * Each block (leaves and indexes), even inode-stored has header. + */ +struct ext4_extent_header { + uint16_t eh_magic; /* probably will support different formats */ + uint16_t eh_entries; /* number of valid entries */ + uint16_t eh_max; /* capacity of store in entries */ + uint16_t eh_depth; /* has tree real underlying blocks? */ + uint32_t eh_generation; /* generation of the tree */ +}; + + + +#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) +#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) + + + + + + + +/* function declartion */ +/******************************************************************************* +extern struct open_file_t * ext2_read(char *); +extern int ext2_read(struct open_file_t *, char *, int); +*******************************************************************************/ + + +#endif /* ext2_fs.h */ diff --git a/core/types.h b/core/types.h deleted file mode 100644 index 4cd3902c..00000000 --- a/core/types.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _TYPES_H -#define _TYPES_H - -typedef unsigned long long __u64; -typedef unsigned int __u32; -typedef unsigned short __u16; -typedef unsigned char __u8; - - -typedef int __s32; -typedef short __s16; -typedef char __s8; - - - - -#endif /* types.h */ -- cgit v1.2.1 From 1a4fe28588ed6bf114f3b9e06966406a1b833d6e Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 14 Jun 2009 14:22:33 +0800 Subject: Core:SYSLINUX: ldlinux.asm converted to C Well, something goes ugly but it works. And I still need spend some more time to make the code much better. --- core/Makefile | 3 +- core/comboot.inc | 4 +- core/extern.inc | 3 + core/fat.c | 963 +++++++++++++++++++++++++++++++++++++++++ core/fs.c | 11 +- core/include/fat_fs.h | 118 +++++ core/ldlinux.asm | 1149 +------------------------------------------------ 7 files changed, 1105 insertions(+), 1146 deletions(-) create mode 100644 core/fat.c create mode 100644 core/include/fat_fs.h diff --git a/core/Makefile b/core/Makefile index c41b423b..c2238972 100644 --- a/core/Makefile +++ b/core/Makefile @@ -33,7 +33,8 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ - extlinux.bin extlinux.bss extlinux.sys + extlinux.bin extlinux.bss extlinux.sys \ + ldlinux.bss ldlinux.sys ldlinux.bin # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) diff --git a/core/comboot.inc b/core/comboot.inc index 8a7d95c4..7c2b6e66 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -911,7 +911,7 @@ comapi_opendir: cmp eax,0 jz comapi_err ; Found nothing ;ZF is unset - call alloc_fill_dir + pm_call alloc_fill_dir mov P_EAX,eax mov P_CX,SECTOR_SIZE mov P_SI,si @@ -929,7 +929,7 @@ comapi_readdir: mov es,P_ES mov di,P_DI mov si,P_SI - call readdir + pm_call readdir mov P_EAX,eax mov P_DL,dl mov P_EBX,ebx diff --git a/core/extern.inc b/core/extern.inc index fdbe2643..2e6dcd07 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -15,4 +15,7 @@ ; fs.c extern fs_init, searchdir, getfssec, mangle_name, load_config + ; fat.c + extern alloc_fill_dir, readdir + %endif ; EXTERN_INC diff --git a/core/fat.c b/core/fat.c new file mode 100644 index 00000000..87e9c0a7 --- /dev/null +++ b/core/fat.c @@ -0,0 +1,963 @@ +#include +#include +#include "cache.h" +#include "core.h" +#include "disk.h" +#include "fat_fs.h" +#include "fs.h" + + +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) +#define MAX_OPEN_LG2 6 +#define MAX_OPEN (1 << MAX_OPEN_LG2) +#define ROOT_DIR_WORD 0x002f + +/* file structure. This holds the information for each currently open file */ +struct open_file_t { + uint32_t file_sector; /* sector pointer ( 0 = structure free ) */ + uint32_t file_bytesleft; /* number of bytes left */ + uint32_t file_left; /* number of sectors left */ + uint32_t pad; /* padding */ +}; + +extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; +extern char trackbuf[8192]; + + +/* the fat bpb data */ +struct fat_bpb fat; +int FATType = 0; + +/* generic information about FAT fs */ +uint32_t FAT; /* Location of (first) FAT */ +uint32_t RootDirArea; /* Location of root directory area */ +uint32_t RootDir; /* Location of root directory proper */ +uint32_t DataArea; /* Location of data area */ +uint32_t TotalSectors; /* Total number of sectors */ +uint32_t ClustSize; /* Bytes/cluster */ +uint32_t ClustMask; /* Sector/cluster - 1 */ +uint8_t CopySuper; /* Distinguish .bs versus .bss */ +uint8_t DriveNumber; /* BIOS drive number */ +uint8_t ClustShift; /* Shift count for sectors/cluster */ +uint8_t ClustByteShift; /* Shift count for bytes/cluster */ + +int CurrentDir; +int PrevDir; + +/* used for long name entry */ +char MangleBuf[12]; +char entry_name[14]; +char *NameStart; +int NameLen; + +/* do this for readdir, because it called from asm and don't know the fs structure */ +struct fs_info *this_fs = NULL; + +/* + * Well, I find I can't reference the syslinux_cfg[i] config file name even though I + * used extern in C side and global in the ASM side. So I thought I can use a gloabl + * pointer called this_filename, points to the current filename. And in the searchdir + * function, we use a flag to determine if we need use the this_filename to go on. + * Here is the principle: + * + * if (regs->esi.w[0] == 0xCFCF) ; Called From C File(CFCF) + * file_name = this_fs; + * else + * file_name = (char *)MK_PTR(regs->es, regs->esi.w[0]) + * + * + * so if we want call searchdir function from C file, and the filename address + * is in the high address(means higher than 1M), we can put regs->edi.w[0] the 0xCFCF + * flag, then I hope all will go well. + * + * (I know it's ugly, sorry) + */ +char *this_filename = NULL; + + +/** + * allocate_file: + * + * Allocate a file structure + * + * @return: if successful return the file pointer, or return NULL + * + */ +static struct open_file_t *allocate_file() +{ + struct open_file_t *file; + int i = 0; + + file = (struct open_file_t *)Files; + + for (; i < MAX_OPEN; i ++ ) { + if ( file->file_sector == 0 ) /* found it */ + return file; + file ++; + } + + return NULL; /* not found */ +} + + +/** + * alloc_fill_dir: + * + * Allocate then fill a file structure for a directory starting in + * sector SECTOR. if successful, return the pointer of filled file + * structure, or return NULL. + * + */ +void alloc_fill_dir(com32sys_t *regs) +{ + sector_t sector = regs->eax.l; + struct open_file_t *file; + + file = allocate_file(); + if ( !file ) { + regs->esi.w[0] = 0; + return; + } + + file->file_sector = sector; /* current sector */ + file->file_bytesleft = 0; /* current offset */ + file->file_left = sector; /* beginning sector */ + + regs->esi.w[0] = OFFS_WRT(file, 0); +} + + +/* Deallocates a file structure */ +static void close_file(struct open_file_t *file) +{ + if ( file ) + file->file_sector = 0; +} + + + +/* Deallocates a directory structure */ +/*********** +void close_dir(struct fat_dir_entry *dir) +{ + if ( dir ) + *(uint32_t*)dir = 0; +} +***********/ + + +/** + * getfatsector: + * + * check for a particular sector in the FAT cache. + * + */ +struct cache_struct *getfatsector(struct fs_info *fs, uint32_t sector) +{ + return get_cache_block(fs->fs_dev, FAT + sector); +} + + +/** + * nextcluster: + * + * Advance a cluster pointer in clust_num to the next cluster + * pointer at in the FAT tables. CF = 0 on return if end of file. + * + * @param: clust_num; + * + * @return: the next cluster number + * + */ +static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) +{ + uint32_t next_cluster; + uint32_t fat_sector; + uint32_t offset; + int lo, hi; + struct cache_struct *cs; + + switch(FATType) { + case FAT12: + fat_sector = (clust_num + clust_num / 2) >> SECTOR_SHIFT; + cs = getfatsector(fs, fat_sector); + offset = (clust_num * 3 / 2) & ( SECTOR_SIZE -1 ); + if ( offset == 0x1ff ) { + /* + * we got the end of the one fat sector, + * but we don't got we have(just one byte, we need two), + * so store the low part, then read the next fat + * sector, read the high part, then combine it. + */ + lo = *(uint8_t *)(cs->data + offset); + cs = getfatsector(fs, fat_sector + 1); + hi = *(uint8_t *)cs->data; + next_cluster = (hi << 8) + lo; + } else + next_cluster = *(uint16_t *)(cs->data + offset); + + if ( clust_num & 0x0001 ) + next_cluster >>= 4; /* cluster number is ODD */ + else + next_cluster &= 0x0fff; /* cluster number is EVEN */ + if ( next_cluster > 0x0ff0 ) + goto fail; + break; + + case FAT16: + fat_sector = clust_num >> (SECTOR_SHIFT - 1); + offset = clust_num & ( (1 << (SECTOR_SHIFT-1)) -1); + cs = getfatsector(fs, fat_sector); + next_cluster = ((uint16_t *)cs->data)[offset]; + if ( next_cluster > 0xfff0 ) + goto fail; + break; + + case FAT32: + fat_sector = clust_num >> (SECTOR_SHIFT - 2); + offset = clust_num & ( (1 << (SECTOR_SHIFT-2)) -1); + cs = getfatsector(fs, fat_sector); + next_cluster = ((uint32_t *)cs->data)[offset] & 0x0fffffff; + if ( next_cluster > 0x0ffffff0 ) + goto fail; + break; + } + + return next_cluster; + + fail: + /* got an unexcepted cluster number, so return ZERO */ + return 0; +} + + + +/** + * nextsector: + * + * given a sector on input, return the next sector of the + * same filesystem object, which may be the root directory or a + * cluster chain. Returns EOF. + * + */ +static uint32_t nextsector(struct fs_info *fs, uint32_t sector) +{ + uint32_t data_sector; + uint32_t cluster; + + if ( sector < DataArea ) { + sector ++; + /* if we reached the end of root area */ + if ( sector == DataArea ) + sector = 0; /* return 0 */ + return sector; + } + + data_sector = sector - DataArea; + if ( (data_sector+1) & ClustMask ) /* in a cluster */ + return (++sector); + + /* got a new cluster */ + cluster = nextcluster(fs, (data_sector >> ClustShift) + 2); + if ( !cluster ) + return 0; + + /* return the start of the new cluster */ + sector = ( (cluster - 2) << ClustShift ) + DataArea; + return sector; +} + + + + + +/** + * __getfssec: + * + * get multiple sectors from a file + * + * This routine makes sure the subransfers do not cross a 64K boundary + * and will correct the situation if it does, UNLESS *sectos* cross + * 64K boundaries. + * + * @param: buf + * @param: file structure + * @param: sectors + * + */ +static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, uint32_t sectors) +{ + uint32_t curr_sector = file->file_sector; + uint32_t frag_start , next_sector; + uint32_t con_sec_cnt; + + while (sectors) { + /* get fragment */ + con_sec_cnt = 0; + frag_start = curr_sector; + + do { + /* get consective sector count */ + con_sec_cnt ++; + sectors --; + if ( sectors == 0 ) + break; + + next_sector = nextsector(fs, curr_sector); + if ( !next_sector ) + break; + }while( next_sector == (++curr_sector) ); + +#if 0 /* Debug message */ + printf("You are reading stores at sector --0x%x--0x%x\n", + frag_start, frag_start + con_sec_cnt -1); +#endif + + /* do read */ + read_sectors(buf, frag_start, con_sec_cnt); + buf += con_sec_cnt << 9;/* adjust buffer pointer */ + + if ( !sectors ) + break; + //curr_sector --; /* this is the last sector actually read */ + curr_sector = next_sector; + } + + /* update the file_sector filed for the next read */ + file->file_sector = nextsector(fs, curr_sector); +} + + + +/** + * getfssec: + * + * get multiple sectors from a file + * + * + * @param: buf + * @param: file + * @param: sectors + * @param: have_more + * + * @return: number of bytes read + * + */ +uint32_t vfat_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) +{ + uint32_t bytes_read = sectors << SECTOR_SHIFT; + struct open_file_t *file = (struct open_file_t *)open_file; + + if ( sectors > file->file_left ) + sectors = file->file_left; + + __getfssec(fs, buf, file, sectors); + + if ( bytes_read >= file->file_bytesleft ) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else + *have_more = 1; + file->file_bytesleft -= bytes_read; + file->file_left -= sectors; + + return bytes_read; +} + +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed to by dst; + * ends on encountering any whitespace. + * + */ +void vfat_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX -1; + + while(*src > ' ') { + if ( *src == '\\' ) + *src = '/'; + + if (*src == '/') { + if (*(src+1) == '/') { + src ++; + i --; + continue; + } + } + i --; + *dst++ = *src++; + } + + while (1) { + if (dst == p) + break; + if ((*(dst-1) != '/') && (*(dst-1) != '.')) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i --) + *dst++ = '\0'; +} + + +/** + * mangle_dos_name: + * + * Mangle a dos filename component pointed to by FILENAME + * into MangleBuf; ends on encountering any whitespace or + * slash. + * + * WARNING: saves pointers into the buffer for longname matchs! + * + * @param: filename + * @param: MangleBuf + * + */ +/** + * for now, it can't handle this case: + * xyxzxyxjfdkfjdjf.txt as it will just output the first 11 chars + * but not care the dot char at the later, so I think we need do + * this, but it seems that the SYSLINUX doesn't do it, so I will + * make it stay as what it was orignal. + * + */ +static void mangle_dos_name(char *MangleBuf, char *filename) +{ + + char *dst = MangleBuf; + char *src = filename; + int i = 0; + unsigned char c; + + NameStart = filename; + + for (; i < 11; i ++) + MangleBuf[i] = ' '; + + for (i = 0; i < 11; i++) { + c = *src ++; + + if ( (c <= ' ') || (c == '/') ) + break; + + if ( c == '.' ) { + dst = &MangleBuf[8]; + i = 7; + continue; + } + + if (c >= 'a' && c <= 'z') + c -= 32; + if ( (c == 0xe5) && (i == 11) ) + c = 0x05; + + *dst++ = c; + } + MangleBuf[12] = '\0'; + + while( (*src != '/') && (*src > ' ') ) + src ++; + + NameLen = src - filename; +} + + + +static void unicode_to_ascii(char *entry_name, uint16_t *unicode_buf) +{ + int i = 0; + + for (; i < 13; i++) { + if ( unicode_buf[i] == 0xffff ) { + entry_name[i] = '\0'; + return; + } + entry_name[i] = (char)unicode_buf[i]; + } +} + +/** + * long_entry_name: + * + * get the long entry name + * + */ +static void long_entry_name(struct fat_long_name_entry *dir) +{ + uint16_t unicode_buf[13]; + + memcpy(unicode_buf, dir->name1, 5 * 2); + memcpy(unicode_buf + 5, dir->name2, 6 * 2); + memcpy(unicode_buf + 11,dir->name3, 2 * 2); + + unicode_to_ascii(entry_name, unicode_buf); + +} + + +static uint8_t get_checksum(char *dir_name) +{ + int i; + uint8_t sum=0; + + for (i=11; i; i--) + sum = ((sum & 1) << 7) + (sum >> 1) + *dir_name++; + return sum; +} + +static inline uint32_t first_sector(struct fat_dir_entry *dir) +{ + uint32_t first_clust, sector; + + first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low; + sector = ((first_clust - 2) << ClustShift) + DataArea; + + return sector; +} + + +/* try with the biggest long name */ +char long_name[0x40 * 13]; + +/** + * search_dos_dir: + * + * search a specific directory for a pre-mangled filename in + * MangleBuf, in the directory starting in sector SECTOR + * + * NOTE: This file considers finding a zero-length file an + * error. This is so we don't have to deal with that special + * case elsewhere in the program (most loops have the test + * at the end). + * + * @param: MangleBuf + * @param: dir_sector, directory sector + * + * @out: file pointer + * @out: file length (MAY BE ZERO!) + * @out: file attribute + * @out: dh, clobbered. + * + */ +static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, + uint32_t dir_sector, uint32_t *file_len, uint8_t *attr) +{ + struct open_file_t* file; + struct cache_struct* cs; + struct fat_dir_entry *dir; + struct fat_long_name_entry *long_dir; + + uint8_t VFATInit, VFATNext, VFATCsum; + uint8_t id; + uint32_t slots; + uint32_t entries; + int checksum; + + file = allocate_file(); + if ( !file ) + return NULL; + + /* + * Compute the value of a possible VFAT longname + * "last" entry (which, of coures, comes first ...) + */ + slots = (NameLen + 12) / 13; + slots |= 0x40; + VFATInit = slots; + VFATNext = slots; + + do { + cs = get_cache_block(fs->fs_dev, dir_sector); + dir = (struct fat_dir_entry *)cs->data; + entries = SECTOR_SIZE / 32; + + /* scan all the entries in a sector */ + do { + if ( dir->name[0] == 0 ) + return NULL; /* Hit directory high water mark */ + + if ( dir->attr == 0x0f ) { + /* it's a long name entry */ + long_dir = (struct fat_long_name_entry *)dir; + id = long_dir->id; + if ( id !=VFATNext ) + goto not_match; + + if ( id & 0x40 ) { + /*get the initial checksum value*/ + VFATCsum = long_dir->checksum; + } else { + if ( long_dir->checksum != VFATCsum ) + goto not_match; + } + + id &= 0x3f; + VFATNext = --id; + + /* got the long entry name */ + long_entry_name(long_dir); + memcpy(long_name + id * 13, entry_name, 13); + + /* + * if we got the last entry? + * if so, check it, or go on with the next entry + */ + if ( id == 0 ) { + if ( strcmp(long_name, NameStart) ) + goto not_match; + } + + goto next_entry; + + } else { + /* it's a short entry */ + if ( dir->attr & 0x08 ) /* ingore volume labels */ + goto not_match; + + + /* If we have a long name match, then VFATNext must be 0 */ + if ( !VFATNext ) { + /* + * we already have a VFAT long name match, however, + * the match is only valid if the checksum matchs. + */ + checksum = get_checksum(dir->name); + if ( checksum == VFATCsum ) + goto found; /* got a match on long name */ + + } else { + if ( strncmp(MangleBuf, dir->name, 11) == 0 ) + goto found; + } + } + + not_match:/* find it again */ + VFATNext = VFATInit; + + next_entry: + dir ++; + + }while ( --entries ); + + dir_sector = nextsector(fs, dir_sector); + + }while ( dir_sector ); /* scan another secotr */ + + found: + *file_len = file->file_bytesleft = dir->file_size; + file->file_sector = first_sector(dir); + *attr = dir->attr; + + return file; +} + + + +/** + * searchdir: + * + * open a file + * + * @param: filename, the file we wanna open + * @param: file_len, to return the file length + * + * @return: return the file structure on successful, or NULL. + * + */ +void vfat_searchdir(char *filename, struct file *file) +{ + uint32_t dir_sector; + uint32_t file_len = 0; + uint8_t attr = 0; + char *p; + struct open_file_t *open_file = NULL; + + if (file->fs != this_fs) + this_fs = file->fs; + + dir_sector = CurrentDir; + if ( *filename == '/' ) { + dir_sector = RootDir; + filename ++; + } + + while ( *filename ) { + p = filename; + + /* try to find the end */ + while ( (*p > ' ') && (*p != '/') ) + p ++; + + if (filename == p) + //return NULL; + goto fail; + + PrevDir = dir_sector; + + mangle_dos_name(MangleBuf, filename); + open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); + if (! open_file) + goto fail; + + if ( *p != '/' ) /* we got a file */ + break; + + if ( (attr & 0x10) == 0 ) /* subdirectory */ + //return NULL; + goto fail; + + dir_sector = open_file->file_sector; + close_file(open_file); + + filename = p + 1; /* search again */ + } + + if ( (attr & 0x18) || (file_len == 0) ) { + fail: + file_len = 0; + open_file = NULL; + } else { + open_file->file_bytesleft = file_len; + open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; + } + + file->file_len = file_len; + file->open_file = (void *)open_file; +} + + + + +/** + * readdir: + * + * read one file from a directory + * + * returns the file's name in the filename string buffer + * + * @param: filename + * @param: file + * + */ +void readdir(com32sys_t *regs)/* + struct fs_info *fs, struct open_file_t* dir_file, + char* filename, uint32_t *file_len, uint8_t *attr) + */ +{ + uint32_t sector, sec_off; + + /* make it to be 1 to check if we have met a long name entry before */ + uint8_t id = 1; + uint8_t init_id, next_id; + uint8_t entries_left; + int i; + + char *filename = (char *)MK_PTR(regs->es, regs->edi.w[0]); + struct open_file_t *dir_file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); + + struct cache_struct *cs; + struct fat_dir_entry *dir; + struct fat_long_name_entry *long_dir; + struct open_file_t file; + + sector = dir_file->file_sector; + sec_off = dir_file->file_bytesleft; + if ( !sector ) + goto fail; + + entries_left = (SECTOR_SIZE - sec_off) >> 5; + cs = get_cache_block(this_fs->fs_dev, sector); + dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ + + while ( 1 ) { + if ( dir->name[0] == 0 ) + goto fail; + + if ( dir->attr == FAT_ATTR_LONG_NAME ) { + /* it's a long name */ + long_dir = (struct fat_long_name_entry *)dir; + + if ( long_dir->id & 0x40 ) { + init_id = id = long_dir->id & 0x3f; + id--; + } else { + next_id = (long_dir->id & 0x3f) - 1; + id--; + if ( id != next_id ) + goto next_entry; + } + + long_entry_name(long_dir); + memcpy(filename + id * 13, entry_name, 13); + + + /* + * we need go on with the next entry + * and we will fall through to next entry + */ + + } else { + /* it's a short entry */ + + if ( !id ) /* we got a long name match */ + break; + + if ( dir->attr & FAT_ATTR_VOLUME_ID ) + goto next_entry; + + for( i = 0; i < 8; i ++) { + if ( dir->name[i] == ' ' ) + break; + *filename++ = dir->name[i]; + } + + *filename++ = '.'; + + for ( i = 8; i < 11; i ++) { + if ( dir->name[i] == ' ' ) + break; + *filename ++ = dir->name[i]; + } + + /* check if we have got an extention */ + if ( ! *(filename - 1) ) + *(filename -2) = '\0'; + else + *filename = '\0'; + + break; + } + + next_entry: + dir ++; + entries_left --; + + if ( !entries_left ) { + sector = nextsector(this_fs, sector); + if ( !sector ) + goto fail; + cs = get_cache_block(this_fs->fs_dev, sector); + dir = (struct fat_dir_entry *)cs->data; + } + } + + /* finally , we get what we want */ + entries_left --; + if ( !entries_left ) { + sector = nextsector(this_fs, sector); + if ( !sector ) + goto fail; + } + + file.file_sector = sector; + file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT) ) & 0xffff; + + regs->eax.l = dir->file_size; + regs->ebx.l = first_sector(dir); + regs->edx.b[0] = dir->attr; + + return; + + fail: + //close_dir(dir); + regs->eax.l = 0; +} + +void vfat_load_config(com32sys_t *regs) +{ + char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; + char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; + char syslinux_cfg3[] = "/syslinux.cfg"; + char config_name[] = "syslinux.cfg"; + + + char *syslinux_cfg[]= {syslinux_cfg1, syslinux_cfg2, syslinux_cfg3}; + com32sys_t oregs; + int i = 0; + + *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; + CurrentDir = RootDir; + + strcpy(ConfigName, config_name); + for (; i < 3; i++) { + regs->edi.w[0] = 0xCFCF; /* Mark we use the this_filename to pass filename para */ + this_filename = syslinux_cfg[i]; + memset(&oregs, 0, sizeof oregs); + call16(core_open, regs, &oregs); + + /* if zf flag set, then failed; try another */ + if (! (oregs.eflags.l & EFLAGS_ZF)) + break; + } + if ( i == 3 ) { + printf("no config file found\n"); + return; /* no config file */ + } + + strcpy(CurrentDirName, syslinux_cfg[i]); + CurrentDirName[strlen(syslinux_cfg[i])-strlen(config_name)] = '\0'; + CurrentDir = PrevDir; +} + +static inline void bsr(uint8_t *res, int num) +{ + int i = 0; + while (num >>= 1) + i ++; + *res = i; +} + +/* init. the fs meta data, return the block size in bits */ +int vfat_fs_init() +{ + int sectors_per_fat; + uint32_t clust_num; + int RootDirSize; + + /* get the fat bpb information */ + read_sectors((char *)&fat, 0, 1); + + TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; + FAT = fat.bxResSectors; + + sectors_per_fat = fat.bxFATsecs ? : fat.u.fat32.bxFATsecs_32; + RootDir = RootDirArea = FAT + sectors_per_fat * fat.bxFATs; + RootDirSize = (fat.bxRootDirEnts+SECTOR_SIZE/32-1) >> (SECTOR_SHIFT-5); + DataArea = RootDirArea + RootDirSize; + + bsr(&ClustShift, fat.bxSecPerClust); + ClustByteShift = ClustShift + SECTOR_SHIFT; + ClustMask = fat.bxSecPerClust - 1; + ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; + + + clust_num = (TotalSectors - DataArea) >> ClustShift; + if ( clust_num < 4085 ) + FATType = FAT12; + else if ( clust_num < 65525 ) + FATType = FAT16; + else + FATType = FAT32; + + /* for SYSLINUX, the cache is based on sector size */ + return SECTOR_SHIFT; +} + +const struct fs_ops vfat_fs_ops = { + .fs_name = "vfat", + .fs_init = vfat_fs_init, + .searchdir = vfat_searchdir, + .getfssec = vfat_getfssec, + .mangle_name = vfat_mangle_name, + .unmangle_name = NULL, + .load_config = vfat_load_config +}; diff --git a/core/fs.c b/core/fs.c index 617e3e5e..2878c384 100644 --- a/core/fs.c +++ b/core/fs.c @@ -55,9 +55,15 @@ void getfssec(com32sys_t *regs) void searchdir(com32sys_t *regs) { - char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + char *filename; struct file file; + if (regs->edi.w[0] == 0xCFCF) { + /* check fat.c for more information */ + extern char *this_filename; + filename = this_filename; + } else + filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); #if 0 printf("filename: %s\n", filename); #endif @@ -119,7 +125,8 @@ void device_init(struct device *dev, uint8_t device_num, sector_t offset) * */ if ( USE_CACHE(dev->device_number) ) { - /* I can't use __lowmem here, 'cause it will cause the error: + /* FIX!! + I can't use __lowmem here, 'cause it will cause the error: "auxseg/lowmem region collides with xfer_buf_seg" */ //static __lowmem char cache_buf[65536]; dev->cache_data = core_cache_buf; diff --git a/core/include/fat_fs.h b/core/include/fat_fs.h new file mode 100644 index 00000000..0f7176b6 --- /dev/null +++ b/core/include/fat_fs.h @@ -0,0 +1,118 @@ +#ifndef FAT_FS_H +#define FAT_FS_H + +#include + +#define FAT_DIR_ENTRY_SIZE 32 +#define DIRENT_SHIFT 5 + +#define FAT_ATTR_READ_ONLY 0x01 +#define FAT_ATTR_HIDDEN 0x02 +#define FAT_ATTR_SYSTEM 0x04 +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIRECTORY 0x10 +#define FAT_ATTR_ARCHIVE 0x20 + +#define FAT_MAXFILE 256 + +#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY \ + | FAT_ATTR_HIDDEN \ + | FAT_ATTR_SYSTEM \ + | FAT_ATTR_VOLUME_ID) + +#define FAT_ATTR_VALID (FAT_ATTR_READ_ONLY \ + | FAT_ATTR_HIDDEN \ + | FAT_ATTR_SYSTEM \ + | FAT_ATTR_DIRECTORY \ + | FAT_ATTR_ARCHIVE) + +enum fat_type{ FAT12, FAT16, FAT32 }; + +/* + * The fat file system structures + */ + +struct fat_bpb { + uint8_t jmp_boot[3]; + uint8_t oem_name[8]; + uint16_t sector_size; + uint8_t bxSecPerClust; + uint16_t bxResSectors; + uint8_t bxFATs; + uint16_t bxRootDirEnts; + uint16_t bxSectors; + uint8_t media; + uint16_t bxFATsecs; + uint16_t sectors_per_track; + uint16_t num_heads; + uint32_t num_hidden_sectors; + uint32_t bsHugeSectors; + + union { + struct { + uint8_t num_ph_drive; + uint8_t reserved; + uint8_t boot_sig; + uint32_t num_serial; + uint8_t label[11]; + uint8_t fstype[8]; + } __attribute__ ((packed)) fat12_16; + + struct { + uint32_t bxFATsecs_32; + uint16_t extended_flags; + uint16_t fs_version; + uint32_t root_cluster; + uint16_t fs_info; + uint16_t backup_boot_sector; + uint8_t reserved[12]; + uint8_t num_ph_drive; + uint8_t reserved1; + uint8_t boot_sig; + uint32_t num_serial; + uint8_t label[11]; + uint8_t fstype[8]; + } __attribute__ ((packed)) fat32; + + } __attribute__ ((packed)) u; + +} __attribute__ ((packed)); + + + +struct fat_dir_entry { + char name[11]; + uint8_t attr; + uint8_t nt_reserved; + uint8_t c_time_tenth; + uint16_t c_time; + uint16_t c_date; + uint16_t a_date; + uint16_t first_cluster_high; + uint16_t w_time; + uint16_t w_date; + uint16_t first_cluster_low; + uint32_t file_size; +} __attribute__ ((packed)); + + + +struct fat_long_name_entry { + uint8_t id; + uint16_t name1[5]; + uint8_t attr; + uint8_t reserved; + uint8_t checksum; + uint16_t name2[6]; + uint16_t first_cluster; + uint16_t name3[2]; +} __attribute__ ((packed)); + +__lowmem char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; +__lowmem char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; +__lowmem char syslinux_cfg3[] = "/syslinux.cfg"; +__lowmem char config_name[] = "syslinux.cfg"; + + + +#endif /* fat_fs.h */ diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 23bc5413..0f207248 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -120,7 +120,11 @@ CopySuper resb 1 ; Distinguish .bs versus .bss ClustShift resb 1 ; Shift count for sectors/cluster ClustByteShift resb 1 ; Shift count for bytes/cluster +; global syslinux_cfg_buffer +;syslinux_cfg_buffer resb 28 ; the syslinux config file name buffer, used by vfat_load_config + alignb open_file_t_size + global Files Files resb MAX_OPEN*open_file_t_size ; @@ -128,91 +132,7 @@ Files resb MAX_OPEN*open_file_t_size ; %include "diskstart.inc" -; -; Common initialization code -; -%include "init.inc" -%include "cpuinit.inc" - -; -; Compute some information about this filesystem. -; - -; First, generate the map of regions -genfatinfo: - mov edx,[bxSectors] - and dx,dx - jnz .have_secs - mov edx,[bsHugeSectors] -.have_secs: - mov [TotalSectors],edx - - mov eax,[bxResSectors] - mov [FAT],eax ; Beginning of FAT - mov edx,[bxFATsecs] - and dx,dx - jnz .have_fatsecs - mov edx,[bootsec+36] ; FAT32 BPB_FATsz32 -.have_fatsecs: - imul edx,[bxFATs] - add eax,edx - mov [RootDirArea],eax ; Beginning of root directory - mov [RootDir],eax ; For FAT12/16 == root dir location - - mov edx,[bxRootDirEnts] - add dx,SECTOR_SIZE/32-1 - shr dx,SECTOR_SHIFT-5 - mov [RootDirSize],edx - add eax,edx - mov [DataArea],eax ; Beginning of data area - -; Next, generate a cluster size shift count and mask - mov eax,[bxSecPerClust] - bsr cx,ax - mov [ClustShift],cl - push cx - add cl,SECTOR_SHIFT - mov [ClustByteShift],cl - pop cx - dec ax - mov [ClustMask],eax - inc ax - shl eax,SECTOR_SHIFT - mov [ClustSize],eax - -; -; FAT12, FAT16 or FAT28^H^H32? This computation is fscking ridiculous. -; -getfattype: - mov eax,[TotalSectors] - sub eax,[DataArea] - shr eax,cl ; cl == ClustShift - mov cl,nextcluster_fat12-(nextcluster+2) - cmp eax,4085 ; FAT12 limit - jb .setsize - mov cl,nextcluster_fat16-(nextcluster+2) - cmp eax,65525 ; FAT16 limit - jb .setsize - ; - ; FAT32, root directory is a cluster chain - ; - mov cl,[ClustShift] - mov eax,[bootsec+44] ; Root directory cluster - sub eax,2 - shl eax,cl - add eax,[DataArea] - mov [RootDir],eax - mov cl,nextcluster_fat28-(nextcluster+2) - mov byte [SuperSize],superblock_len_fat32 -.setsize: - mov byte [nextcluster+1],cl - -; -; Initialize the metadata cache -; - mov eax, 9 - pm_call cache_init ; ; Now, everything is "up and running"... patch kaboom for more @@ -243,45 +163,8 @@ getfattype: ; ; Load configuration file ; - mov si,config_name ; Save configuration file name - mov di,ConfigName - call strcpy - mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName - - mov eax,[RootDir] ; Make the root directory ... - mov [CurrentDir],eax ; ... the current directory - mov di,syslinux_cfg1 - push di - call core_open - pop di - jnz .config_open - mov di,syslinux_cfg2 - push di - call core_open - pop di - jnz .config_open - mov di,syslinux_cfg3 - push di - call core_open - pop di + pm_call load_config jz no_config_file -.config_open: - push si - mov si,di - push si - mov di,CurrentDirName - ; This is inefficient as it will copy more than needed - ; but not by too much - call strcpy - mov ax,config_name ;Cut it down - pop si - sub ax,si - mov di,CurrentDirName - add di,ax - mov byte [di],0 - pop si - mov eax,[PrevDir] ; Make the directory with syslinux.cfg ... - mov [CurrentDir],eax ; ... the current directory ; ; Now we have the config file open. Parse the config file and @@ -289,327 +172,7 @@ getfattype: ; %include "ui.inc" -; -; allocate_file: Allocate a file structure -; -; If successful: -; ZF set -; BX = file pointer -; In unsuccessful: -; ZF clear -; -allocate_file: - TRACER 'a' - push cx - mov bx,Files - mov cx,MAX_OPEN -.check: cmp dword [bx], byte 0 - je .found - add bx,open_file_t_size ; ZF = 0 - loop .check - ; ZF = 0 if we fell out of the loop -.found: pop cx - ret - -; -; alloc_fill_dir: -; Allocate then fill a file structure for a directory starting in -; sector EAX. -; -; Assumes DS == ES == CS. -; -; If successful: -; ZF clear -; SI = file pointer -; If unsuccessful -; ZF set -; EAX clobbered -; -alloc_fill_dir: - push bx - call allocate_file - jnz .alloc_failure -.found: - mov si,bx - mov [si+file_sector],eax ; Current sector - mov dword [si+file_bytesleft],0 ; Current offset - mov [si+file_left],eax ; Beginning sector - pop bx - ret - -.alloc_failure: - pop bx - xor eax,eax ; ZF <- 1 - ret - -; -; search_dos_dir: -; Search a specific directory for a pre-mangled filename in -; MangledBuf, in the directory starting in sector EAX. -; -; NOTE: This file considers finding a zero-length file an -; error. This is so we don't have to deal with that special -; case elsewhere in the program (most loops have the test -; at the end). -; -; Assumes DS == ES == CS. -; -; If successful: -; ZF clear -; SI = file pointer -; EAX = file length (MAY BE ZERO!) -; DL = file attribute -; DH = clobbered -; If unsuccessful -; ZF set -; EAX, SI, DX clobbered -; - -search_dos_dir: - push bx - call allocate_file - jnz .alloc_failure - - push cx - push gs - push es - push ds - pop es ; ES = DS - - ; Compute the value of a possible VFAT longname - ; "last" entry (which, of course, comes first...) - push ax - push dx - mov ax,[NameLen] - add ax,12 - xor dx,dx - mov cx,13 - div cx - or al,40h - mov [VFATInit],al - mov [VFATNext],al - pop dx - pop ax - -.scansector: - ; EAX <- directory sector to scan - pm_call get_cache_block - ; GS:SI now points to this sector - - mov cx,SECTOR_SIZE/32 ; 32 == directory entry size -.scanentry: - cmp byte [gs:si],0 - jz .failure ; Hit directory high water mark - cmp word [gs:si+11],0Fh ; Long filename - jne .short_entry - - ; Process a VFAT long entry - pusha - mov al,[gs:si] - cmp al,[VFATNext] - jne .not_us - mov bl,[gs:si+13] - test al,40h - jz .match_csum - ; Get the initial checksum value - mov [VFATCsum],bl - jmp .done_csum -.match_csum: - cmp bl,[VFATCsum] - jne .not_us ; Checksum mismatch -.done_csum: - and ax,03fh - jz .not_us ; Can't be zero... - dec ax - mov [VFATNext],al ; Optimistically... - mov bx,ax - shl bx,2 ; *4 - add ax,bx ; *5 - add bx,bx ; *8 - add bx,ax ; *13 - cmp bx,[NameLen] - jae .not_us - mov di,[NameStart] - inc si - mov cx,13 -.vfat_cmp: - gs lodsw - push bx - cmp bx,[NameLen] - jae .vfat_tail - movzx bx,byte [bx+di] - add bx,bx - cmp ax,[cp_unicode+bx] ; Primary case - je .ucs_ok - cmp ax,[cp_unicode_alt+bx] ; Alternate case - je .ucs_ok - ; Mismatch... - jmp .not_us_pop -.vfat_tail: - ; *AT* the end we should have 0x0000, *AFTER* the end - ; we should have 0xFFFF... - je .vfat_end - inc ax ; 0xFFFF -> 0x0000 -.vfat_end: - and ax,ax - jnz .not_us_pop -.ucs_ok: - pop bx - inc bx - cmp cx,3 - je .vfat_adj_add2 - cmp cx,9 - jne .vfat_adj_add0 -.vfat_adj_add3: inc si -.vfat_adj_add2: inc si -.vfat_adj_add1: inc si -.vfat_adj_add0: - loop .vfat_cmp - ; Okay, if we got here we had a match on this particular - ; entry... live to see another one. - popa - jmp .next_entry - -.not_us_pop: - pop bx -.not_us: - popa - jmp .nomatch - -.short_entry: - test byte [gs:si+11],8 ; Ignore volume labels - jnz .nomatch - - cmp byte [VFATNext],0 ; Do we have a longname match? - jne .no_long_match - - ; We already have a VFAT longname match, however, - ; the match is only valid if the checksum matches - push cx - push si - push ax - xor ax,ax - mov cx,11 -.csum_loop: - gs lodsb - ror ah,1 - add ah,al - loop .csum_loop - cmp ah,[VFATCsum] - pop ax - pop si - pop cx - je .found ; Got a match on longname - -.no_long_match: ; Look for a shortname match - push cx - push si - push di - mov di,MangledBuf - mov cx,11 - gs repe cmpsb - pop di - pop si - pop cx - je .found -.nomatch: - ; Reset the VFAT matching state machine - mov dh,[VFATInit] - mov [VFATNext],dh -.next_entry: - add si,32 - dec cx - jnz .scanentry - - call nextsector - jnc .scansector ; CF is set if we're at end - - ; If we get here, we failed -.failure: - pop es - pop gs - pop cx -.alloc_failure: - pop bx - xor eax,eax ; ZF <- 1 - ret -.found: - mov eax,[gs:si+28] ; File size - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [bx+4],eax ; Sector count - - mov cl,[ClustShift] - mov dx,[gs:si+20] ; High cluster word - shl edx,16 - mov dx,[gs:si+26] ; Low cluster word - sub edx,2 - shl edx,cl - add edx,[DataArea] - mov [bx],edx ; Starting sector - - mov eax,[gs:si+28] ; File length again - mov dl,[gs:si+11] ; File attribute - mov si,bx ; File pointer... - and si,si ; ZF <- 0 - - pop es - pop gs - pop cx - pop bx - ret - - section .data16 - alignz 4 - ; Note: we have no use of the first 32 bytes (header), - ; nor of the folloing 32 bytes (case mapping of control - ; characters), as long as we adjust the offsets appropriately. -codepage equ $-(32+32) -codepage_data: incbin "codepage.cp",32+32 -cp_uppercase equ codepage+cp.uppercase -cp_unicode equ codepage+cp.unicode -cp_unicode_alt equ codepage+cp.unicode_alt -codepage_end equ $ - section .text16 -; -; Input: UCS-2 character in AX -; Output: Single byte character in AL, ZF = 1 -; On failure, returns ZF = 0 -; -ucs2_to_cp: - push es - push di - push cx - push cs - pop es - mov di,cp_unicode - mov cx,512 - repne scasw - xchg ax,cx - pop cx - pop di - pop es - not ax ; Doesn't change the flags! - ret - - section .bss16 -VFATInit resb 1 -VFATNext resb 1 -VFATCsum resb 1 - - section .text16 -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -close_file: - and si,si - jz .closed - mov dword [si],0 ; First dword == file_sector - xor si,si -.closed: ret ; ; close_dir: @@ -623,340 +186,7 @@ close_dir: xor si,si .closed: ret -; -; searchdir: -; -; Open a file -; -; On entry: -; DS:DI = filename -; If successful: -; ZF clear -; SI = file pointer -; EAX = file length in bytes -; If unsuccessful -; ZF set -; -; Assumes CS == DS == ES, and trashes BX and CX. -; -searchdir: - mov eax,[CurrentDir] - cmp byte [di],'/' ; Root directory? - jne .notroot - mov eax,[RootDir] - inc di -.notroot: - -.pathwalk: - push eax ; Current directory sector - mov si,di -.findend: - lodsb - cmp al,' ' - jbe .endpath - cmp al,'/' - jne .findend -.endpath: - xchg si,di ; GRC: si begin; di end[ /]+1 - pop eax ; Current directory sector - - ; GRC Here I need to check if di-1 = si which signifies - ; we have the desired directory in EAX - ; What about where the file name = "."; later - mov dx,di - dec dx - cmp dx,si - jz .founddir - - mov [PrevDir],eax ; Remember last directory searched - - push di - call mangle_dos_name ; MangledBuf <- component - call search_dos_dir - pop di - jz .notfound ; Pathname component missing - - cmp byte [di-1],'/' ; Do we expect a directory - je .isdir - - ; Otherwise, it should be a file -.isfile: - test dl,18h ; Subdirectory|Volume Label - jnz .badfile ; If not a file, it's a bad thing - - ; SI and EAX are already set - mov [si+file_bytesleft],eax - push eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [si+file_left],eax ; Sectors left - pop eax - and eax,eax ; EAX != 0 - jz .badfile - ret ; Done! - - ; If we expected a directory, it better be one... -.isdir: - test dl,10h ; Subdirectory - jz .badfile - - xor eax,eax - xchg eax,[si+file_sector] ; Get sector number and free file structure - jmp .pathwalk ; Walk the next bit of the path - ; Found the desired directory; ZF set but EAX not 0 -.founddir: - ret - -.badfile: - xor eax,eax - mov [si],eax ; Free file structure - -.notfound: - xor eax,eax ; Zero out EAX - ret - -; -; readdir: Read one file from a directory -; -; ES:DI -> String buffer (filename) -; DS:SI -> Pointer to open_file_t -; DS Must be the SYSLINUX Data Segment -; -; Returns the file's name in the filename string buffer -; EAX returns the file size -; EBX returns the beginning sector (currently without offsetting) -; DL returns the file type -; The directory handle's data is incremented to reflect a name read. -; -readdir: - push ecx - push bp ; Using bp to transfer between segment registers - push si - push es - push fs ; Using fs to store the current es (from COMBOOT) - push gs - mov bp,es - mov fs,bp - cmp si,0 - jz .fail -.load_handle: - mov eax,[ds:si+file_sector] ; Current sector - mov ebx,[ds:si+file_bytesleft] ; Current offset - cmp eax,0 - jz .fail -.fetch_cache: - pm_call get_cache_block -.move_current: - add si,bx ; Resume last position in sector - mov ecx,SECTOR_SIZE ; 0 out high part - sub cx,bx - shr cx,5 ; Number of entries left -.scanentry: - cmp byte [gs:si],0 - jz .fail - cmp word [gs:si+11],0Fh ; Long filename - jne .short_entry - -.vfat_entry: - push eax - push ecx - push si - push di -.vfat_ln_info: ; Get info about the line that we're on - mov al,[gs:si] - test al,40h - jz .vfat_tail_ln - and al,03Fh - mov ah,1 ; On beginning line - jmp .vfat_ck_ln - -.vfat_tail_ln: ; VFAT tail line processing (later in VFAT, head in name) - test al,80h ; Invalid data? - jnz .vfat_abort - mov ah,0 ; Not on beginning line - cmp dl,al - jne .vfat_abort ; Is this the entry we need? - mov bl,[gs:si+13] - cmp bl,[VFATCsum] - je .vfat_cp_ln - jmp .vfat_abort - -.vfat_ck_ln: ; Load this line's VFAT CheckSum - mov bl,[gs:si+13] - mov [VFATCsum],bl -.vfat_cp_ln: ; Copy VFAT line - dec al ; Store the next line we need - mov dx,ax ; Use DX to store the progress - mov cx,13 ; 13 characters per VFAT DIRENT - cbw ; AH <- 0 - mul cl ; Offset for DI - add di,ax ; Increment DI - inc si ; Align to the real characters -.vfat_cp_chr: - gs lodsw ; Unicode here!! - call ucs2_to_cp ; Convert to local codepage - jnz .vfat_abort ; Use short name if character not on codepage - stosb ; CAN NOT OVERRIDE es - cmp al,0 - jz .vfat_find_next ; Null-terminated string; don't process more - cmp cx,3 - je .vfat_adj_add2 - cmp cx,9 - jne .vfat_adj_add0 -.vfat_adj_add3: inc si -.vfat_adj_add2: inc si -.vfat_adj_add1: inc si -.vfat_adj_add0: - loop .vfat_cp_chr - cmp dh,1 ; Is this the first round? - jnz .vfat_find_next -.vfat_null_term: ; Need to null-terminate if first line as we rolled over the end - mov al,0 - stosb - -.vfat_find_next: ;Find the next part of the name - pop di - pop si - pop ecx - pop eax - cmp dl,0 - jz .vfat_find_info ; We're done with the name - add si,DIRENT_SIZE - dec cx - jnz .vfat_entry - call nextsector - jnc .vfat_entry ; CF is set if we're at end - jmp .fail -.vfat_find_info: ; Fetch next entry for the size/"INode" - add si,DIRENT_SIZE - dec cx - jnz .get_info - call nextsector - jnc .get_info ; CF is set if we're at end - jmp .fail -.vfat_abort: ; Something went wrong, skip - pop di - pop si - pop ecx - pop eax - jmp .skip_entry - -.short_entry: - test byte [gs:si+11],8 ; Ignore volume labels //HERE - jnz .skip_entry - mov edx,eax ;Save current sector - push cx - push si - push di - mov cx,8 -.short_file: - gs lodsb - cmp al,'.' - jz .short_dot -.short_file_loop: - cmp al,' ' - jz .short_skip_bs - stosb - loop .short_file_loop - jmp .short_period -.short_skip_bs: ; skip blank spaces in FILENAME (before EXT) - add si,cx - dec si -.short_period: - mov al,'.' - stosb - mov cx,3 -.short_ext: - gs lodsb - cmp al,' ' - jz .short_done - stosb - loop .short_ext - jmp .short_done -.short_dot: - stosb - gs lodsb - cmp al,' ' - jz .short_done - stosb -.short_done: - mov al,0 ; Null-terminate the short strings - stosb - pop di - pop si - pop cx - mov eax,edx -.get_info: - mov ebx,[gs:si+28] ; length - mov dl,[gs:si+11] ; type -.next_entry: - add si,DIRENT_SIZE - dec cx - jnz .store_offset - call nextsector - jnc .store_sect ; CF is set if we're at end - jmp .fail - -.skip_entry: - add si,DIRENT_SIZE - dec cx - jnz .scanentry - call nextsector - jnc .scanentry ; CF is set if we're at end - jmp .fail - -.store_sect: - pop gs - pop fs - pop es - pop si - mov [ds:si+file_sector],eax - mov eax,0 ; Now at beginning of new sector - jmp .success - -.store_offset: - pop gs - pop fs - pop es - pop si ; cx=num remain; SECTOR_SIZE-(cx*32)=cur pos - shl ecx,DIRENT_SHIFT - mov eax,SECTOR_SIZE - sub eax,ecx - and eax,0ffffh - -.success: - mov [ds:si+file_bytesleft],eax - ; "INode" number = ((CurSector-RootSector)*SECTOR_SIZE + Offset)/DIRENT_SIZE) - mov ecx,eax - mov eax,[ds:si+file_sector] - sub eax,[RootDir] - shl eax,SECTOR_SHIFT - add eax,ecx - shr eax,DIRENT_SHIFT - dec eax - xchg eax,ebx ; -> EBX=INode, EAX=FileSize - jmp .done - -.fail: - pop gs - pop fs - pop es - pop si - call close_dir - xor eax,eax - stc -.done: - pop bp - pop ecx -.end: - ret - - section .bss16 - alignb 4 -PrevDir resd 1 ; Last scanned directory - - section .text16 ; ; @@ -971,65 +201,13 @@ kaboom2: call getchar call vgaclearmode int 19h ; And try once more to boot... -.norge: jmp short .norge ; If int 19h returned; this is the end +.norge: jmp short .norge ; If int 19h returned; this is the end .int18: call vgaclearmode int 18h -.noreg: jmp short .noreg ; Nynorsk +.noreg: jmp short .noreg ; Nynorsk -; -; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace. -; DI is preserved. -; -; This verifies that a filename is < FILENAME_MAX characters, -; doesn't contain whitespace, zero-pads the output buffer, -; and removes trailing dots and redundant slashes, plus changes -; backslashes to forward slashes, -; so "repe cmpsb" can do a compare, and the path-searching routine -; gets a bit of an easier job. -; -; -mangle_name: - push di - push bx - xor ax,ax - mov cx,FILENAME_MAX-1 - mov bx,di -.mn_loop: - lodsb - cmp al,' ' ; If control or space, end - jna .mn_end - cmp al,'\' ; Backslash? - jne .mn_not_bs - mov al,'/' ; Change to forward slash -.mn_not_bs: - cmp al,ah ; Repeated slash? - je .mn_skip - xor ah,ah - cmp al,'/' - jne .mn_ok - mov ah,al -.mn_ok stosb -.mn_skip: loop .mn_loop -.mn_end: - cmp bx,di ; At the beginning of the buffer? - jbe .mn_zero - cmp byte [es:di-1],'.' ; Terminal dot? - je .mn_kill - cmp byte [es:di-1],'/' ; Terminal slash? - jne .mn_zero -.mn_kill: dec di ; If so, remove it - inc cx - jmp short .mn_end -.mn_zero: - inc cx ; At least one null byte - xor ax,ax ; Zero-fill name - rep stosb - pop bx - pop di - ret ; Done ; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled @@ -1048,318 +226,7 @@ unmangle_name: call strcpy dec di ; Point to final null byte ret -; -; mangle_dos_name: -; Mangle a DOS filename component pointed to by DS:SI -; into [MangledBuf]; ends on encountering any whitespace or -; slash. -; -; WARNING: saves pointers into the buffer for longname -; matches! -; -; Assumes CS == DS == ES. -; - -mangle_dos_name: - pusha - mov di,MangledBuf - mov [NameStart],si - - mov cx,11 ; # of bytes to write - mov bx,cp_uppercase ; Case-conversion table -.loop: - lodsb - cmp al,' ' ; If control or space, end - jna .end - cmp al,'/' ; Slash, too - je .end - cmp al,'.' ; Period -> space-fill - je .is_period - xlatb ; Convert to upper case - mov ah,cl ; If the first byte (only!)... - cmp ax,0BE5h ; ... equals E5 hex ... - jne .charok - mov al,05h ; ... change it to 05 hex -.charok: stosb - loop .loop ; Don't continue if too long - ; Find the end for the benefit of longname search -.find_end: - lodsb - cmp al,' ' - jna .end - cmp al,'/' - jne .find_end -.end: - dec si - sub si,[NameStart] - mov [NameLen],si - mov al,' ' ; Space-fill name - rep stosb ; Doesn't do anything if CX=0 - popa - ret ; Done - -.is_period: - mov al,' ' ; We need to space-fill -.period_loop: cmp cx,3 ; If <= 3 characters left - jbe .loop ; Just ignore it - stosb ; Otherwise, write a space - loop .period_loop ; Dec CX and *always* jump - - section .bss16 - alignb 2 -NameStart resw 1 -NameLen resw 1 -MangledBuf resb 11 - - section .text16 -; -; getfssec_edx: Get multiple sectors from a file -; -; This routine makes sure the subtransfers do not cross a 64K boundary, -; and will correct the situation if it does, UNLESS *sectors* cross -; 64K boundaries. -; -; ES:BX -> Buffer -; EDX -> Current sector number -; CX -> Sector count (0FFFFh = until end of file) -; Must not exceed the ES segment -; Returns EDX=0, CF=1 on EOF (not necessarily error) -; All arguments are advanced to reflect data read. -; -getfssec_edx: - push ebp - push eax -.getfragment: - xor ebp,ebp ; Fragment sector count - push edx ; Starting sector pointer -.getseccnt: - inc bp - dec cx - jz .do_read - xor eax,eax - mov ax,es - shl ax,4 - add ax,bx ; Now AX = how far into 64K block we are - not ax ; Bytes left in 64K block - inc eax - shr eax,SECTOR_SHIFT ; Sectors left in 64K block - cmp bp,ax - jnb .do_read ; Unless there is at least 1 more sector room... - mov eax,edx ; Current sector - inc edx ; Predict it's the linearly next sector - call nextsector - jc .do_read - cmp edx,eax ; Did it match? - jz .getseccnt -.do_read: - pop eax ; Starting sector pointer - call getlinsecsr - lea eax,[eax+ebp-1] ; This is the last sector actually read - shl bp,9 - add bx,bp ; Adjust buffer pointer - call nextsector - jc .eof - mov edx,eax - and cx,cx - jnz .getfragment -.done: - pop eax - pop ebp - ret -.eof: - xor edx,edx - stc - jmp .done - -; -; getfssec: Get multiple sectors from a file -; -; Same as above, except SI is a pointer to a open_file_t -; -; ES:BX -> Buffer -; DS:SI -> Pointer to open_file_t -; CX -> Sector count (0FFFFh = until end of file) -; Must not exceed the ES segment -; Returns CF=1 on EOF (not necessarily error) -; ECX returns number of bytes read. -; All arguments are advanced to reflect data read. -; -getfssec: - push edx - movzx edx,cx - push edx ; Zero-extended CX - cmp edx,[si+file_left] - jbe .sizeok - mov edx,[si+file_left] - mov cx,dx -.sizeok: - sub [si+file_left],edx - mov edx,[si+file_sector] - call getfssec_edx - mov [si+file_sector],edx - pop ecx ; Sectors requested read - shl ecx,SECTOR_SHIFT - cmp ecx,[si+file_bytesleft] - ja .eof -.noteof: - sub [si+file_bytesleft],ecx ; CF <- 0 - pop edx - ret -.eof: - mov ecx,[si+file_bytesleft] - call close_file - pop edx - stc - ret - -; -; nextcluster: Advance a cluster pointer in EDI to the next cluster -; pointed at in the FAT tables. CF=0 on return if end of file. -; -nextcluster: - jmp strict short nextcluster_fat28 ; This gets patched - -nextcluster_fat12: - push eax - push edx - push bx - push cx - push si - mov edx,edi - shr edi,1 - pushf ; Save the shifted-out LSB (=CF) - add edx,edi - mov eax,edx - shr eax,9 - call getfatsector - mov bx,dx - and bx,1FFh - mov cl,[gs:si+bx] - inc edx - mov eax,edx - shr eax,9 - call getfatsector - mov bx,dx - and bx,1FFh - mov ch,[gs:si+bx] - popf - jnc .even - shr cx,4 -.even: and cx,0FFFh - movzx edi,cx - cmp di,0FF0h - pop si - pop cx - pop bx - pop edx - pop eax - ret - -; -; FAT16 decoding routine. -; -nextcluster_fat16: - push eax - push si - push bx - mov eax,edi - shr eax,SECTOR_SHIFT-1 - call getfatsector - mov bx,di - add bx,bx - and bx,1FEh - movzx edi,word [gs:si+bx] - cmp di,0FFF0h - pop bx - pop si - pop eax - ret -; -; FAT28 ("FAT32") decoding routine. -; -nextcluster_fat28: - push eax - push si - push bx - mov eax,edi - shr eax,SECTOR_SHIFT-2 - call getfatsector - mov bx,di - add bx,bx - add bx,bx - and bx,1FCh - mov edi,dword [gs:si+bx] - and edi,0FFFFFFFh ; 28 bits only - cmp edi,0FFFFFF0h - pop bx - pop si - pop eax - ret - -; -; nextsector: Given a sector in EAX on input, return the next sector -; of the same filesystem object, which may be the root -; directory or a cluster chain. Returns EOF. -; -; Assumes CS == DS. -; -nextsector: - push edi - push edx - mov edx,[DataArea] - mov edi,eax - sub edi,edx - jae .isdata - - ; Root directory - inc eax - cmp eax,edx - cmc - jmp .done - -.isdata: - not edi - test edi,[ClustMask] - jz .endcluster - - ; It's not the final sector in a cluster - inc eax - jmp .done - -.endcluster: - push gs ; nextcluster trashes gs - push cx - not edi - mov cl,[ClustShift] - shr edi,cl - add edi,2 - - ; Now EDI contains the cluster number - call nextcluster - cmc - jc .exit ; There isn't anything else... - - ; New cluster number now in EDI - sub edi,2 - shl edi,cl ; CF <- 0, unless something is very wrong - lea eax,[edi+edx] -.exit: - pop cx - pop gs -.done: - pop edx - pop edi - ret - -; -; getfatsector: Check for a particular sector (in EAX) in the FAT cache, -; and return a pointer in GS:SI, loading it if needed. -; -; Assumes CS == DS. -; -getfatsector: - add eax,[FAT] ; FAT starting address - pm_call get_cache_block + ; ----------------------------------------------------------------------------- ; Common modules -- cgit v1.2.1 From 9f3c0b060e9d1b54263acac245df30552a9b6bce Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 15 Jun 2009 12:25:07 +0800 Subject: Core:SYSLINUX: rm the __lowemem stuff --- core/include/fat_fs.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/include/fat_fs.h b/core/include/fat_fs.h index 0f7176b6..71c1d9a7 100644 --- a/core/include/fat_fs.h +++ b/core/include/fat_fs.h @@ -108,10 +108,6 @@ struct fat_long_name_entry { uint16_t name3[2]; } __attribute__ ((packed)); -__lowmem char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; -__lowmem char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; -__lowmem char syslinux_cfg3[] = "/syslinux.cfg"; -__lowmem char config_name[] = "syslinux.cfg"; -- cgit v1.2.1 From 9b298f3e7fdf50fbb1f0bcc188f2dc3f9eea25d4 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 15 Jun 2009 13:32:44 +0800 Subject: Core:EXTLINUX: clean the code remove some unused variables in extlinux.asm and remove some extern statement in ext2.c --- core/ext2.c | 51 +++++++++++++++++++++++---------------------------- core/extlinux.asm | 34 +--------------------------------- 2 files changed, 24 insertions(+), 61 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index f6217b87..ae300218 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -25,18 +25,16 @@ struct open_file_t { }; extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; -extern char ThisInode[128]; -struct ext2_inode *this_inode = (struct ext2_inode *)ThisInode; -struct ext2_super_block *sb; - -extern uint16_t ClustByteShift, ClustShift; -extern uint32_t SecPerClust, ClustSize, ClustMask; -extern uint32_t PtrsPerBlock1, PtrsPerBlock2; -uint32_t PtrsPerBlock3; +struct ext2_inode this_inode; +struct ext2_super_block sb; + +uint16_t ClustByteShift, ClustShift; +uint32_t SecPerClust, ClustSize, ClustMask; +uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; int DescPerBlock, InodePerBlock; extern char trackbuf[8192]; -extern char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; +char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; @@ -159,7 +157,7 @@ struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) block_num = group_num / DescPerBlock; offset = group_num % DescPerBlock; - block_num += sb->s_first_data_block + 1; + block_num += sb.s_first_data_block + 1; cs = get_cache_block(fs->fs_dev, block_num); desc = (struct ext2_group_desc *)cs->data + offset; @@ -193,11 +191,11 @@ void read_inode(struct fs_info *fs, uint32_t inode_offset, cs = get_cache_block(fs->fs_dev, *block); /* well, in EXT4, the inode structure usually be 256 */ - inode = (struct ext2_inode *)(cs->data + (*offset * (sb->s_inode_size))); + inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size))); memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE); /* for file structure */ - *offset = (inode_offset * sb->s_inode_size) % ClustSize; + *offset = (inode_offset * sb.s_inode_size) % ClustSize; } @@ -228,19 +226,19 @@ struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file file->file_sector = 0; inr --; - inode_group = inr / sb->s_inodes_per_group; + inode_group = inr / sb.s_inodes_per_group; /* get the group desc */ desc = get_group_desc(fs, inode_group); - inode_offset = inr % sb->s_inodes_per_group; - read_inode(fs, inode_offset, this_inode, desc, &block_num, &block_off); + inode_offset = inr % sb.s_inodes_per_group; + read_inode(fs, inode_offset, &this_inode, desc, &block_num, &block_off); /* Finally, we need to convet it to sector for now */ file->file_in_sec = (block_num<>SECTOR_SHIFT); file->file_in_off = block_off & (SECTOR_SIZE - 1); - file->file_mode = this_inode->i_mode; - *file_len = file->file_bytesleft = this_inode->i_size; + file->file_mode = this_inode.i_mode; + *file_len = file->file_bytesleft = this_inode.i_size; if (*file_len == 0) return NULL; @@ -397,7 +395,7 @@ sector_t linsector(struct fs_info *fs, sector_t lin_sector) struct ext2_inode *inode; /* well, this is what I think the variable this_inode used for */ - inode = this_inode; + inode = &this_inode; if (inode->i_flags & EXT4_EXTENTS_FLAG) block = linsector_extent(fs, block, inode); @@ -588,11 +586,11 @@ char* do_symlink(struct fs_info *fs, struct open_file_t *file, char *lnk_end; char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; - flag = this_inode->i_file_acl ? SecPerClust : 0; - if (this_inode->i_blocks == flag) { + flag = this_inode.i_file_acl ? SecPerClust : 0; + if (this_inode.i_blocks == flag) { /* fast symlink */ close_file(file); /* we've got all we need */ - memcpy(SymlinkTmpBuf, this_inode->i_block, file_len); + memcpy(SymlinkTmpBuf, this_inode.i_block, file_len); lnk_end = SymlinkTmpBuf + file_len; } else { @@ -733,7 +731,7 @@ void ext2_load_config(com32sys_t *regs) strcpy(ConfigName, config_name); *(uint32_t *)CurrentDirName = 0x00002f2e; - regs->edi.w[0] = ConfigName; + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); memset(&out_regs, 0, sizeof out_regs); call16(core_open, regs, &out_regs); @@ -752,18 +750,15 @@ void ext2_load_config(com32sys_t *regs) */ int ext2_fs_init(void) { - extern char SuperBlock[1024]; - /* read the super block */ - read_sectors(SuperBlock, 2, 2); - sb = (struct ext2_super_block *) SuperBlock; + read_sectors((char *)&sb, 2, 2); - ClustByteShift = sb->s_log_block_size + 10; + ClustByteShift = sb.s_log_block_size + 10; ClustSize = 1 << ClustByteShift; ClustShift = ClustByteShift - SECTOR_SHIFT; DescPerBlock = ClustSize >> ext2_group_desc_lg2size; - InodePerBlock = ClustSize / sb->s_inode_size; + InodePerBlock = ClustSize / sb.s_inode_size; SecPerClust = ClustSize >> SECTOR_SHIFT; ClustMask = SecPerClust - 1; diff --git a/core/extlinux.asm b/core/extlinux.asm index be256cf5..9f623ad4 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -18,7 +18,6 @@ %define IS_EXTLINUX 1 %include "head.inc" -%include "ext2_fs.inc" ; ; Some semi-configurable constants... change on your own risk. @@ -39,13 +38,6 @@ MAX_OPEN equ (1 << MAX_OPEN_LG2) SECTOR_SHIFT equ 9 SECTOR_SIZE equ (1 << SECTOR_SHIFT) -MAX_SYMLINKS equ 64 ; Maximum number of symlinks per lookup -SYMLINK_SECTORS equ 2 ; Max number of sectors in a symlink - ; (should be >= FILENAME_MAX) - -ROOT_DIR_WORD equ 0x002F -CUR_DIR_DWORD equ 0x00002F2E - ; ; The following structure is used for "virtual kernels"; i.e. LILO-style ; option labels. The options we permit here are `kernel' and `append @@ -94,17 +86,7 @@ trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h section .bss16 - global SuperBlock, ClustSize, ClustMask, PtrsPerBlock1 - global PtrsPerBlock2, ClustShift, ClustByteShift -SuperBlock resb 1024 ; ext2 superblock -ClustSize resd 1 ; Bytes/cluster ("block") -ClustMask resd 1 ; Sectors/cluster - 1 -PtrsPerBlock1 resd 1 ; Pointers/cluster -PtrsPerBlock2 resd 1 ; (Pointers/cluster)^2 -ClustShift resb 1 ; Shift count for sectors/cluster -ClustByteShift resb 1 ; Shift count for bytes/cluster - - alignb open_file_t_size + alignb 16 global Files Files resb MAX_OPEN*open_file_t_size @@ -153,20 +135,6 @@ Files resb MAX_OPEN*open_file_t_size %include "ui.inc" - section .bss16 - alignb 4 - global ThisInode -ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode - - - section .bss16 - alignb 4 - global SymlinkBuf -SymlinkBuf resb SYMLINK_SECTORS*SECTOR_SIZE+64 -ThisDir resd 1 - - - section .text16 ; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled ; filename to the conventional representation. This is needed -- cgit v1.2.1 From a5f4a37ff9fd6a9f94cb853878bc875d4cee8821 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 15 Jun 2009 14:18:40 +0800 Subject: Core:EXTLINUX: removes the open_file_t structure --- core/extlinux.asm | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/core/extlinux.asm b/core/extlinux.asm index 9f623ad4..27fbc3e6 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -55,22 +55,7 @@ vk_append: resb max_cmd_len+1 ; Command line vk_end: equ $ ; Should be <= vk_size endstruc -; -; File structure. This holds the information for each currently open file. -; - struc open_file_t -file_bytesleft resd 1 ; Number of bytes left (0 = free) -file_sector resd 1 ; Next linear sector to read -file_in_sec resd 1 ; Sector where inode lives -file_in_off resw 1 -file_mode resw 1 - endstruc -%ifndef DEPEND -%if (open_file_t_size & (open_file_t_size-1)) -%error "open_file_t is not a power of 2" -%endif -%endif ; --------------------------------------------------------------------------- ; BEGIN CODE @@ -88,7 +73,7 @@ trackbuf resb trackbufsize ; Track buffer goes here section .bss16 alignb 16 global Files -Files resb MAX_OPEN*open_file_t_size +Files resb MAX_OPEN*16 ; 16 == open_file_t_size ; ; Common bootstrap code for disk-based derivatives -- cgit v1.2.1 From 07a7e66063aa30ac93ac39ad921e066bb81146ac Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 15 Jun 2009 14:54:17 +0800 Subject: Core:SYSLINUX: code clean removes the unused variables in ldlinux.asm --- core/ldlinux.asm | 56 +++----------------------------------------------------- 1 file changed, 3 insertions(+), 53 deletions(-) diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 0f207248..5c449044 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -45,10 +45,7 @@ MAX_OPEN equ (1 << MAX_OPEN_LG2) SECTOR_SHIFT equ 9 SECTOR_SIZE equ (1 << SECTOR_SHIFT) -DIRENT_SHIFT equ 5 -DIRENT_SIZE equ (1 << DIRENT_SHIFT) -ROOT_DIR_WORD equ 0x002F ; ; The following structure is used for "virtual kernels"; i.e. LILO-style @@ -67,32 +64,7 @@ vk_append: resb max_cmd_len+1 ; Command line vk_end: equ $ ; Should be <= vk_size endstruc -; -; File structure. This holds the information for each currently open file. -; - struc open_file_t -file_sector resd 1 ; Sector pointer (0 = structure free) -file_bytesleft resd 1 ; Number of bytes left -file_left resd 1 ; Number of sectors left - resd 1 ; Unused - endstruc -; -; Structure for codepage files -; - struc cp -.magic resd 2 ; 8-byte magic number -.reserved resd 6 ; Reserved for future use -.uppercase resb 256 ; Internal upper-case table -.unicode resw 256 ; Unicode matching table -.unicode_alt resw 256 ; Alternate Unicode matching table - endstruc - -%ifndef DEPEND -%if (open_file_t_size & (open_file_t_size-1)) -%error "open_file_t is not a power of 2" -%endif -%endif ; --------------------------------------------------------------------------- ; BEGIN CODE @@ -107,25 +79,9 @@ trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h section .bss16 - alignb 4 -FAT resd 1 ; Location of (first) FAT -RootDirArea resd 1 ; Location of root directory area -RootDir resd 1 ; Location of root directory proper -DataArea resd 1 ; Location of data area -RootDirSize resd 1 ; Root dir size in sectors -TotalSectors resd 1 ; Total number of sectors -ClustSize resd 1 ; Bytes/cluster -ClustMask resd 1 ; Sectors/cluster - 1 -CopySuper resb 1 ; Distinguish .bs versus .bss -ClustShift resb 1 ; Shift count for sectors/cluster -ClustByteShift resb 1 ; Shift count for bytes/cluster - -; global syslinux_cfg_buffer -;syslinux_cfg_buffer resb 28 ; the syslinux config file name buffer, used by vfat_load_config - - alignb open_file_t_size + alignb 16 global Files -Files resb MAX_OPEN*open_file_t_size +Files resb MAX_OPEN*16 ; 16 == open_file_t_size ; ; Common bootstrap code for disk-based derivatives @@ -172,8 +128,7 @@ Files resb MAX_OPEN*open_file_t_size ; %include "ui.inc" - section .text16 - + ; ; close_dir: ; Deallocates a directory structure (pointer in SI) @@ -248,11 +203,6 @@ copyright_str db ' Copyright (C) 1994-' db ' H. Peter Anvin et al', CR, LF, 0 err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' db 'a key to continue.', CR, LF, 0 -syslinux_cfg1 db '/boot' ; /boot/syslinux/syslinux.cfg -syslinux_cfg2 db '/syslinux' ; /syslinux/syslinux.cfg -syslinux_cfg3 db '/' ; /syslinux.cfg -config_name db 'syslinux.cfg', 0 ; syslinux.cfg - ; ; Config file keyword table ; -- cgit v1.2.1 From b47f43fae78efd41486f2de2d6ee099654008cdb Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 15 Jun 2009 15:19:01 +0800 Subject: Core:SYSLINUX: applies the sector_t data types Applies the sector_t data types and makes come code clean --- core/fat.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/core/fat.c b/core/fat.c index 87e9c0a7..2a099d61 100644 --- a/core/fat.c +++ b/core/fat.c @@ -30,10 +30,10 @@ struct fat_bpb fat; int FATType = 0; /* generic information about FAT fs */ -uint32_t FAT; /* Location of (first) FAT */ -uint32_t RootDirArea; /* Location of root directory area */ -uint32_t RootDir; /* Location of root directory proper */ -uint32_t DataArea; /* Location of data area */ +sector_t FAT; /* Location of (first) FAT */ +sector_t RootDirArea; /* Location of root directory area */ +sector_t RootDir; /* Location of root directory proper */ +sector_t DataArea; /* Location of data area */ uint32_t TotalSectors; /* Total number of sectors */ uint32_t ClustSize; /* Bytes/cluster */ uint32_t ClustMask; /* Sector/cluster - 1 */ @@ -48,6 +48,9 @@ int PrevDir; /* used for long name entry */ char MangleBuf[12]; char entry_name[14]; + +/* try with the biggest long name */ +char long_name[0x40 * 13]; char *NameStart; int NameLen; @@ -153,7 +156,7 @@ void close_dir(struct fat_dir_entry *dir) * check for a particular sector in the FAT cache. * */ -struct cache_struct *getfatsector(struct fs_info *fs, uint32_t sector) +struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) { return get_cache_block(fs->fs_dev, FAT + sector); } @@ -173,7 +176,7 @@ struct cache_struct *getfatsector(struct fs_info *fs, uint32_t sector) static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) { uint32_t next_cluster; - uint32_t fat_sector; + sector_t fat_sector; uint32_t offset; int lo, hi; struct cache_struct *cs; @@ -241,9 +244,9 @@ static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) * cluster chain. Returns EOF. * */ -static uint32_t nextsector(struct fs_info *fs, uint32_t sector) +static sector_t nextsector(struct fs_info *fs, sector_t sector) { - uint32_t data_sector; + sector_t data_sector; uint32_t cluster; if ( sector < DataArea ) { @@ -288,8 +291,8 @@ static uint32_t nextsector(struct fs_info *fs, uint32_t sector) */ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, uint32_t sectors) { - uint32_t curr_sector = file->file_sector; - uint32_t frag_start , next_sector; + sector_t curr_sector = file->file_sector; + sector_t frag_start , next_sector; uint32_t con_sec_cnt; while (sectors) { @@ -514,7 +517,8 @@ static uint8_t get_checksum(char *dir_name) return sum; } -static inline uint32_t first_sector(struct fat_dir_entry *dir) +/* compute the first sector number of one dir where the data stores */ +static inline sector_t first_sector(struct fat_dir_entry *dir) { uint32_t first_clust, sector; @@ -525,9 +529,6 @@ static inline uint32_t first_sector(struct fat_dir_entry *dir) } -/* try with the biggest long name */ -char long_name[0x40 * 13]; - /** * search_dos_dir: * @@ -675,7 +676,7 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, */ void vfat_searchdir(char *filename, struct file *file) { - uint32_t dir_sector; + sector_t dir_sector; uint32_t file_len = 0; uint8_t attr = 0; char *p; -- cgit v1.2.1 From 6a0cf5f86ec1efd9ea05e6449f7ec0f97d28c594 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 16 Jun 2009 07:42:07 +0800 Subject: core: new diskio library Beginnings of a diskio library capable of reading and writing, and with proper handling of bounce buffers and segment boundaries. Signed-off-by: H. Peter Anvin --- core/fs.c | 3 --- core/include/disk.h | 6 ++++-- core/include/fs.h | 13 +++++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/core/fs.c b/core/fs.c index 617e3e5e..d2a82c36 100644 --- a/core/fs.c +++ b/core/fs.c @@ -126,9 +126,6 @@ void device_init(struct device *dev, uint8_t device_num, sector_t offset) dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; - - /* I just considered the floppy and disk now */ - dev->read_sectors = read_sectors; } diff --git a/core/include/disk.h b/core/include/disk.h index 44a425f8..1eb9f038 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -1,11 +1,13 @@ #ifndef DISK_H #define DISK_H +#include + #define SECTOR_SHIFT 9 #define SECTOR_SIZE (1 << SECTOR_SHIFT) -typedef unsigned int sector_t; -typedef unsigned int block_t; +typedef uint64_t sector_t; +typedef uint32_t block_t; extern void read_sectors(char *, sector_t, int); extern void getoneblk(char *, block_t, int); diff --git a/core/include/fs.h b/core/include/fs.h index 0cb1bfc6..0c837bd7 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -1,6 +1,8 @@ #ifndef FS_H #define FS_H +#include +#include #include #include "core.h" #include "disk.h" @@ -15,7 +17,7 @@ struct fs_info { struct device *fs_dev; }; -struct file{ +struct file { void* open_file; /* points to the fs-specific open_file_t */ struct fs_info *fs; uint32_t file_len; @@ -58,11 +60,16 @@ struct device { /* the sector size, 512B for disk and floppy, 2048B for CD */ uint16_t sector_size; + uint8_t sector_shift; + + /* CHS geometry */ + uint8_t h, s; + uint8_t pad1; /* the start address of this partition(in sectors) */ sector_t part_start; - void (*read_sectors)(char *, sector_t, int ); + int (*rdwr_sectors)(struct device *, void *, sector_t, size_t, bool); /* * I think we still need the cache_data filed here, 'cause hpa said @@ -76,6 +83,4 @@ struct device { uint32_t cache_size; }; - - #endif /* FS_H */ -- cgit v1.2.1 From f6528168f826c8e1d8acf45f8b1443000314be58 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 20 Jun 2009 15:34:12 +0800 Subject: Core:EXTLINUX: applies the path from hpa to EXTLINUX I just added it to EXTLINUX first, and I will consider if I should added it SYLSINUX and ISOLINUX and so on tomorrow (I'm not sure for now). And I added a new structure disk to store the disk specific information, so some changes happened on the vfs-like interface. Hope you will like it, hap;) the new code broken on the non-standard disk geometry, like the exttest package given by hpa. --- core/diskio.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++++ core/diskstart.inc | 10 +- core/ext2.c | 11 +- core/fs.c | 33 +++--- core/include/disk.h | 27 ++++- core/include/fs.h | 47 ++------- 6 files changed, 361 insertions(+), 62 deletions(-) create mode 100644 core/diskio.c diff --git a/core/diskio.c b/core/diskio.c new file mode 100644 index 00000000..8b33d8a7 --- /dev/null +++ b/core/diskio.c @@ -0,0 +1,295 @@ +#include +#include +#include +#include +#include "core.h" +#include "fs.h" +#include "disk.h" + +#define RETRY_COUNT 6 + +extern uint16_t MaxTransfer; + +static int chs_rdwr_sectors(struct disk *disk, void *buf, + sector_t lba, size_t count, bool is_write) +{ + char *ptr = buf; + char *tptr; + size_t chunk, freeseg; + int sector_size = disk->sector_size; + int sector_shift = disk->sector_shift; + uint32_t xlba = lba; /* Truncated LBA (CHS is << 2 TB) */ + uint32_t t; + uint16_t c, h, s; + com32sys_t ireg, oreg; + size_t done = 0; + size_t bytes; + int retry; + + memset(&ireg, 0, sizeof ireg); + + ireg.eax.b[1] = 0x02 + is_write; + ireg.edx.b[0] = disk->disk_number; + + while (count) { + chunk = count; + if (chunk > MaxTransfer) + chunk = MaxTransfer; + + freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift; + + if ((size_t)buf <= 0xf0000 && freeseg) { + /* Can do a direct load */ + tptr = ptr; + } else { + /* Either accessing high memory or we're crossing a 64K line */ + tptr = core_xfer_buf; + freeseg = (0x10000 - ((size_t)tptr & 0xffff)) >> sector_shift; + } + if (chunk > freeseg) + chunk = freeseg; + + bytes = chunk << sector_shift; + + if (tptr != ptr && is_write) + memcpy(tptr, ptr, bytes); + + s = xlba % disk->s; + t = xlba / disk->s; + h = t % disk->h; + c = t / disk->h; + + ireg.eax.b[0] = chunk; + ireg.ecx.b[1] = c; + ireg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1); + ireg.edx.b[1] = h; + ireg.ebx.w[0] = OFFS(tptr); + ireg.es = SEG(tptr); + + retry = RETRY_COUNT; + + for (;;) { + __intcall(0x13, &ireg, &oreg); + if (!(oreg.eflags.l & EFLAGS_CF)) + break; + if (retry--) + continue; + chunk >>= 1; + if (chunk) { + MaxTransfer = chunk; + retry = RETRY_COUNT; + continue; + } + return done; /* Failure */ + } + + bytes = chunk << sector_shift; + + if (tptr != ptr && !is_write) + memcpy(ptr, tptr, bytes); + + ptr += bytes; + xlba += chunk; + count -= chunk; + done += chunk; + } + return done; +} + +struct edd_rdwr_packet { + uint16_t size; + uint16_t blocks; + far_ptr_t buf; + uint64_t lba; +}; + +static int edd_rdwr_sectors(struct disk *disk, void *buf, + sector_t lba, size_t count, bool is_write) +{ + static __lowmem struct edd_rdwr_packet pkt; + char *ptr = buf; + char *tptr; + size_t chunk, freeseg; + int sector_size = disk->sector_size; + int sector_shift = disk->sector_shift; + com32sys_t ireg, oreg; + size_t done = 0; + size_t bytes; + int retry; + + memset(&ireg, 0, sizeof ireg); + + ireg.eax.b[1] = 0x42 + is_write; + ireg.edx.b[0] = disk->disk_number; + ireg.ds = SEG(&pkt); + ireg.esi.w[0] = OFFS(&pkt); + + while (count) { + chunk = count; + if (chunk > MaxTransfer) + chunk = MaxTransfer; + + freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift; + + if ((size_t)buf <= 0xf0000 && freeseg) { + /* Can do a direct load */ + tptr = ptr; + } else { + /* Either accessing high memory or we're crossing a 64K line */ + tptr = core_xfer_buf; + freeseg = (0x10000 - ((size_t)tptr & 0xffff)) >> sector_shift; + } + if (chunk > freeseg) + chunk = freeseg; + + bytes = chunk << sector_shift; + + if (tptr != ptr && is_write) + memcpy(tptr, ptr, bytes); + + pkt.size = sizeof pkt; + pkt.blocks = chunk; + pkt.buf = FAR_PTR(tptr); + pkt.lba = lba; + + retry = RETRY_COUNT; + + for (;;) { + __intcall(0x13, &ireg, &oreg); + if (!(oreg.eflags.l & EFLAGS_CF)) + break; + if (retry--) + continue; + chunk >>= 1; + if (chunk) { + MaxTransfer = chunk; + retry = RETRY_COUNT; + continue; + } + /*** XXX: Consider falling back to CHS here?! ***/ + return done; /* Failure */ + } + + bytes = chunk << sector_shift; + + if (tptr != ptr && !is_write) + memcpy(ptr, tptr, bytes); + + ptr += bytes; + lba += chunk; + count -= chunk; + done += chunk; + } + return done; +} +struct edd_disk_params { + uint16_t len; + uint16_t flags; + uint32_t phys_c; + uint32_t phys_h; + uint32_t phys_s; + uint64_t sectors; + uint16_t sector_size; + far_ptr_t dpte; + uint16_t devpath_key; + uint8_t devpath_len; + uint8_t _pad1[3]; + char bus_type[4]; + char if_type[8]; + uint8_t if_path[8]; + uint8_t dev_path[8]; + uint8_t _pad2; + uint8_t devpath_csum; +} __attribute__((packed)); + +static inline bool is_power_of_2(uint32_t x) +{ + return !(x & (x-1)); +} + +int ilog2(uint32_t num) +{ + int i = 0; + + if (!is_power_of_2(num)) { + printf("ERROR: the num must be power of 2 when conveting to log2\n"); + return 0; + } + while (num >>= 1) + i++; + return i; +} + +void dump_disk(struct disk *disk) +{ + printf("drive number: 0x%x\n", disk->disk_number); + printf("disk type: %s(%d)\n", disk->type ? "EDD" : "CHS", disk->type); + printf("sector size: %d(%d)\n", disk->sector_size, disk->sector_shift); + printf("h: %d\ts: %d\n", disk->h, disk->s); + printf("offset: %d\n", disk->part_start); + printf("%s\n", disk->rdwr_sectors == edd_rdwr_sectors ? "EDD_RDWR_SECTORS" : + "CHS_RDWR_SECTORS"); +} + +struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, + uint16_t bsHeads, uint16_t bsSecPerTrack) +{ + static struct disk disk; + static __lowmem struct edd_disk_params edd_params; + com32sys_t ireg, oreg; + bool ebios = cdrom; + int sector_size = cdrom ? 2048 : 512; + + memset(&ireg, 0, sizeof ireg); + + /* Get EBIOS support */ + ireg.eax.b[1] = 0x41; + ireg.ebx.w[0] = 0x55aa; + ireg.edx.b[0] = devno; + ireg.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &ireg, &oreg); + + if (cdrom || (!(oreg.eflags.l & EFLAGS_CF) && + oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1))) { + /* Query EBIOS parameters */ + ireg.eax.b[1] = 0x48; + ireg.ds = SEG(&edd_params); + ireg.esi.w[0] = OFFS(&edd_params); + __intcall(0x13, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) { + ebios = true; + if (edd_params.sector_size >= 512 && + is_power_of_2(edd_params.sector_size)) + sector_size = edd_params.sector_size; + } + } + + /* CBIOS parameters */ + disk.h = bsHeads; + disk.s = bsSecPerTrack; + + if ((int8_t)devno < 0) { + /* Get hard disk geometry from BIOS */ + + ireg.eax.b[1] = 0x08; + __intcall(0x13, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF)) { + disk.h = oreg.edx.b[1] + 1; + disk.s = oreg.ecx.b[0] & 63; + } + } + + disk.disk_number = devno; + disk.type = ebios; + disk.sector_size = sector_size; + disk.sector_shift = ilog2(sector_size); + disk.part_start = part_start; + disk.rdwr_sectors = ebios ? edd_rdwr_sectors : chs_rdwr_sectors; + + dump_disk(&disk); + + return &disk; +} diff --git a/core/diskstart.inc b/core/diskstart.inc index a08aa281..e6cd2ab1 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -455,6 +455,7 @@ bailmsg: db 'Boot error', 0Dh, 0Ah, 0 zb 1F8h-($-$$) FirstSector dd 0xDEADBEEF ; Location of sector 1 + global MaxTransfer MaxTransfer dw 0x007F ; Max transfer size ; This field will be filled in 0xAA55 by the installer, but we abuse it @@ -713,7 +714,8 @@ expand_super: %include "init.inc" %include "cpuinit.inc" - + + pushad %if IS_PXELINUX extern pxe_fs_ops mov eax,pxe_fs_ops @@ -729,7 +731,11 @@ expand_super: mov eax,iso_fs_ops %endif mov dl,[DriveNumber] + mov dh,0 ; we are boot from disk not CDROM mov ecx,[bsHidden] mov ebx,[bsHidden+4] + mov si,[bsHeads] + mov di,[bsSecPerTrack] %endif - pm_call fs_init + pm_call fs_init + popad diff --git a/core/ext2.c b/core/ext2.c index ae300218..0ddda8ee 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -442,7 +442,8 @@ inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) * n ext2 block pointer, i.e. anything *except the superblock * */ -void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) +void getlinsec_ext(struct fs_info *fs, char *buf, + sector_t sector, int sector_cnt) { int ext_cnt = 0; @@ -454,7 +455,7 @@ void getlinsec_ext(char *buf, sector_t sector, int sector_cnt) sector += ext_cnt; sector_cnt -= ext_cnt; - read_sectors(buf, sector, sector_cnt); + fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, buf, sector, sector_cnt, 0); } /** @@ -516,7 +517,7 @@ uint32_t ext2_getfssec(struct fs_info *fs, char *buf, printf("You are reading stores at sector --0x%x--0x%x\n", frag_start, frag_start + con_sec_cnt -1); #endif - getlinsec_ext(buf, frag_start, con_sec_cnt); + getlinsec_ext(fs, buf, frag_start, con_sec_cnt); buf += con_sec_cnt << 9; file->file_sector += con_sec_cnt; /* next sector index */ }while(sectors); @@ -748,10 +749,10 @@ void ext2_load_config(com32sys_t *regs) /** * init. the fs meta data, return the block size bits. */ -int ext2_fs_init(void) +int ext2_fs_init(struct fs_info *fs) { /* read the super block */ - read_sectors((char *)&sb, 2, 2); + fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)&sb, 2, 2, 0); ClustByteShift = sb.s_log_block_size + 10; ClustSize = 1 << ClustByteShift; diff --git a/core/fs.c b/core/fs.c index d2a82c36..35a11e9e 100644 --- a/core/fs.c +++ b/core/fs.c @@ -7,7 +7,6 @@ /* The this fs pointer */ struct fs_info *this_fs; struct fs_info fs; -struct device dev; void load_config(com32sys_t *regs) @@ -105,12 +104,12 @@ uint8_t detect_edd(uint8_t device_num) /* * initialize the device structure */ -void device_init(struct device *dev, uint8_t device_num, sector_t offset) +struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start, + uint16_t bsHeads, uint16_t bsSecPerTrack) { - dev->device_number = device_num; - dev->part_start = offset; + static struct device dev; - dev->type = detect_edd(device_num); + dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack); /* * check if we use cache or not, for now I just know ISO fs @@ -118,21 +117,23 @@ void device_init(struct device *dev, uint8_t device_num, sector_t offset) * it correctly. * */ - if ( USE_CACHE(dev->device_number) ) { + if ( USE_CACHE(dev.disk->disk_number) ) { /* I can't use __lowmem here, 'cause it will cause the error: "auxseg/lowmem region collides with xfer_buf_seg" */ //static __lowmem char cache_buf[65536]; - dev->cache_data = core_cache_buf; - dev->cache_size = sizeof core_cache_buf; + dev.cache_data = core_cache_buf; + dev.cache_size = sizeof core_cache_buf; } else - dev->cache_data = NULL; + dev.cache_data = NULL; + + return &dev; } /* debug function */ void dump_dev(struct device *dev) { - printf("device type:%s\n", dev->type ? "CHS" : "EDD"); + printf("device type:%s\n", dev->disk->type ? "EDD" : "CHS"); printf("cache_data: %p\n", dev->cache_data); printf("cache_head: %p\n", dev->cache_head); printf("cache_block_size: %d\n", dev->cache_block_size); @@ -153,18 +154,18 @@ void fs_init(com32sys_t *regs) int blk_shift; struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - device_init(&dev, regs->edx.b[0], regs->ecx.l); - /* set up the fs stucture */ fs.fs_name = ops->fs_name; fs.fs_ops = ops; - fs.fs_dev = &dev; + fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, + regs->esi.w[0], regs->edi.w[0]); this_fs = &fs; /* invoke the fs-specific init code */ - blk_shift = fs.fs_ops->fs_init(); + blk_shift = fs.fs_ops->fs_init(&fs); /* initialize the cache */ - if (dev.cache_data) - cache_init(&dev, blk_shift); + if (fs.fs_dev->cache_data) + cache_init(fs.fs_dev, blk_shift); + dump_dev(fs.fs_dev); } diff --git a/core/include/disk.h b/core/include/disk.h index 1eb9f038..376052dd 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -1,15 +1,40 @@ #ifndef DISK_H #define DISK_H +#include #include +#include #define SECTOR_SHIFT 9 #define SECTOR_SIZE (1 << SECTOR_SHIFT) -typedef uint64_t sector_t; +/* I do want it be simple for now */ +typedef uint32_t sector_t; typedef uint32_t block_t; + +/* + * struct disk: contains the information about a specific disk and also + * contains the I/O function. + */ +struct disk { + uint8_t disk_number; /* in BIOS style */ + uint8_t type; /* CHS or EDD */ + uint16_t sector_size; /* gener512B or 2048B */ + uint8_t sector_shift; + + uint8_t h, s; /* CHS geometry */ + uint8_t pad; + + sector_t part_start; /* the start address of this partition(in sectors) */ + + int (*rdwr_sectors)(struct disk *, void *, sector_t, size_t, bool); +}; + extern void read_sectors(char *, sector_t, int); extern void getoneblk(char *, block_t, int); +/* diskio.c */ +struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t); + #endif /* DISK_H */ diff --git a/core/include/fs.h b/core/include/fs.h index 0c837bd7..92f3e7fd 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -28,7 +28,7 @@ struct fs_ops { /* in fact, we use fs_ops structure to find the right fs */ char *fs_name; - int (*fs_init)(void); + int (*fs_init)(struct fs_info *); void (*searchdir)(char *, struct file *); uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); void (*mangle_name)(char *, char *); @@ -37,47 +37,18 @@ struct fs_ops { }; enum dev_type {CHS, EDD}; - + /* - * Struct device should have all the information about a specific disk - * structure, and contain either a pointer to the metadata cache or - * actually contain the cache itself. - * - * All the information in this case is stuff like BIOS device number, - * type of access (CHS, EDD, ...), geometry, partition offset, and - * sector size. - * - * It would be usefull and much easier to implement the C version getlinsec - * later(I have not much time to implement it now, so I will leave it for - * a while, maybe a long while). + * Struct device contains: + * the pointer points to the disk structure, + * the cache stuff. */ struct device { - /* the device numger (in BIOS style ) */ - uint8_t device_number; - - /* type of access (CHS or EDD ) */ - uint8_t type; - - /* the sector size, 512B for disk and floppy, 2048B for CD */ - uint16_t sector_size; - uint8_t sector_shift; - - /* CHS geometry */ - uint8_t h, s; - uint8_t pad1; - - /* the start address of this partition(in sectors) */ - sector_t part_start; - - int (*rdwr_sectors)(struct device *, void *, sector_t, size_t, bool); + struct disk *disk; - /* - * I think we still need the cache_data filed here, 'cause hpa said - * different device has diffrent cache buffer, and the following filed - * are quite for cache parts. - */ - char* cache_data; - struct cache_struct *cache_head; + /* the cache stuff */ + char* cache_data; + struct cache_struct* cache_head; uint16_t cache_block_size; uint16_t cache_entries; uint32_t cache_size; -- cgit v1.2.1 From afa8f040dba2e7b90a953d5ff00fe19b42d444a2 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 21 Jun 2009 14:59:46 +0800 Subject: Core:ISOLINUX: convert the isolinux.asm to C --- core/Makefile | 3 +- core/disk.c | 10 +- core/diskstart.inc | 1 + core/fs.c | 23 +- core/include/core.h | 2 +- core/include/fs.h | 4 - core/include/iso9660_fs.h | 21 ++ core/iso9660.c | 580 ++++++++++++++++++++++++++++++++++++++++++++++ core/isolinux.asm | 418 ++------------------------------- 9 files changed, 633 insertions(+), 429 deletions(-) create mode 100644 core/include/iso9660_fs.h create mode 100644 core/iso9660.c diff --git a/core/Makefile b/core/Makefile index c41b423b..0f257f1d 100644 --- a/core/Makefile +++ b/core/Makefile @@ -33,7 +33,8 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ - extlinux.bin extlinux.bss extlinux.sys + extlinux.bin extlinux.bss extlinux.sys \ + isolinux.bin isolinux-debug.bin # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) diff --git a/core/disk.c b/core/disk.c index 8ec880c6..69a9c0bf 100644 --- a/core/disk.c +++ b/core/disk.c @@ -6,7 +6,7 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) { com32sys_t regs; - static __lowmem char low_buf[65536]; + //static __lowmem char low_buf[65536]; /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ int high_addr = (buf + (sectors << SECTOR_SHIFT)) > (char *)0x100000; @@ -15,17 +15,17 @@ void read_sectors(char *buf, sector_t sector_num, int sectors) regs.ebp.l = sectors; if (high_addr) { - regs.es = SEG(low_buf); - regs.ebx.w[0] = OFFS(low_buf); + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); } else { regs.es = SEG(buf); - regs.ebx.w[0] = OFFS(buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); } call16(getlinsec, ®s, NULL); if (high_addr) - memcpy(buf, low_buf, sectors << SECTOR_SHIFT); + memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); } diff --git a/core/diskstart.inc b/core/diskstart.inc index a08aa281..3dc8f8a8 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -729,6 +729,7 @@ expand_super: mov eax,iso_fs_ops %endif mov dl,[DriveNumber] + mov dh,0 ; it's a disk not cdrom mov ecx,[bsHidden] mov ebx,[bsHidden+4] %endif diff --git a/core/fs.c b/core/fs.c index 617e3e5e..5dc767a7 100644 --- a/core/fs.c +++ b/core/fs.c @@ -1,4 +1,5 @@ #include +#include #include #include "fs.h" #include "cache.h" @@ -105,30 +106,24 @@ uint8_t detect_edd(uint8_t device_num) /* * initialize the device structure */ -void device_init(struct device *dev, uint8_t device_num, sector_t offset) +void device_init(struct device *dev, uint8_t device_num, + bool cdrom, sector_t offset) { dev->device_number = device_num; dev->part_start = offset; dev->type = detect_edd(device_num); - /* - * check if we use cache or not, for now I just know ISO fs - * does not use the cache, and I hope the USE_CACHE can detect - * it correctly. - * - */ - if ( USE_CACHE(dev->device_number) ) { + if (!cdrom) { /* I can't use __lowmem here, 'cause it will cause the error: - "auxseg/lowmem region collides with xfer_buf_seg" */ - //static __lowmem char cache_buf[65536]; + "auxseg/lowmem region collides with xfer_buf_seg" + + static __lowmem char cache_buf[65536]; + */ dev->cache_data = core_cache_buf; dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; - - /* I just considered the floppy and disk now */ - dev->read_sectors = read_sectors; } @@ -156,7 +151,7 @@ void fs_init(com32sys_t *regs) int blk_shift; struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - device_init(&dev, regs->edx.b[0], regs->ecx.l); + device_init(&dev, regs->edx.b[0], regs->edx.b[1], regs->ecx.l); /* set up the fs stucture */ fs.fs_name = ops->fs_name; diff --git a/core/include/core.h b/core/include/core.h index 574fd7af..f7a7262d 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -11,7 +11,7 @@ extern char CurrentDirName[]; extern char ConfigName[]; -/* diskstart.inc */ +/* diskstart.inc isolinux.asm*/ extern void getlinsec(void); /* getc.inc */ diff --git a/core/include/fs.h b/core/include/fs.h index 0cb1bfc6..208b22d4 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -5,10 +5,6 @@ #include "core.h" #include "disk.h" -/* I don't know it's right or not */ -#define USE_CACHE(device_num) (device_num >= 0x00 && device_num < 0xfe) - - struct fs_info { char *fs_name; struct fs_ops *fs_ops; diff --git a/core/include/iso9660_fs.h b/core/include/iso9660_fs.h new file mode 100644 index 00000000..ca123b16 --- /dev/null +++ b/core/include/iso9660_fs.h @@ -0,0 +1,21 @@ +#ifndef ISO9660_FS_H +#define ISO9660_FS_H + +#include + +struct iso_dir_entry { + uint8_t length; /* 00 */ + uint8_t ext_attr_length; /* 01 */ + uint8_t extent[8]; /* 02 */ + uint8_t size[8]; /* 0a */ + uint8_t date[7]; /* 12 */ + uint8_t flags; /* 19 */ + uint8_t file_unit_size; /* 1a */ + uint8_t interleave; /* 1b */ + uint8_t volume_sequence_number[4]; /* 1c */ + uint8_t name_len; /* 20 */ + //uint8_t name[]; /* 21 */ +}; + + +#endif /* iso9660_fs.h */ diff --git a/core/iso9660.c b/core/iso9660.c new file mode 100644 index 00000000..267b8cd9 --- /dev/null +++ b/core/iso9660.c @@ -0,0 +1,580 @@ +#include +#include +//#include "cache.h" +#include "core.h" +#include "disk.h" +#include "iso9660_fs.h" +#include "fs.h" + +#define DEBUG 1 + +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) +#define MAX_OPEN_LG2 6 +#define MAX_OPEN (1 << MAX_OPEN_LG2) +#define ISO_SECTOR_SHIFT 11 +#define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) +#define ROOT_DIR_WORD 0x002f +#define TRACKBUF_SIZE 8192 + + +struct open_file_t { + uint32_t file_sector; + uint32_t file_bytesleft; + uint32_t file_left; + uint32_t pad; +}; +extern char Files[]; + +struct dir_t { + uint32_t dir_lba; /* Directory start (LBA) */ + uint32_t dir_len; /* Length in bytes */ + uint32_t dir_clust; /* Length in clusters */ +}; +struct dir_t RootDir; +struct dir_t CurrentDir; + + +extern char trackbuf[TRACKBUF_SIZE]; +uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; +uint16_t BufSafeBytes = TRACKBUF_SIZE; + +char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ +char *ISOFileNameEnd = &ISOFileName[64]; + +uint32_t FirstSecSum; /* checksum of bytes 64-2048 */ +uint32_t ImageDwords; /* isolinux.bin size, dwords */ +uint32_t InitStack; /* Initial stack pointer (SS:SP) */ +uint16_t DiskSys; /* Last INT 13h call */ +uint16_t ImageSectors; /* isolinux.bin size, sectors */ + +/* These following two are accessed as a single dword ... */ +uint16_t GetlinsecPtr; /* the sector-read pointer */ +uint16_t BIOSType; +uint8_t DiskError; /* Error code for disk I/O */ +uint8_t DriveNumber; /* CD-ROM BIOS drive number */ +uint8_t ISOFlags; /* Flags for ISO directory search */ +uint8_t RetryCount; /* Used for ISO directory search */ +uint16_t bsSecPerTrack; /* Used in hybrid mode */ +uint16_t bsHeads; /* Used in hybrid mode */ + + +/** + * allocate_file: + * + * allocate a file structure + * + */ +struct open_file_t *allocate_file() +{ + struct open_file_t *file; + int i = 0; + + file = (struct open_file_t *)Files; + for (; i < MAX_OPEN; i ++ ) { + if ( file->file_sector == 0 ) /* found it */ + return file; + file ++; + } + + return NULL; /* not found */ +} + + +/** + * close_file: + * + * Deallocates a file structure + * + */ +void close_file(struct open_file_t *file) +{ + if (file) + file->file_sector = 0; +} + +void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) +{ + com32sys_t regs; + //static __lowmem char low_buf[65536]; + /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ + int high_addr = (buf + (sectors << ISO_SECTOR_SHIFT)) > (char *)0x100000; + + memset(®s, 0, sizeof regs); + regs.eax.l = sector_num; + regs.ebp.l = sectors; + + if (high_addr) { + regs.es = SEG(core_xfer_buf); + regs.ebx.w[0] = OFFS(core_xfer_buf); + } else { + regs.es = SEG(buf); + regs.ebx.w[0] = OFFS(buf); + } + + call16(getlinsec, ®s, NULL); + + if (high_addr) + memcpy(buf, core_xfer_buf, sectors << ISO_SECTOR_SHIFT); +} + + + + +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed + * to by dst; ends on encountering any whitespace. + * dst is preserved. + * + * This verifies that a filename is < FilENAME_MAX characters, + * doesn't contain whitespace, zero-pads the output buffer, + * and removes trailing dots and redumndant slashes, so "repe + * cmpsb" can do a compare, and the path-searching routine gets + * a bit of an easier job. + * + */ +void iso_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX - 1; + + while ( *src > ' ' ) { + if ( *src == '/' ) { + if ( *(src+1) == '/' ) { + i --; + src ++; + continue; + } + } + + *dst++ = *src ++; + i --; + } + + while ( 1 ) { + if ( dst == p ) + break; + + if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i -- ) + *dst++ = '\0'; +} + + +/** + * compare the names si and di and report if they are + * equal from an ISO 9600 perspective. + * + * @param: de_name, the name from the file system. + * @param: len, the length of de_name, and will return the real name of the de_name + * ';' and other terminates excluded. + * @param: file_name, the name we want to check, is expected to end with a null + * + * @return: 1 on match, or 0. + * + */ +int iso_compare_names(char *de_name, int *len, char *file_name) +{ + char *p = ISOFileName; + char c1, c2; + + int i = 0; + + while ( (i < *len) && *de_name && (*de_name != ';') && (p < ISOFileNameEnd - 1) ) { + *p++ = *de_name++; + i++; + } + + /* Remove terminal dots */ + while ( *(p-1) == '.' ) { + if ( *len <= 2 ) + break; + + if ( p <= ISOFileName ) + break; + p --; + i--; + } + + if ( i <= 0 ) + return 0; + + *p = '\0'; + + /* return the 'real' length of de_name */ + *len = i; + + p = ISOFileName; + + /* i is the 'real' name length of file_name */ + while ( i ) { + c1 = *p++; + c2 = *file_name++; + + if ( (c1 == 0) && (c2 == 0) ) + return 1; /* success */ + + else if ( (c1 == 0) || ( c2 == 0 ) ) + return 0; + + c1 |= 0x20; + c2 |= 0x20; /* convert to lower case */ + if ( c1 != c2 ) + return 0; + i --; + } + + return 1; +} + + +/** + * iso_getfssec: + * + * Get multiple clusters from a file, given the file pointer. + * + * we don't use the fs struct for now + * + * @param: buf + * @param: file, the address of the open file structure + * @param: sectors, how many we want to read at once + * @param: have_more, to indicate if we have reach the end of the file + * + */ +uint32_t iso_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) +{ + uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; + struct open_file_t *file = (struct open_file_t *)open_file; + + if ( sectors > file->file_left ) + sectors = file->file_left; + + getlinsec_cdrom(buf, file->file_sector, sectors); + + file->file_sector += sectors; + file->file_left -= sectors; + + if ( bytes_read >= file->file_bytesleft ) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else + *have_more = 1; + file->file_bytesleft -= bytes_read; + + return bytes_read; +} + + + +/** + * do_search_dir: + * + * find a file or directory with name within the _dir_ directory. + * + * the return value will tell us what we find, it's a file or dir? + * on 1 be dir, 2 be file, 0 be error. + * + * res will return the result. + * + */ +int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) +{ + struct open_file_t *file; + struct iso_dir_entry *de; + struct iso_dir_entry tmpde; + + uint32_t offset = 0; /* let's start it with the start */ + uint32_t file_pos = 0; + char *de_name; + int de_len; + int de_name_len; + int have_more; + + file = allocate_file(); + if ( !file ) + return 0; + + file->file_left = dir->dir_clust; + file->file_sector = dir->dir_lba; + + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + de = (struct iso_dir_entry *)trackbuf; + + while ( file_pos < dir->dir_len ) { + int found = 0; + + if ( (char *)de >= (char *)(trackbuf + TRACKBUF_SIZE) ) { + if ( !have_more ) + return 0; + + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + offset = 0; + } + + de = (struct iso_dir_entry *) (trackbuf + offset); + + de_len = de->length; + + if ( de_len == 0) { + offset = file_pos = (file_pos+ISO_SECTOR_SIZE) & ~(ISO_SECTOR_SIZE-1); + continue; + } + + + offset += de_len; + + /* Make sure we have a full directory entry */ + if ( offset >= TRACKBUF_SIZE ) { + int slop = TRACKBUF_SIZE - offset + de_len; + memcpy(&tmpde, de, slop); + offset &= TRACKBUF_SIZE - 1; + file->file_sector ++; + if ( offset ) { + if ( !have_more ) + return 0; + iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + memcpy((void*)&tmpde + slop, trackbuf, offset); + } + de = &tmpde; + } + + if ( de_len < 33 ) { + printf("Corrutped directory entry in sector %d\n", file->file_sector); + return 0; + } + + de_name_len = de->name_len; + de_name = (char *)((void *)de + 0x21); + + + if ( (de_name_len == 1) && (*de_name == 0) ) { + found = iso_compare_names(".", &de_name_len, name); + + } else if ( (de_name_len == 1) && (*de_name == 1) ) { + de_name_len = 2; + found = iso_compare_names("..", &de_name_len, name); + + } else + found = iso_compare_names(de_name, &de_name_len, name); + + if (found) + break; + + file_pos += de_len; + } + + if ( file_pos >= dir->dir_len ) + return 0; /* not found */ + + + if ( *(name+de_name_len) && (*(name+de_name_len) != '/' ) ) { + printf("Something wrong happened during searching file %s\n", name); + + *res = NULL; + return 0; + } + + if ( de->flags & 0x02 ) { + /* it's a directory */ + dir = &CurrentDir; + dir->dir_lba = *(uint32_t *)de->extent; + dir->dir_len = *(uint32_t *)de->size; + dir->dir_clust = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = dir->dir_len; + *res = dir; + + /* we can close it now */ + close_file(file); + + /* Mark we got a directory */ + return 1; + } else { + /* it's a file */ + file->file_sector = *(uint32_t *)de->extent; + file->file_bytesleft = *(uint32_t *)de->size; + file->file_left = (file->file_bytesleft + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = file->file_bytesleft; + *res = file; + + /* Mark we got a file */ + return 2; + } +} + + +/** + * iso_searchdir: + * + * open a file + * + * searchdir_iso is a special entry point for ISOLINUX only. In addition + * to the above, searchdir_iso passes a file flag mask in AL. This is + * useful for searching for directories. + * + * well, it's not like the searchidr function in EXT fs or FAT fs; it also + * can read a diretory.(Just thought of mine, liu) + * + */ +void iso_searchdir(char *filename, struct file *file) +{ + struct open_file_t *open_file = NULL; + struct dir_t *dir; + uint32_t file_len; + int ret; + void *res; + + dir = &CurrentDir; + if ( *filename == '/' ) { + dir = &RootDir; + filename ++; + } + + while ( *filename ) { + + ret = do_search_dir(dir, filename, &file_len, &res); + if ( ret == 1 ) + dir = (struct dir_t *)res; + else if ( ret == 2 ) + break; + else + goto err; + + /* find the end */ + while ( *filename && (*filename != '/') ) + filename ++; + + /* skip the slash */ + while ( *filename && (*filename == '/') ) + filename++; + } + + /* well , we need recheck it , becuase it can be a directory */ + if ( ret == 2 ) { + open_file = (struct open_file_t *)res; + goto found; + } else { + open_file = allocate_file(); + if ( !open_file ) + goto err; + + open_file->file_sector = dir->dir_lba; + open_file->file_bytesleft = dir->dir_len; + open_file->file_left = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + goto found; + } + err: + close_file(open_file); + file_len = 0; + open_file = NULL; + + found: + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 0 + if (open_file) { + printf("file bytesleft: %d\n", open_file->file_bytesleft); + printf("file sector : %d\n", open_file->file_sector); + printf("file in sector: %d\n", open_file->file_in_sec); + printf("file offsector: %d\n", open_file->file_in_off); + } +#endif +} + +void iso_load_config(com32sys_t *regs) +{ + char *config_name = "isolinux.cfg"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + + regs->edi.w[0] = ConfigName; + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); +} + + +int iso_fs_init() +{ + char *iso_dir; + char *boot_dir = "/boot/isolinux"; + char *isolinux_dir = "/isolinux"; + + struct file file; + struct open_file_t *open_file; + int len; + int bi_pvd = 16; + + getlinsec_cdrom(trackbuf, bi_pvd, 1); + + CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); + +#ifdef DEBUG + printf("Root directory at LBA = 0x%x\n", RootDir.dir_lba); +#endif + + CurrentDir.dir_len = RootDir.dir_len = *(uint32_t*)(trackbuf + 156 + 10); + CurrentDir.dir_clust = RootDir.dir_clust = (RootDir.dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + /* + * Look for an isolinux directory, and if found, + * make it the current directory instead of the + * root directory. + * + * Also copy the name of the directory to CurrrentDirName + */ + *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; + + iso_dir = boot_dir; + iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ + if ( !file.file_len ) { + iso_dir = isolinux_dir; + iso_searchdir(isolinux_dir, &file); /* search for /isolinux */ + if ( !file.file_len ) + goto no_isolinux_dir; + } + + strcpy(CurrentDirName, iso_dir); + len = strlen(CurrentDirName); + CurrentDirName[len] = '/'; + CurrentDirName[len+1] = '\0'; + + open_file = (struct open_file_t *)file.open_file; + CurrentDir.dir_len = open_file->file_bytesleft; + CurrentDir.dir_clust = open_file->file_left; + CurrentDir.dir_lba = open_file->file_sector; + close_file(open_file); + +#ifdef DEBUG + printf("isolinux directory at LBA = %0x%x\n", CurrentDir.dir_lba); +#endif + + no_isolinux_dir: + printf("No isolinux directory found\n"); + + /* we do not use cache for now, so we can just return 0 */ + return 0; +} + + +const struct fs_ops iso_fs_ops = { + .fs_name = "iso", + .fs_init = iso_fs_init, + .searchdir = iso_searchdir, + .getfssec = iso_getfssec, + .mangle_name = iso_mangle_name, + .unmangle_name = NULL, + .load_config = iso_load_config +}; diff --git a/core/isolinux.asm b/core/isolinux.asm index b2c9c986..1a1cae9f 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -86,6 +86,7 @@ dir_clust resd 1 ; Length in clusters ; Memory below this point is reserved for the BIOS and the MBR ; section .earlybss + global trackbuf trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h @@ -191,6 +192,7 @@ _spec_end equ $ _spec_len equ _spec_end - _spec_start section .bss16 + global Files alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size @@ -767,6 +769,7 @@ getonesec: ; ES:BX - Target buffer ; BP - Sector count ; + global getlinsec getlinsec: jmp word [cs:GetlinsecPtr] %ifndef DEBUG_MESSAGES @@ -1160,90 +1163,25 @@ all_read: ; (which will be at 16 only for a single-session disk!); from the PVD ; we should be able to find the rest of what we need to know. ; -get_fs_structures: - mov eax,[bi_pvd] - mov bx,trackbuf - call getonesec - - mov eax,[trackbuf+156+2] - mov [RootDir+dir_lba],eax - mov [CurrentDir+dir_lba],eax -%ifdef DEBUG_MESSAGES - mov si,dbg_rootdir_msg - call writemsg - call writehex8 - call crlf -%endif - mov eax,[trackbuf+156+10] - mov [RootDir+dir_len],eax - mov [CurrentDir+dir_len],eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [RootDir+dir_clust],eax - mov [CurrentDir+dir_clust],eax - - ; Look for an isolinux directory, and if found, - ; make it the current directory instead of the root - ; directory. - ; Also copy the name of the directory to CurrentDirName - mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName - mov di,boot_dir ; Search for /boot/isolinux - mov al,02h - push di - call searchdir_iso - pop di - jnz .found_dir - mov di,isolinux_dir - mov al,02h ; Search for /isolinux - push di - call searchdir_iso - pop di - jz .no_isolinux_dir -.found_dir: - ; Copy current directory name to CurrentDirName - push si - push di - mov si,di - mov di,CurrentDirName - call strcpy - mov byte [di],0 ;done in case it's not word aligned - dec di - mov byte [di],'/' - pop di - pop si - - mov [CurrentDir+dir_len],eax - mov eax,[si+file_left] - mov [CurrentDir+dir_clust],eax - xor eax,eax ; Free this file pointer entry - xchg eax,[si+file_sector] - mov [CurrentDir+dir_lba],eax -%ifdef DEBUG_MESSAGES - push si - mov si,dbg_isodir_msg - call writemsg - pop si - call writehex8 - call crlf -%endif -.no_isolinux_dir: + pushad + extern iso_fs_ops + mov eax,iso_fs_ops + mov dl,[DriveNumber] + mov dh,1 ; it's cdrom + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] + pm_call fs_init + popad ; ; Locate the configuration file ; -load_config: %ifdef DEBUG_MESSAGES mov si,dbg_config_msg call writemsg %endif - mov si,config_name - mov di,ConfigName - call strcpy - - mov di,ConfigName - call open - jz no_config_file ; Not found or empty + pm_call load_config %ifdef DEBUG_MESSAGES mov si,dbg_configok_msg @@ -1289,7 +1227,7 @@ is_disk_image: mov bx,trackbuf mov cx,1 ; Load 1 sector - call getfssec + pm_call getfssec cmp word [trackbuf+510],0aa55h ; Boot signature jne .bad_image ; Image not bootable @@ -1386,284 +1324,6 @@ is_disk_image: mov al,bl .done_sector: ret -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -close_file: - and si,si - jz .closed - mov dword [si],0 ; First dword == file_left - xor si,si -.closed: ret - -; -; searchdir: -; -; Open a file -; -; On entry: -; DS:DI = filename -; If successful: -; ZF clear -; SI = file pointer -; EAX = file length in bytes -; If unsuccessful -; ZF set -; -; Assumes CS == DS == ES, and trashes BX and CX. -; -; searchdir_iso is a special entry point for ISOLINUX only. In addition -; to the above, searchdir_iso passes a file flag mask in AL. This is useful -; for searching for directories. -; -alloc_failure: - xor ax,ax ; ZF <- 1 - ret - -searchdir: - xor al,al -searchdir_iso: - mov [ISOFlags],al - TRACER 'S' - call allocate_file ; Temporary file structure for directory - jnz alloc_failure - push es - push ds - pop es ; ES = DS - mov si,CurrentDir - cmp byte [di],'/' ; If filename begins with slash - jne .not_rooted - inc di ; Skip leading slash - mov si,RootDir ; Reference root directory instead -.not_rooted: - mov eax,[si+dir_clust] - mov [bx+file_left],eax - shl eax,SECTOR_SHIFT - mov [bx+file_bytesleft],eax - mov eax,[si+dir_lba] - mov [bx+file_sector],eax - mov edx,[si+dir_len] - -.look_for_slash: - mov ax,di -.scan: - mov cl,[di] - inc di - and cl,cl - jz .isfile - cmp cl,'/' - jne .scan - mov [di-1],byte 0 ; Terminate at directory name - mov cl,02h ; Search for directory - xchg cl,[ISOFlags] - - push di ; Save these... - push cx - - ; Create recursion stack frame... - push word .resume ; Where to "return" to - push es -.isfile: xchg ax,di - -.getsome: - ; Get a chunk of the directory - ; This relies on the fact that ISOLINUX doesn't change SI - mov si,trackbuf - TRACER 'g' - pushad - xchg bx,si - mov cx,[BufSafe] - call getfssec - popad - -.compare: - movzx eax,byte [si] ; Length of directory entry - cmp al,33 - jb .next_sector - TRACER 'c' - mov cl,[si+25] - xor cl,[ISOFlags] - test cl, byte 8Eh ; Unwanted file attributes! - jnz .not_file - pusha - movzx cx,byte [si+32] ; File identifier length - add si,byte 33 ; File identifier offset - TRACER 'i' - call iso_compare_names - popa - je .success -.not_file: - sub edx,eax ; Decrease bytes left - jbe .failure - add si,ax ; Advance pointer - -.check_overrun: - ; Did we finish the buffer? - cmp si,trackbuf+trackbufsize - jb .compare ; No, keep going - - jmp short .getsome ; Get some more directory - -.next_sector: - ; Advance to the beginning of next sector - lea ax,[si+SECTOR_SIZE-1] - and ax,~(SECTOR_SIZE-1) - sub ax,si - jmp short .not_file ; We still need to do length checks - -.failure: xor eax,eax ; ZF = 1 - mov [bx+file_sector],eax - pop es - ret - -.success: - mov eax,[si+2] ; Location of extent - mov [bx+file_sector],eax - mov eax,[si+10] ; Data length - mov [bx+file_bytesleft],eax - push eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [bx+file_left],eax - pop eax - jz .failure ; Empty file? - ; ZF = 0 - mov si,bx - pop es - ret - -.resume: ; We get here if we were only doing part of a lookup - ; This relies on the fact that .success returns bx == si - xchg edx,eax ; Directory length in edx - pop cx ; Old ISOFlags - pop di ; Next filename pointer - mov byte [di-1], '/' ; Restore slash - mov [ISOFlags],cl ; Restore the flags - jz .failure ; Did we fail? If so fail for real! - jmp .look_for_slash ; Otherwise, next level - -; -; allocate_file: Allocate a file structure -; -; If successful: -; ZF set -; BX = file pointer -; In unsuccessful: -; ZF clear -; -allocate_file: - TRACER 'a' - push cx - mov bx,Files - mov cx,MAX_OPEN -.check: cmp dword [bx], byte 0 - je .found - add bx,open_file_t_size ; ZF = 0 - loop .check - ; ZF = 0 if we fell out of the loop -.found: pop cx - ret - -; -; iso_compare_names: -; Compare the names DS:SI and DS:DI and report if they are -; equal from an ISO 9660 perspective. SI is the name from -; the filesystem; CX indicates its length, and ';' terminates. -; DI is expected to end with a null. -; -; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment -; - -iso_compare_names: - ; First, terminate and canonicalize input filename - push di - mov di,ISOFileName -.canon_loop: jcxz .canon_end - lodsb - dec cx - cmp al,';' - je .canon_end - and al,al - je .canon_end - stosb - cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun - jb .canon_loop -.canon_end: - cmp di,ISOFileName - jbe .canon_done - cmp byte [di-1],'.' ; Remove terminal dots - jne .canon_done - dec di - jmp short .canon_end -.canon_done: - mov [di],byte 0 ; Null-terminate string - pop di - mov si,ISOFileName -.compare: - lodsb - mov ah,[di] - inc di - and ax,ax - jz .success ; End of string for both - and al,al ; Is either one end of string? - jz .failure ; If so, failure - and ah,ah - jz .failure - or ax,2020h ; Convert to lower case - cmp al,ah - je .compare -.failure: and ax,ax ; ZF = 0 (at least one will be nonzero) -.success: ret - -; -; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace. -; DI is preserved. -; -; This verifies that a filename is < FILENAME_MAX characters, -; doesn't contain whitespace, zero-pads the output buffer, -; and removes trailing dots and redundant slashes, -; so "repe cmpsb" can do a compare, and the -; path-searching routine gets a bit of an easier job. -; -mangle_name: - push di - push bx - xor ax,ax - mov cx,FILENAME_MAX-1 - mov bx,di - -.mn_loop: - lodsb - cmp al,' ' ; If control or space, end - jna .mn_end - cmp al,ah ; Repeated slash? - je .mn_skip - xor ah,ah - cmp al,'/' - jne .mn_ok - mov ah,al -.mn_ok stosb -.mn_skip: loop .mn_loop -.mn_end: - cmp bx,di ; At the beginning of the buffer? - jbe .mn_zero - cmp byte [es:di-1],'.' ; Terminal dot? - je .mn_kill - cmp byte [es:di-1],'/' ; Terminal slash? - jne .mn_zero -.mn_kill: dec di ; If so, remove it - inc cx - jmp short .mn_end -.mn_zero: - inc cx ; At least one null byte - xor ax,ax ; Zero-fill name - rep stosb - pop bx - pop di - ret ; Done ; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled @@ -1680,56 +1340,6 @@ unmangle_name: call strcpy dec di ; Point to final null byte ret -; -; getfssec: Get multiple clusters from a file, given the file pointer. -; -; On entry: -; ES:BX -> Buffer -; SI -> File pointer -; CX -> Cluster count -; On exit: -; SI -> File pointer (or 0 on EOF) -; CF = 1 -> Hit EOF -; ECX -> Bytes actually read -; -getfssec: - TRACER 'F' - push ds - push cs - pop ds ; DS <- CS - - movzx ecx,cx - cmp ecx,[si+file_left] - jna .ok_size - mov ecx,[si+file_left] -.ok_size: - - pushad - mov eax,[si+file_sector] - mov bp,cx - TRACER 'l' - call getlinsec - popad - - ; ECX[31:16] == 0 here... - add [si+file_sector],ecx - sub [si+file_left],ecx - shl ecx,SECTOR_SHIFT ; Convert to bytes - cmp ecx,[si+file_bytesleft] - jb .not_all - mov ecx,[si+file_bytesleft] -.not_all: sub [si+file_bytesleft],ecx - jnz .ret ; CF = 0 in this case... - push eax - xor eax,eax - mov [si+file_sector],eax ; Unused - mov si,ax - pop eax - stc -.ret: - pop ds - TRACER 'f' - ret ; ----------------------------------------------------------------------------- ; Common modules -- cgit v1.2.1 From 1d0b44adb51e7a1193c5fdf35c324003d2bbaeaa Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 22 Jun 2009 15:11:43 +0800 Subject: Core:ISOLINUX: make the isolinux do the work --- core/Makefile | 1 - core/fs.c | 5 +++-- core/iso9660.c | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/core/Makefile b/core/Makefile index 0f257f1d..a96eec70 100644 --- a/core/Makefile +++ b/core/Makefile @@ -33,7 +33,6 @@ CODEPAGE = cp865 # The targets to build in this directory... BTARGET = kwdhash.gen \ - extlinux.bin extlinux.bss extlinux.sys \ isolinux.bin isolinux-debug.bin # All primary source files for the main syslinux files diff --git a/core/fs.c b/core/fs.c index 5dc767a7..375beec6 100644 --- a/core/fs.c +++ b/core/fs.c @@ -120,8 +120,8 @@ void device_init(struct device *dev, uint8_t device_num, static __lowmem char cache_buf[65536]; */ - dev->cache_data = core_cache_buf; - dev->cache_size = sizeof core_cache_buf; + //dev->cache_data = core_cache_buf; + //dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; } @@ -130,6 +130,7 @@ void device_init(struct device *dev, uint8_t device_num, /* debug function */ void dump_dev(struct device *dev) { + printf("drive number: 0x%x\n", dev->device_number); printf("device type:%s\n", dev->type ? "CHS" : "EDD"); printf("cache_data: %p\n", dev->cache_data); printf("cache_head: %p\n", dev->cache_head); diff --git a/core/iso9660.c b/core/iso9660.c index 267b8cd9..68885a61 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -500,7 +500,7 @@ void iso_load_config(com32sys_t *regs) strcpy(ConfigName, config_name); - regs->edi.w[0] = ConfigName; + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); memset(&out_regs, 0, sizeof out_regs); call16(core_open, regs, &out_regs); } @@ -542,8 +542,10 @@ int iso_fs_init() if ( !file.file_len ) { iso_dir = isolinux_dir; iso_searchdir(isolinux_dir, &file); /* search for /isolinux */ - if ( !file.file_len ) - goto no_isolinux_dir; + if ( !file.file_len ) { + printf("No isolinux directory found!\n"); + return 0; + } } strcpy(CurrentDirName, iso_dir); @@ -558,13 +560,10 @@ int iso_fs_init() close_file(open_file); #ifdef DEBUG - printf("isolinux directory at LBA = %0x%x\n", CurrentDir.dir_lba); + printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); #endif - no_isolinux_dir: - printf("No isolinux directory found\n"); - - /* we do not use cache for now, so we can just return 0 */ + /* we do not use cache for now, so we can just return 0 */ return 0; } -- cgit v1.2.1 From 39f7aaa7b65411159316836e4294592eaf1c4d70 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 23 Jun 2009 05:17:15 +0800 Subject: removes the %if IS_ISOLINUX stuff in the layout.inc removes the %if IS_ISOLINUX stuff in the layout.inc to make the fs.c can find the core_cache_buf symbol from ISOLINUX. --- core/fs.c | 4 ++-- core/layout.inc | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/core/fs.c b/core/fs.c index 375beec6..9dac9e93 100644 --- a/core/fs.c +++ b/core/fs.c @@ -120,8 +120,8 @@ void device_init(struct device *dev, uint8_t device_num, static __lowmem char cache_buf[65536]; */ - //dev->cache_data = core_cache_buf; - //dev->cache_size = sizeof core_cache_buf; + dev->cache_data = core_cache_buf; + dev->cache_size = sizeof core_cache_buf; } else dev->cache_data = NULL; } diff --git a/core/layout.inc b/core/layout.inc index 3f5a7457..3df07721 100644 --- a/core/layout.inc +++ b/core/layout.inc @@ -125,16 +125,11 @@ auxseg resb aux_size ; is somewhat excessive. Sector alignment is obligatory, however. ; -%if IS_ISOLINUX -; ISOLINUX doesn't have a block cache yet -real_mode_seg equ 4000h -%else global cache_seg, core_cache_buf cache_seg equ 4000h ; 64K area for metadata cache core_cache_buf equ cache_seg << 4 real_mode_seg equ 5000h pktbuf_seg equ cache_seg ; PXELINUX packet buffers -%endif comboot_seg equ real_mode_seg ; COMBOOT image loading zone -- cgit v1.2.1 From 29b1fd4674bb4a09f20fb435df986dc513b730be Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 23 Jun 2009 12:45:55 +0800 Subject: Core:EXTLINUX: add more debug stuff --- core/diskio.c | 4 ++++ core/ext2.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/core/diskio.c b/core/diskio.c index 8b33d8a7..c85d92ad 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -229,6 +229,10 @@ void dump_disk(struct disk *disk) printf("offset: %d\n", disk->part_start); printf("%s\n", disk->rdwr_sectors == edd_rdwr_sectors ? "EDD_RDWR_SECTORS" : "CHS_RDWR_SECTORS"); + printf("--------------------------------\n"); + printf("disk->rdwr_sectors@: %p\n", disk->rdwr_sectors); + printf("edd_rdwr_sectors @: %p\n", edd_rdwr_sectors); + printf("chs_rdwr_sectors @: %p\n", chs_rdwr_sectors); } struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, diff --git a/core/ext2.c b/core/ext2.c index 0ddda8ee..8bfca6ac 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -751,6 +751,9 @@ void ext2_load_config(com32sys_t *regs) */ int ext2_fs_init(struct fs_info *fs) { +#if 1 + printf("super block@: %p\n", &sb); +#endif /* read the super block */ fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)&sb, 2, 2, 0); -- cgit v1.2.1 From 1544972f0af1c1eec9dd9c4ee9d8cd4bb9d9ea17 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 23 Jun 2009 16:20:43 +0800 Subject: Core:LDLINUX: removes the ugly code Make the ConfigName to store the config file path, well it's enough because the longest config file path lenght is just 28. --- core/fat.c | 31 +++++++------------------------ core/fs.c | 10 ++-------- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/core/fat.c b/core/fat.c index 2a099d61..7f523d36 100644 --- a/core/fat.c +++ b/core/fat.c @@ -57,27 +57,6 @@ int NameLen; /* do this for readdir, because it called from asm and don't know the fs structure */ struct fs_info *this_fs = NULL; -/* - * Well, I find I can't reference the syslinux_cfg[i] config file name even though I - * used extern in C side and global in the ASM side. So I thought I can use a gloabl - * pointer called this_filename, points to the current filename. And in the searchdir - * function, we use a flag to determine if we need use the this_filename to go on. - * Here is the principle: - * - * if (regs->esi.w[0] == 0xCFCF) ; Called From C File(CFCF) - * file_name = this_fs; - * else - * file_name = (char *)MK_PTR(regs->es, regs->esi.w[0]) - * - * - * so if we want call searchdir function from C file, and the filename address - * is in the high address(means higher than 1M), we can put regs->edi.w[0] the 0xCFCF - * flag, then I hope all will go well. - * - * (I know it's ugly, sorry) - */ -char *this_filename = NULL; - /** * allocate_file: @@ -888,10 +867,13 @@ void vfat_load_config(com32sys_t *regs) *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; CurrentDir = RootDir; - strcpy(ConfigName, config_name); + /* + * we use the ConfigName to pass the config path because + * it is under the address 0xffff + */ + regs->edi.w[0] = ConfigName; for (; i < 3; i++) { - regs->edi.w[0] = 0xCFCF; /* Mark we use the this_filename to pass filename para */ - this_filename = syslinux_cfg[i]; + strcpy(ConfigName, syslinux_cfg[i]); memset(&oregs, 0, sizeof oregs); call16(core_open, regs, &oregs); @@ -904,6 +886,7 @@ void vfat_load_config(com32sys_t *regs) return; /* no config file */ } + strcpy(ConfigName, config_name); strcpy(CurrentDirName, syslinux_cfg[i]); CurrentDirName[strlen(syslinux_cfg[i])-strlen(config_name)] = '\0'; CurrentDir = PrevDir; diff --git a/core/fs.c b/core/fs.c index 2878c384..11459499 100644 --- a/core/fs.c +++ b/core/fs.c @@ -55,15 +55,9 @@ void getfssec(com32sys_t *regs) void searchdir(com32sys_t *regs) { - char *filename; + char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]);; struct file file; - - if (regs->edi.w[0] == 0xCFCF) { - /* check fat.c for more information */ - extern char *this_filename; - filename = this_filename; - } else - filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + #if 0 printf("filename: %s\n", filename); #endif -- cgit v1.2.1 From c757a46143e82b51e15d1c0428ad841f6ad48f02 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 23 Jun 2009 17:28:02 +0800 Subject: Core: merge ldlinux --- core/fat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/fat.c b/core/fat.c index 7f523d36..c5d8e83b 100644 --- a/core/fat.c +++ b/core/fat.c @@ -297,7 +297,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, #endif /* do read */ - read_sectors(buf, frag_start, con_sec_cnt); + fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)buf, frag_start, con_sec_cnt, 0); buf += con_sec_cnt << 9;/* adjust buffer pointer */ if ( !sectors ) @@ -871,7 +871,7 @@ void vfat_load_config(com32sys_t *regs) * we use the ConfigName to pass the config path because * it is under the address 0xffff */ - regs->edi.w[0] = ConfigName; + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); for (; i < 3; i++) { strcpy(ConfigName, syslinux_cfg[i]); memset(&oregs, 0, sizeof oregs); @@ -901,14 +901,14 @@ static inline void bsr(uint8_t *res, int num) } /* init. the fs meta data, return the block size in bits */ -int vfat_fs_init() +int vfat_fs_init(struct fs_info *fs) { int sectors_per_fat; uint32_t clust_num; int RootDirSize; /* get the fat bpb information */ - read_sectors((char *)&fat, 0, 1); + fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)&fat, 0, 1, 0); TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; FAT = fat.bxResSectors; -- cgit v1.2.1 From 1d303a9d6dc7c059848893d45c9f14ad054eefb8 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 24 Jun 2009 06:08:52 +0800 Subject: Core:ISOLINUX: fixs the bug to make the isolinux do the work --- core/iso9660.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/core/iso9660.c b/core/iso9660.c index 09da65a8..a9e314ba 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -242,8 +242,6 @@ int iso_compare_names(char *de_name, int *len, char *file_name) * * Get multiple clusters from a file, given the file pointer. * - * we don't use the fs struct for now - * * @param: buf * @param: file, the address of the open file structure * @param: sectors, how many we want to read at once @@ -251,7 +249,7 @@ int iso_compare_names(char *de_name, int *len, char *file_name) * */ uint32_t iso_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) + void *open_file, int sectors, int *have_more) { uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; struct open_file_t *file = (struct open_file_t *)open_file; @@ -287,7 +285,8 @@ uint32_t iso_getfssec(struct fs_info *fs, char *buf, * res will return the result. * */ -int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) +int do_search_dir(struct fs_info *fs, struct dir_t *dir, + char *name, uint32_t *file_len, void **res) { struct open_file_t *file; struct iso_dir_entry *de; @@ -307,7 +306,7 @@ int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) file->file_left = dir->dir_clust; file->file_sector = dir->dir_lba; - iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); de = (struct iso_dir_entry *)trackbuf; while ( file_pos < dir->dir_len ) { @@ -317,7 +316,7 @@ int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) if ( !have_more ) return 0; - iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); offset = 0; } @@ -342,7 +341,7 @@ int do_search_dir(struct dir_t *dir, char *name, uint32_t *file_len, void **res) if ( offset ) { if ( !have_more ) return 0; - iso_getfssec(NULL, trackbuf, file, BufSafe, &have_more); + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); memcpy((void*)&tmpde + slop, trackbuf, offset); } de = &tmpde; @@ -440,17 +439,16 @@ void iso_searchdir(char *filename, struct file *file) dir = &RootDir; filename ++; } -#define DEBUG() printf("go there? %d\n", __LINE__) + while ( *filename ) { - DEBUG(); - ret = do_search_dir(dir, filename, &file_len, &res); + ret = do_search_dir(file->fs, dir, filename, &file_len, &res); if ( ret == 1 ) dir = (struct dir_t *)res; else if ( ret == 2 ) break; else goto err; - DEBUG(); + /* find the end */ while ( *filename && (*filename != '/') ) filename ++; @@ -459,7 +457,7 @@ void iso_searchdir(char *filename, struct file *file) while ( *filename && (*filename == '/') ) filename++; } - DEBUG(); + /* well , we need recheck it , becuase it can be a directory */ if ( ret == 2 ) { open_file = (struct open_file_t *)res; @@ -538,6 +536,7 @@ int iso_fs_init(struct fs_info *fs) *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; iso_dir = boot_dir; + file.fs = fs; iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ if ( !file.file_len ) { iso_dir = isolinux_dir; -- cgit v1.2.1 From 7253943ae070b253b98430a558e10e4dd1527dbb Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 24 Jun 2009 06:31:39 +0800 Subject: Core: code clean removes the unused variables and unused functions --- core/diskio.c | 2 -- core/fs.c | 46 ++++++++-------------------------------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index c1c8dc00..28aac105 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -16,7 +16,6 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, char *ptr = buf; char *tptr; size_t chunk, freeseg; - int sector_size = disk->sector_size; int sector_shift = disk->sector_shift; uint32_t xlba = lba; /* Truncated LBA (CHS is << 2 TB) */ uint32_t t; @@ -110,7 +109,6 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, char *ptr = buf; char *tptr; size_t chunk, freeseg; - int sector_size = disk->sector_size; int sector_shift = disk->sector_shift; com32sys_t ireg, oreg; size_t done = 0; diff --git a/core/fs.c b/core/fs.c index 77d03575..3ebc0b15 100644 --- a/core/fs.c +++ b/core/fs.c @@ -74,33 +74,6 @@ void searchdir(com32sys_t *regs) regs->eflags.l |= EFLAGS_ZF; } -/* - * well, I find that in the diskstart.inc, there's no room fow us to - * get the edd check result, so we implement a new one here. - */ -uint8_t detect_edd(uint8_t device_num) -{ - com32sys_t iregs, oregs; - - /* Sending int 13h func 41h to query EBIOS information */ - memset(&iregs, 0, sizeof iregs); - memset(&oregs, 0, sizeof oregs); - - /* Get EBIOS support */ - iregs.eax.w[0] = 0x4100; - iregs.ebx.w[0] = 0x55aa; - iregs.edx.b[0] = device_num; - iregs.eflags.b[0] = 0x3; /* CF set */ - - __intcall(0x13, &iregs, &oregs); - - /* Detecting EDD support */ - if (!(oregs.eflags.l & EFLAGS_CF) && - oregs.ebx.w[0] == 0xaa55 && (oregs.ecx.b[0] & 1)) - return 1; - else - return 0; -} /* * initialize the device structure @@ -112,17 +85,14 @@ struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start, dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack); - /* - * check if we use cache or not, for now I just know ISO fs - * does not use the cache, and I hope the USE_CACHE can detect - * it correctly. - * - */ + /* for now, isolinux doesn't use cache */ if (!cdrom) { - /* FIX!! - I can't use __lowmem here, 'cause it will cause the error: - "auxseg/lowmem region collides with xfer_buf_seg" */ - //static __lowmem char cache_buf[65536]; + /* + * FIX!! I can't use __lowmem here, 'cause it will cause the error: + * "auxseg/lowmem region collides with xfer_buf_seg". + * + * static __lowmem char cache_buf[65536]; + */ dev.cache_data = core_cache_buf; dev.cache_size = sizeof core_cache_buf; } else @@ -146,8 +116,8 @@ void dump_dev(struct device *dev) /* * it will do: - * initialize the device structure; * set up the vfs fs structure; + * initialize the device structure; * invoke the fs-specific init function; * finally, initialize the cache * -- cgit v1.2.1 From e27720e6888425e65a4a91cb7e332020579c6935 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 24 Jun 2009 06:44:11 +0800 Subject: Core: fixs the chunk>>=1 problem well, it seems ugly, but it can do the right work(I think). here is the new way: chunk = chunk == 1 ? 0 : ((chunk+1) >> 1); if we are reading ONE sector, and after six retries, we can mark it as _failed_. So just make it be ZERO. --- core/diskio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index 28aac105..bb5b34ce 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -73,7 +73,9 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, break; if (retry--) continue; - chunk >>= 1; + + /* if we are reading ONE sector and go here, just make it _faile_ */ + chunk = chunk == 1 ? 0 : ((chunk+1) >> 1); if (chunk) { MaxTransfer = chunk; retry = RETRY_COUNT; @@ -158,7 +160,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, break; if (retry--) continue; - chunk >>= 1; + chunk = chunk == 1 ? 0 : ((chunk+1) >> 1); if (chunk) { MaxTransfer = chunk; retry = RETRY_COUNT; -- cgit v1.2.1 From 9598746ea128d18ea849427434a1977276024e5e Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 8 Jul 2009 00:44:45 +0800 Subject: Core: code clean: breakup the fs->fs_dev->disk stuff Add a new disk structure pointer disk to point to fs->fs_dev_disk to break the long code. --- core/ext2.c | 8 +++++--- core/fat.c | 9 +++++---- core/iso9660.c | 11 ++++++----- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index 8bfca6ac..a0bd2aff 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -446,6 +446,7 @@ void getlinsec_ext(struct fs_info *fs, char *buf, sector_t sector, int sector_cnt) { int ext_cnt = 0; + struct disk *disk = fs->fs_dev->disk; if (sector < SecPerClust) { ext_cnt = SecPerClust - sector; @@ -455,7 +456,7 @@ void getlinsec_ext(struct fs_info *fs, char *buf, sector += ext_cnt; sector_cnt -= ext_cnt; - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, buf, sector, sector_cnt, 0); + disk->rdwr_sectors(disk, buf, sector, sector_cnt, 0); } /** @@ -751,11 +752,12 @@ void ext2_load_config(com32sys_t *regs) */ int ext2_fs_init(struct fs_info *fs) { -#if 1 + struct disk *disk = fs->fs_dev->disk; +#if 0 printf("super block@: %p\n", &sb); #endif /* read the super block */ - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)&sb, 2, 2, 0); + disk->rdwr_sectors(disk, (void *)&sb, 2, 2, 0); ClustByteShift = sb.s_log_block_size + 10; ClustSize = 1 << ClustByteShift; diff --git a/core/fat.c b/core/fat.c index c5d8e83b..f8d9f6da 100644 --- a/core/fat.c +++ b/core/fat.c @@ -273,6 +273,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, sector_t curr_sector = file->file_sector; sector_t frag_start , next_sector; uint32_t con_sec_cnt; + struct disk *disk = fs->fs_dev->disk; while (sectors) { /* get fragment */ @@ -297,7 +298,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, #endif /* do read */ - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)buf, frag_start, con_sec_cnt, 0); + disk->rdwr_sectors(disk, (void *)buf, frag_start, con_sec_cnt, 0); buf += con_sec_cnt << 9;/* adjust buffer pointer */ if ( !sectors ) @@ -906,9 +907,10 @@ int vfat_fs_init(struct fs_info *fs) int sectors_per_fat; uint32_t clust_num; int RootDirSize; + struct disk *disk = fs->fs_dev->disk; /* get the fat bpb information */ - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)&fat, 0, 1, 0); + disk->rdwr_sectors(disk, (void *)&fat, 0, 1, 0); TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; FAT = fat.bxResSectors; @@ -921,8 +923,7 @@ int vfat_fs_init(struct fs_info *fs) bsr(&ClustShift, fat.bxSecPerClust); ClustByteShift = ClustShift + SECTOR_SHIFT; ClustMask = fat.bxSecPerClust - 1; - ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; - + ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; clust_num = (TotalSectors - DataArea) >> ClustShift; if ( clust_num < 4085 ) diff --git a/core/iso9660.c b/core/iso9660.c index a9e314ba..e696c841 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -253,11 +253,12 @@ uint32_t iso_getfssec(struct fs_info *fs, char *buf, { uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; struct open_file_t *file = (struct open_file_t *)open_file; + struct disk *disk = fs->fs_dev->disk; if ( sectors > file->file_left ) sectors = file->file_left; - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void *)buf, file->file_sector, sectors, 0); + disk->rdwr_sectors(disk, (void *)buf, file->file_sector, sectors, 0); file->file_sector += sectors; file->file_left -= sectors; @@ -509,13 +510,13 @@ int iso_fs_init(struct fs_info *fs) char *iso_dir; char *boot_dir = "/boot/isolinux"; char *isolinux_dir = "/isolinux"; - + int len; + int bi_pvd = 16; struct file file; struct open_file_t *open_file; - int len; - int bi_pvd = 16; + struct disk *disk = fs->fs_dev->disk; - fs->fs_dev->disk->rdwr_sectors(fs->fs_dev->disk, (void*)trackbuf, bi_pvd, 1, 0); + disk->rdwr_sectors(disk, (void*)trackbuf, bi_pvd, 1, 0); CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); -- cgit v1.2.1 From d84cf9dbc1fc1e3dfd9ab58ed1a2dceb447f93b9 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 8 Jul 2009 00:59:03 +0800 Subject: Core: code clean: cuts the unnecessary data type conversion in disk read-write function It's unnecessary to do that conversion. --- core/ext2.c | 2 +- core/fat.c | 4 ++-- core/iso9660.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index a0bd2aff..d808acd3 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -757,7 +757,7 @@ int ext2_fs_init(struct fs_info *fs) printf("super block@: %p\n", &sb); #endif /* read the super block */ - disk->rdwr_sectors(disk, (void *)&sb, 2, 2, 0); + disk->rdwr_sectors(disk, &sb, 2, 2, 0); ClustByteShift = sb.s_log_block_size + 10; ClustSize = 1 << ClustByteShift; diff --git a/core/fat.c b/core/fat.c index f8d9f6da..ce804bf3 100644 --- a/core/fat.c +++ b/core/fat.c @@ -298,7 +298,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, #endif /* do read */ - disk->rdwr_sectors(disk, (void *)buf, frag_start, con_sec_cnt, 0); + disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0); buf += con_sec_cnt << 9;/* adjust buffer pointer */ if ( !sectors ) @@ -910,7 +910,7 @@ int vfat_fs_init(struct fs_info *fs) struct disk *disk = fs->fs_dev->disk; /* get the fat bpb information */ - disk->rdwr_sectors(disk, (void *)&fat, 0, 1, 0); + disk->rdwr_sectors(disk, &fat, 0, 1, 0); TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; FAT = fat.bxResSectors; diff --git a/core/iso9660.c b/core/iso9660.c index e696c841..0a0ae19e 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -258,7 +258,7 @@ uint32_t iso_getfssec(struct fs_info *fs, char *buf, if ( sectors > file->file_left ) sectors = file->file_left; - disk->rdwr_sectors(disk, (void *)buf, file->file_sector, sectors, 0); + disk->rdwr_sectors(disk, buf, file->file_sector, sectors, 0); file->file_sector += sectors; file->file_left -= sectors; @@ -516,7 +516,7 @@ int iso_fs_init(struct fs_info *fs) struct open_file_t *open_file; struct disk *disk = fs->fs_dev->disk; - disk->rdwr_sectors(disk, (void*)trackbuf, bi_pvd, 1, 0); + disk->rdwr_sectors(disk, trackbuf, bi_pvd, 1, 0); CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); -- cgit v1.2.1 From 46cf51c77881189413fca90f56f12bc1e72241a8 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 11 Jul 2009 05:46:47 +0800 Subject: Core: changes the sector_t and block_t types to be uint64_t --- core/ext2.c | 43 ++++++++++++++++++++++--------------------- core/fat.c | 3 +-- core/include/disk.h | 5 ++--- core/iso9660.c | 3 +-- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index d808acd3..3f55c1ef 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -17,14 +17,14 @@ * File structure, This holds the information for each currently open file */ struct open_file_t { - uint32_t file_bytesleft; /* Number of bytes left (0 = free) */ - uint32_t file_sector; /* Next linear sector to read */ - uint32_t file_in_sec; /* Sector where inode lives */ - uint16_t file_in_off; - uint16_t file_mode; + uint32_t file_bytesleft; /* Number of bytes left (0 = free) */ + uint32_t file_sector; /* Next linear sector to read */ + sector_t file_in_sec; /* Sector where inode lives */ + uint16_t file_in_off; + uint16_t file_mode; }; -extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; +extern char Files[]; struct ext2_inode this_inode; struct ext2_super_block sb; @@ -253,7 +253,7 @@ ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block { struct ext4_extent_idx *index; struct cache_struct *cs; - uint64_t blk; + block_t blk; int i; while (1) { @@ -282,12 +282,12 @@ ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block } /* handle the ext4 extents to get the phsical block number */ -uint64_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) +block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct ext4_extent_header *leaf; struct ext4_extent *ext; int i; - uint64_t start; + block_t start; leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); if (! leaf) { @@ -326,7 +326,7 @@ uint64_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode * * * @return: the physic block number */ -block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *inode) +block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode) { struct cache_struct *cs; @@ -341,7 +341,7 @@ block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *i block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; cs = get_cache_block(fs->fs_dev, ind_block); - return ((block_t *)cs->data)[block]; + return ((uint32_t *)cs->data)[block]; } /* double indirect blocks */ @@ -350,10 +350,10 @@ block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *i block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; cs = get_cache_block(fs->fs_dev, dou_block); - dou_block = ((block_t *)cs->data)[block / PtrsPerBlock1]; + dou_block = ((uint32_t *)cs->data)[block / PtrsPerBlock1]; cs = get_cache_block(fs->fs_dev, dou_block); - return ((block_t*)cs->data)[block % PtrsPerBlock1]; + return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; } /* triple indirect block */ @@ -362,10 +362,10 @@ block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *i block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; cs = get_cache_block(fs->fs_dev, tri_block); - tri_block = ((block_t *)cs->data)[block / PtrsPerBlock2]; + tri_block = ((uint32_t *)cs->data)[block / PtrsPerBlock2]; cs = get_cache_block(fs->fs_dev, tri_block); - tri_block = ((block_t *)cs->data)[block % PtrsPerBlock2]; + tri_block = ((uint32_t *)cs->data)[block % PtrsPerBlock2]; cs = get_cache_block(fs->fs_dev, tri_block); return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; @@ -389,26 +389,27 @@ block_t linsector_direct(struct fs_info *fs, block_t block, struct ext2_inode *i * * @return: physic sector number */ -sector_t linsector(struct fs_info *fs, sector_t lin_sector) +sector_t linsector(struct fs_info *fs, uint32_t lin_sector) { - block_t block = lin_sector >> ClustShift; + uint32_t block = lin_sector >> ClustShift; + block_t ret; struct ext2_inode *inode; /* well, this is what I think the variable this_inode used for */ inode = &this_inode; if (inode->i_flags & EXT4_EXTENTS_FLAG) - block = linsector_extent(fs, block, inode); + ret = linsector_extent(fs, block, inode); else - block = (uint32_t)linsector_direct(fs, block, inode); + ret = linsector_direct(fs, block, inode); - if (!block) { + if (!ret) { printf("ERROR: something error happend at linsector..\n"); return 0; } /* finally convert it to sector */ - return ((block << ClustShift) + (lin_sector & ClustMask)); + return ((ret << ClustShift) + (lin_sector & ClustMask)); } diff --git a/core/fat.c b/core/fat.c index ce804bf3..3e792fe7 100644 --- a/core/fat.c +++ b/core/fat.c @@ -15,10 +15,9 @@ /* file structure. This holds the information for each currently open file */ struct open_file_t { - uint32_t file_sector; /* sector pointer ( 0 = structure free ) */ + sector_t file_sector; /* sector pointer ( 0 = structure free ) */ uint32_t file_bytesleft; /* number of bytes left */ uint32_t file_left; /* number of sectors left */ - uint32_t pad; /* padding */ }; extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; diff --git a/core/include/disk.h b/core/include/disk.h index 376052dd..386f4f7b 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -8,9 +8,8 @@ #define SECTOR_SHIFT 9 #define SECTOR_SIZE (1 << SECTOR_SHIFT) -/* I do want it be simple for now */ -typedef uint32_t sector_t; -typedef uint32_t block_t; +typedef uint64_t sector_t; +typedef uint64_t block_t; /* diff --git a/core/iso9660.c b/core/iso9660.c index 0a0ae19e..7bf82e6f 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -19,10 +19,9 @@ struct open_file_t { - uint32_t file_sector; + sector_t file_sector; uint32_t file_bytesleft; uint32_t file_left; - uint32_t pad; }; extern char Files[]; -- cgit v1.2.1 From b42cf60c1018f6fe99f2f7e2bd323deeba6fde9c Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 13 Jul 2009 14:34:52 +0800 Subject: Core: fix the HD-mode error in isolinux error fixed. Just as what hpa told, deal with that might simply be to consider a 2K CD sector a "block" rather than a "sector". so, in cdrom mode, we have 2K blocksize and 2k sector size, while in hybrid mode we have 2k blocksize and 512 bytes sector size. --- core/diskio.c | 14 ++++++++++++-- core/iso9660.c | 19 ++++++++++++++++--- core/isolinux.asm | 10 +++++----- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index bb5b34ce..7d3ec3f8 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -17,7 +17,7 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, char *tptr; size_t chunk, freeseg; int sector_shift = disk->sector_shift; - uint32_t xlba = lba; /* Truncated LBA (CHS is << 2 TB) */ + uint32_t xlba = lba + disk->part_start; /* Truncated LBA (CHS is << 2 TB) */ uint32_t t; uint16_t c, h, s; com32sys_t ireg, oreg; @@ -124,6 +124,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, ireg.ds = SEG(&pkt); ireg.esi.w[0] = OFFS(&pkt); + lba += disk->part_start; while (count) { chunk = count; if (chunk > MaxTransfer) @@ -151,7 +152,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, pkt.blocks = chunk; pkt.buf = FAR_PTR(tptr); pkt.lba = lba; - + retry = RETRY_COUNT; for (;;) { @@ -245,6 +246,15 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, bool ebios = cdrom; int sector_size = cdrom ? 2048 : 512; + /* + * set the size be 512 when we are in iso_hybrid mode. + * we estimate it by the devno, As far as I know, the + * cdrom will use 0xe0 and above as the devno, well I'm + * not sure it's right or not. + */ + if (devno < 0xe0) + sector_size = 512; + memset(&ireg, 0, sizeof ireg); /* Get EBIOS support */ diff --git a/core/iso9660.c b/core/iso9660.c index 7bf82e6f..ed5e013f 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -57,6 +57,12 @@ uint8_t RetryCount; /* Used for ISO directory search */ uint16_t bsSecPerTrack; /* Used in hybrid mode */ uint16_t bsHeads; /* Used in hybrid mode */ +/* + * use to store the block shift, since we treat the hd-mode as 512 bytes + * sector size, 2048 bytes block size. we still treat the cdrom as 2048 + * bytes sector size and also the block size. + */ +int block_shift; /** * allocate_file: @@ -235,6 +241,13 @@ int iso_compare_names(char *de_name, int *len, char *file_name) return 1; } +static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, int count) +{ + /* changed those to _sector_ */ + block <<= block_shift; + count <<= block_shift; + return disk->rdwr_sectors(disk, buf, block, count, 0); +} /** * iso_getfssec: @@ -257,7 +270,7 @@ uint32_t iso_getfssec(struct fs_info *fs, char *buf, if ( sectors > file->file_left ) sectors = file->file_left; - disk->rdwr_sectors(disk, buf, file->file_sector, sectors, 0); + cdrom_read_sectors(disk, buf, file->file_sector, sectors); file->file_sector += sectors; file->file_left -= sectors; @@ -515,8 +528,8 @@ int iso_fs_init(struct fs_info *fs) struct open_file_t *open_file; struct disk *disk = fs->fs_dev->disk; - disk->rdwr_sectors(disk, trackbuf, bi_pvd, 1, 0); - + block_shift = ISO_SECTOR_SHIFT - disk->sector_shift; + cdrom_read_sectors(disk, trackbuf, bi_pvd, 1); CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); #ifdef DEBUG diff --git a/core/isolinux.asm b/core/isolinux.asm index ddd45946..4b11b43c 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -1165,12 +1165,12 @@ all_read: ; we should be able to find the rest of what we need to know. ; pushad - extern iso_fs_ops - mov eax,iso_fs_ops - mov dl,[DriveNumber] + extern iso_fs_ops + mov eax,iso_fs_ops + mov dl,[DriveNumber] mov dh,1 ; it's cdrom - mov ecx,[bsHidden] - mov ebx,[bsHidden+4] + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] mov si,[bsHeads] mov di,[bsSecPerTrack] pm_call fs_init -- cgit v1.2.1 From c69d6f0ca9344bce0c090737ce08ce6fe64fa1d6 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 13 Jul 2009 14:47:02 +0800 Subject: Core: code clean cleans the unused variables --- core/diskio.c | 3 ++- core/fs.c | 1 - core/iso9660.c | 16 ---------------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index 7d3ec3f8..90dccbe5 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -304,7 +304,8 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, disk.part_start = part_start; disk.rdwr_sectors = ebios ? edd_rdwr_sectors : chs_rdwr_sectors; +#if 0 dump_disk(&disk); - +#endif return &disk; } diff --git a/core/fs.c b/core/fs.c index 3ebc0b15..165d07e8 100644 --- a/core/fs.c +++ b/core/fs.c @@ -140,5 +140,4 @@ void fs_init(com32sys_t *regs) /* initialize the cache */ if (fs.fs_dev->cache_data) cache_init(fs.fs_dev, blk_shift); - dump_dev(fs.fs_dev); } diff --git a/core/iso9660.c b/core/iso9660.c index ed5e013f..1ce710f7 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -41,22 +41,6 @@ uint16_t BufSafeBytes = TRACKBUF_SIZE; char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ char *ISOFileNameEnd = &ISOFileName[64]; -uint32_t FirstSecSum; /* checksum of bytes 64-2048 */ -uint32_t ImageDwords; /* isolinux.bin size, dwords */ -uint32_t InitStack; /* Initial stack pointer (SS:SP) */ -uint16_t DiskSys; /* Last INT 13h call */ -uint16_t ImageSectors; /* isolinux.bin size, sectors */ - -/* These following two are accessed as a single dword ... */ -uint16_t GetlinsecPtr; /* the sector-read pointer */ -uint16_t BIOSType; -uint8_t DiskError; /* Error code for disk I/O */ -uint8_t DriveNumber; /* CD-ROM BIOS drive number */ -uint8_t ISOFlags; /* Flags for ISO directory search */ -uint8_t RetryCount; /* Used for ISO directory search */ -uint16_t bsSecPerTrack; /* Used in hybrid mode */ -uint16_t bsHeads; /* Used in hybrid mode */ - /* * use to store the block shift, since we treat the hd-mode as 512 bytes * sector size, 2048 bytes block size. we still treat the cdrom as 2048 -- cgit v1.2.1 From d33dbedfe1cddbf578b86d599cdba7c8356b91e8 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 13 Jul 2009 15:56:51 +0800 Subject: Core: fix the hybride mode detection code --- core/diskio.c | 9 --------- core/isolinux.asm | 8 +++++++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index 90dccbe5..cbd93050 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -246,15 +246,6 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, bool ebios = cdrom; int sector_size = cdrom ? 2048 : 512; - /* - * set the size be 512 when we are in iso_hybrid mode. - * we estimate it by the devno, As far as I know, the - * cdrom will use 0xe0 and above as the devno, well I'm - * not sure it's right or not. - */ - if (devno < 0xe0) - sector_size = 512; - memset(&ireg, 0, sizeof ireg); /* Get EBIOS support */ diff --git a/core/isolinux.asm b/core/isolinux.asm index 4b11b43c..f369e598 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -1168,7 +1168,13 @@ all_read: extern iso_fs_ops mov eax,iso_fs_ops mov dl,[DriveNumber] - mov dh,1 ; it's cdrom + cmp word [BIOSType],bios_cdrom + jne hybrid + mov dh,1 ; it's cdrom + jmp end +hybrid: + mov dh,0 ; it's in hybrid mode +end: mov ecx,[bsHidden] mov ebx,[bsHidden+4] mov si,[bsHeads] -- cgit v1.2.1 From 927069c1099f4beb4d0cc6b8972beb6801c03f84 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 13 Jul 2009 16:08:12 +0800 Subject: Core: do trick on the hybrid mode detection --- core/isolinux.asm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/isolinux.asm b/core/isolinux.asm index f369e598..41777d79 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -1169,12 +1169,7 @@ all_read: mov eax,iso_fs_ops mov dl,[DriveNumber] cmp word [BIOSType],bios_cdrom - jne hybrid - mov dh,1 ; it's cdrom - jmp end -hybrid: - mov dh,0 ; it's in hybrid mode -end: + sete dh ; 1 for cdrom, 0 for hybrid mode mov ecx,[bsHidden] mov ebx,[bsHidden+4] mov si,[bsHeads] -- cgit v1.2.1 From c401b53dd8e60a4dd4e913fb472af223cb5d6c48 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 20 Jul 2009 08:46:16 +0800 Subject: Core: some bugs fixed --- core/diskio.c | 13 ++++++++----- core/ext2.c | 4 ++-- core/fat.c | 12 ++++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/core/diskio.c b/core/diskio.c index cbd93050..bf222203 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -57,7 +57,7 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, t = xlba / disk->s; h = t % disk->h; c = t / disk->h; - + ireg.eax.b[0] = chunk; ireg.ecx.b[1] = c; ireg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1); @@ -66,8 +66,8 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, ireg.es = SEG(tptr); retry = RETRY_COUNT; - - for (;;) { + + for (;;) { __intcall(0x13, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF)) break; @@ -76,10 +76,11 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, /* if we are reading ONE sector and go here, just make it _faile_ */ chunk = chunk == 1 ? 0 : ((chunk+1) >> 1); - if (chunk) { + if (chunk) { MaxTransfer = chunk; retry = RETRY_COUNT; - continue; + ireg.eax.b[0] = chunk; + continue; } return done; /* Failure */ } @@ -94,6 +95,7 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, count -= chunk; done += chunk; } + return done; } @@ -165,6 +167,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, if (chunk) { MaxTransfer = chunk; retry = RETRY_COUNT; + pkt.blocks = chunk; continue; } /*** XXX: Consider falling back to CHS here?! ***/ diff --git a/core/ext2.c b/core/ext2.c index 3f55c1ef..115ed218 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -513,10 +513,10 @@ uint32_t ext2_getfssec(struct fs_info *fs, char *buf, sector_idx ++; next_sector ++; - }while(next_sector == linsector(fs, sectors)); + }while(next_sector == linsector(fs, sector_idx)); #if 0 - printf("You are reading stores at sector --0x%x--0x%x\n", + printf("You are reading data stored at sector --0x%x--0x%x\n", frag_start, frag_start + con_sec_cnt -1); #endif getlinsec_ext(fs, buf, frag_start, con_sec_cnt); diff --git a/core/fat.c b/core/fat.c index 3e792fe7..df249a08 100644 --- a/core/fat.c +++ b/core/fat.c @@ -15,9 +15,9 @@ /* file structure. This holds the information for each currently open file */ struct open_file_t { - sector_t file_sector; /* sector pointer ( 0 = structure free ) */ - uint32_t file_bytesleft; /* number of bytes left */ - uint32_t file_left; /* number of sectors left */ + sector_t file_sector; /* sector pointer ( 0 = structure free ) */ + uint32_t file_bytesleft; /* number of bytes left */ + uint32_t file_left; /* number of sectors left */ }; extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; @@ -291,10 +291,10 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, break; }while( next_sector == (++curr_sector) ); -#if 0 /* Debug message */ - printf("You are reading stores at sector --0x%x--0x%x\n", +#if 0 + printf("You are reading data stored at sector --0x%x--0x%x\n", frag_start, frag_start + con_sec_cnt -1); -#endif +#endif /* do read */ disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0); -- cgit v1.2.1 From a6b80d3e8a356a55b4365c5e402e502843bbff8c Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Tue, 4 Aug 2009 17:35:32 -0700 Subject: gpllib: refactor partitions detection Re-implement the logic to parse extended partitions to correctly go through the linked list of partitions. Updated the CLI in hdt and tested it both on Qemu (Debian Lenny installation) and on DELL E6400 (6 partitions). The output seemed sane. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/msdos.c | 107 +++++++++++++++++++++------------------------- com32/hdt/hdt-cli-disk.c | 11 +++-- 2 files changed, 53 insertions(+), 65 deletions(-) diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index 9bfcacca..3b31dd0d 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -29,67 +29,62 @@ static inline int msdos_magic_present(char *ptab) } /** - * process_ebr - execute a callback for each partition contained in an ebr - * @drive_info: driveinfo struct describing the drive - * @ptab_root: part_entry struct describing the root partition (pointing to the ebr) - * @ebr_seen: Number of ebr processed - * @callback: Callback to execute + * process_extended_partition - execute a callback for each partition contained listed in an ebr + * @drive_info: driveinfo struct describing the drive + * @partition_offset: Absolute start (lba) of the partition + * @callback: Callback to execute + * @error: Buffer for I/O errors + * @nb_part_seen: Number of partitions found on the disk so far **/ -static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_root, - int ebr_seen, - void *callback(struct driveinfo *, struct part_entry *, struct part_entry *, int, int, int), - int *error, int offset_root) +static void process_extended_partition(struct driveinfo *drive_info, + int partition_offset, + void *callback(struct driveinfo *, struct part_entry *, int, int), + int *error, int nb_part_seen) { /* The ebr is located at the first sector of the extended partition */ - char* ebr = read_sectors(drive_info, ptab_root->start_lba+offset_root, 1, error); - if (!ebr) + char* ebr = read_sectors(drive_info, partition_offset, 1, error); + + /* If something bad during the read happens, we can't do much: bail out */ + if (*error) return; /* Check msdos magic signature */ - if(!msdos_magic_present(ebr)) + if (!msdos_magic_present(ebr)) return; - ebr_seen += 1; - struct part_entry *ptab_child = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); + struct part_entry *ptab = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); - /* First process the data partitions */ for (int i = 0; i < 4; i++) { - if (*error) - return; + if (!is_extended_partition(&ptab[i])) { + /* + * This EBR partition table entry points to the + * logical partition associated to that EBR + */ + int logical_partition_start = partition_offset + ptab[i].start_lba; - if (ptab_child[i].start_sect > 0) { - if (is_extended_partition(&ptab_child[i])) { + /* Last EBR in the extended partition? */ + if (!logical_partition_start) continue; - } - /* Check for garbage in the 3rd and 4th entries */ - if (i > 2) { - unsigned int offset = ptab_child->start_lba + ptab_root->start_lba; - if ( offset + ptab_child->length <= ptab_root->start_lba || - offset >= ptab_root->start_lba + ptab_root->length ) { - continue; - } - } - callback(drive_info, - &ptab_child[i], - ptab_root, - offset_root, - i, - ebr_seen); - } - } + /* + * Check for garbage: + * 3rd and 4th entries in an EBR should be zero + * Some (malformed) partitioning software still add some + * data partitions there. + */ + if (ptab[i].start_lba <= 0 || ptab[i].length <= 0) + continue; - /* Now process the extended partitions */ - for (int i = 0; i < 4; i++) { - if (is_extended_partition(&ptab_child[i])) { + nb_part_seen++; callback(drive_info, - &ptab_child[i], - ptab_root, - offset_root, - i, - ebr_seen); - process_ebr(drive_info, &ptab_child[i], ebr_seen + 1, callback, error, ptab_root->start_lba); - } + &ptab[i], + logical_partition_start, + nb_part_seen); + } else + process_extended_partition(drive_info, + partition_offset + ptab[i].start_lba, + callback, + error, nb_part_seen); } } @@ -101,7 +96,7 @@ static void process_ebr(struct driveinfo *drive_info, struct part_entry *ptab_ro * @error: Return the error code (I/O), if needed **/ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, - void *callback(struct driveinfo *, struct part_entry *, struct part_entry *, int, int, int), + void *callback(struct driveinfo *, struct part_entry *, int, int), int *error) { for (int i = 0; i < 4; i++) { @@ -112,18 +107,14 @@ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, if (is_extended_partition(&ptab[i])) { callback(drive_info, &ptab[i], - ptab, - 0, - i, - 0); - process_ebr(drive_info, &ptab[i], 0, callback, error, 0); + ptab[i].start_lba, + i+1); + process_extended_partition(drive_info, ptab[i].start_lba, callback, error, 4); } else callback(drive_info, &ptab[i], - ptab, - 0, - i, - 0); + ptab[i].start_lba, + i+1); } } } @@ -138,10 +129,8 @@ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, * * void callback(struct driveinfo *drive_info, * struct part_entry *ptab, - * struct part_entry *ptab_root, * int offset_root, - * int local_partition_number, - * int ebr_seen) + * int nb_part_seen) **/ int parse_partition_table(struct driveinfo *d, void *callback, int *error) { diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 3209c8b1..8e07ed08 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -58,9 +58,8 @@ **/ static void show_partition_information(struct driveinfo *drive_info, struct part_entry *ptab, - struct part_entry *ptab_root, - int offset_root, int data_partitions_seen, - int ebr_seen) + int partition_offset, + int nb_partitions_seen) { char size[8]; char *parttype; @@ -68,10 +67,10 @@ static void show_partition_information(struct driveinfo *drive_info, char *error_buffer; unsigned int start, end; - int i = 1 + ebr_seen * 4 + data_partitions_seen; + int i = nb_partitions_seen; - start = ptab->start_lba + ptab_root->start_lba + offset_root; - end = (ptab->start_lba + ptab_root->start_lba) + ptab->length + offset_root; + start = partition_offset; + end = start + ptab->length; if (ptab->length > 0) sectors_to_size(ptab->length, size); -- cgit v1.2.1 From 35d52abdfc7e6a6af960c80869b6a1e95262810f Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 12:39:21 -0700 Subject: disklib: Fix write_verify_sectors Compare the entire chunk (all sectors), not only the first one. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index 70c73ba4..b772ba72 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -121,7 +121,7 @@ int write_verify_sectors(struct driveinfo* drive_info, if (!rb) return -1; /* Readback failure */ - rv = memcmp(data, rb, SECTOR); + rv = memcmp(data, rb, SECTOR * size); free(rb); return rv ? -1 : 0; } -- cgit v1.2.1 From 737102c3c7abe183e50c1740be3b5c5276b1fa17 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 12:42:37 -0700 Subject: disklib: Change read/write interface Get rid of the error pointer and use a errno-like error reporting mechanism. Intent is to make these more like the standard read/write system calls. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/errno_disk.h | 49 +++++++++++++++ com32/gplinclude/disk/read.h | 7 +-- com32/gplinclude/disk/write.h | 6 +- com32/gpllib/disk/errno_disk.c | 12 ++++ com32/gpllib/disk/error.c | 124 ++----------------------------------- com32/gpllib/disk/msdos.c | 56 +++++++++-------- com32/gpllib/disk/read.c | 56 +++++++++-------- com32/gpllib/disk/write.c | 60 +++++++++--------- 8 files changed, 164 insertions(+), 206 deletions(-) create mode 100644 com32/gplinclude/disk/errno_disk.h create mode 100644 com32/gpllib/disk/errno_disk.c diff --git a/com32/gplinclude/disk/errno_disk.h b/com32/gplinclude/disk/errno_disk.h new file mode 100644 index 00000000..0c4dccb6 --- /dev/null +++ b/com32/gplinclude/disk/errno_disk.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _ERRNO_DISK_H +#define _ERRNO_DISK_H + +extern int errno_disk; + +#define EINV 0x01 /* Invalid function in AH or invalid parameter */ +#define EADDR 0x02 /* Address mark not found */ +#define ERO 0x03 /* Disk write-protected */ +#define ENOFND 0x04 /* Sector not found/read error */ +#define ERFAIL 0x05 /* Reset failed (hard disk) */ +#define ECHANG 0x06 /* Disk changed (floppy) */ +#define EDFAIL 0x07 /* Drive parameter activity failed (hard disk) */ +#define EDMA 0x08 /* DMA overrun */ +#define EBOUND 0x09 /* Data boundary error (attempted DMA across 64K boundary or >80h sectors) */ +#define EBADS 0x0A /* Bad sector detected (hard disk) */ +#define EBADT 0x0B /* Bad track detected (hard disk) */ +#define EINVM 0x0C /* Unsupported track or invalid media */ +#define EINVS 0x0D /* Invalid number of sectors on format (PS/2 hard disk) */ +#define EADDRM 0x0E /* Control data address mark detected (hard disk) */ +#define EDMARG 0x0F /* DMA arbitration level out of range (hard disk) */ +#define ECRCF 0x10 /* Uncorrectable CRC or ECC error on read */ +#define ECRCV 0x11 /* Data ECC corrected (hard disk) */ +#define ECTRL 0x20 /* Controller failure */ +#define EMEDIA 0x31 /* No media in drive (IBM/MS INT 13 extensions) */ +#define ECMOS 0x32 /* Incorrect drive type stored in CMOS (Compaq) */ +#define ESEEKF 0x40 /* Seek failed */ +#define ETIME 0x80 /* Timeout (not ready) */ +#define EREADY 0xAA /* Drive not ready (hard disk) */ +#define ENLOCK 0xB0 /* Volume not locked in drive (INT 13 extensions) */ +#define ELOCK 0xB1 /* Volume locked in drive (INT 13 extensions) */ +#define EREMOV 0xB2 /* Volume not removable (INT 13 extensions) */ +#define EUSED 0xB3 /* Volume in use (INT 13 extensions) */ +#define ECOUNT 0xB4 /* Lock count exceeded (INT 13 extensions) */ +#define EEJF 0xB5 /* Valid eject request failed (INT 13 extensions) */ +#define EUNKOWN 0xBB /* Undefined error (hard disk) */ +#define EWF 0xCC /* Write fault (hard disk) */ +#define ERF 0xE0 /* Status register error (hard disk) */ +#define ESF 0xFF /* Sense operation failed (hard disk) */ + +#endif /* _ERRNO_DISK_H */ diff --git a/com32/gplinclude/disk/read.h b/com32/gplinclude/disk/read.h index 6d6d9fe9..43762a68 100644 --- a/com32/gplinclude/disk/read.h +++ b/com32/gplinclude/disk/read.h @@ -12,8 +12,7 @@ #include -void *read_mbr(int, int*); -void *dev_read(int, unsigned int, int, int*); -void *read_sectors(struct driveinfo*, const unsigned int, - const int, int *); +int read_mbr(int, void*); +int dev_read(int, void*, unsigned int, int); +int read_sectors(struct driveinfo*, void*, const unsigned int, const int); #endif /* _READ_H */ diff --git a/com32/gplinclude/disk/write.h b/com32/gplinclude/disk/write.h index fe251f94..faa80c7d 100644 --- a/com32/gplinclude/disk/write.h +++ b/com32/gplinclude/disk/write.h @@ -18,11 +18,11 @@ #include int write_sectors(const struct driveinfo*, const unsigned int, - const void *, const int, int *); + const void *, const int); int write_verify_sector(struct driveinfo* drive_info, const unsigned int, - const void *, int*); + const void *); int write_verify_sectors(struct driveinfo*, const unsigned int, - const void *, const int, int *); + const void *, const int); #endif diff --git a/com32/gpllib/disk/errno_disk.c b/com32/gpllib/disk/errno_disk.c new file mode 100644 index 00000000..8a68802f --- /dev/null +++ b/com32/gpllib/disk/errno_disk.c @@ -0,0 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include + +int errno_disk; diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 6848ef3e..5491b994 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -9,128 +9,16 @@ #include #include -#include + +#include /** * get_error - decode a disk error status - * @status: Error code - * @buffer_ptr: Pointer to set to the error message + * @buffer_ptr: Preallocated buffer * - * A buffer will be allocated to contain the error message. - * @buffer_ptr will point to it. The caller will need to free it. + * Fill @buffer_ptr with the last errno_disk **/ -void get_error(int status, char** buffer_ptr) +void get_error(void* buffer_ptr) { - int buffer_size = (80 * sizeof(char)); - char* buffer = malloc(buffer_size); - *buffer_ptr = buffer; - - switch (status) { - case 0x0: - strncpy(buffer, "successful completion", buffer_size); - break; - case 0x01: - strncpy(buffer, "invalid function in AH or invalid parameter", buffer_size); - break; - case 0x02: - strncpy(buffer, "address mark not found", buffer_size); - break; - case 0x03: - strncpy(buffer, "disk write-protected", buffer_size); - break; - case 0x04: - strncpy(buffer, "sector not found/read error", buffer_size); - break; - case 0x05: - strncpy(buffer, "reset failed (hard disk)", buffer_size); - //strncpy(buffer, "data did not verify correctly (TI Professional PC)", buffer_size); - break; - case 0x06: - strncpy(buffer, "disk changed (floppy)", buffer_size); - break; - case 0x07: - strncpy(buffer, "drive parameter activity failed (hard disk)", buffer_size); - break; - case 0x08: - strncpy(buffer, "DMA overrun", buffer_size); - break; - case 0x09: - strncpy(buffer, "data boundary error (attempted DMA across 64K boundary or >80h sectors)", buffer_size); - break; - case 0x0A: - strncpy(buffer, "bad sector detected (hard disk)", buffer_size); - break; - case 0x0B: - strncpy(buffer, "bad track detected (hard disk)", buffer_size); - break; - case 0x0C: - strncpy(buffer, "unsupported track or invalid media", buffer_size); - break; - case 0x0D: - strncpy(buffer, "invalid number of sectors on format (PS/2 hard disk)", buffer_size); - break; - case 0x0E: - strncpy(buffer, "control data address mark detected (hard disk)", buffer_size); - break; - case 0x0F: - strncpy(buffer, "DMA arbitration level out of range (hard disk)", buffer_size); - break; - case 0x10: - strncpy(buffer, "uncorrectable CRC or ECC error on read", buffer_size); - break; - case 0x11: - strncpy(buffer, "data ECC corrected (hard disk)", buffer_size); - break; - case 0x20: - strncpy(buffer, "controller failure", buffer_size); - break; - case 0x31: - strncpy(buffer, "no media in drive (IBM/MS INT 13 extensions)", buffer_size); - break; - case 0x32: - strncpy(buffer, "incorrect drive type stored in CMOS (Compaq)", buffer_size); - break; - case 0x40: - strncpy(buffer, "seek failed", buffer_size); - break; - case 0x80: - strncpy(buffer, "timeout (not ready)", buffer_size); - break; - case 0xAA: - strncpy(buffer, "drive not ready (hard disk)", buffer_size); - break; - case 0xB0: - strncpy(buffer, "volume not locked in drive (INT 13 extensions)", buffer_size); - break; - case 0xB1: - strncpy(buffer, "volume locked in drive (INT 13 extensions)", buffer_size); - break; - case 0xB2: - strncpy(buffer, "volume not removable (INT 13 extensions)", buffer_size); - break; - case 0xB3: - strncpy(buffer, "volume in use (INT 13 extensions)", buffer_size); - break; - case 0xB4: - strncpy(buffer, "lock count exceeded (INT 13 extensions)", buffer_size); - break; - case 0xB5: - strncpy(buffer, "valid eject request failed (INT 13 extensions)", buffer_size); - break; - case 0xBB: - strncpy(buffer, "undefined error (hard disk)", buffer_size); - break; - case 0xCC: - strncpy(buffer, "write fault (hard disk)", buffer_size); - break; - case 0xE0: - strncpy(buffer, "status register error (hard disk)", buffer_size); - break; - case 0xFF: - strncpy(buffer, "sense operation failed (hard disk)", buffer_size); - break; - default: - snprintf(buffer, buffer_size, "unknown error 0x%X, buggy bios?", status); - break; - } + sprintf(buffer_ptr, "Disklib: error %d\n", errno_disk); } diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index 3b31dd0d..249d39c4 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -13,6 +13,8 @@ * ----------------------------------------------------------------------- */ #include + +#include #include #include #include @@ -23,7 +25,7 @@ static inline int is_extended_partition(struct part_entry *ptab) ptab->ostype == 0x0f || ptab->ostype == 0x85); } -static inline int msdos_magic_present(char *ptab) +static inline int msdos_magic_present(const char *ptab) { return ( *(uint16_t *)(ptab + 0x1fe) == 0xaa55 ); } @@ -36,25 +38,28 @@ static inline int msdos_magic_present(char *ptab) * @error: Buffer for I/O errors * @nb_part_seen: Number of partitions found on the disk so far **/ -static void process_extended_partition(struct driveinfo *drive_info, +static int process_extended_partition(struct driveinfo *drive_info, int partition_offset, void *callback(struct driveinfo *, struct part_entry *, int, int), - int *error, int nb_part_seen) + int nb_part_seen) { + int status = 0; /* The ebr is located at the first sector of the extended partition */ - char* ebr = read_sectors(drive_info, partition_offset, 1, error); + char* ebr = malloc(SECTOR * sizeof(char)); - /* If something bad during the read happens, we can't do much: bail out */ - if (*error) - return; + if (read_sectors(drive_info, ebr, partition_offset, 1) == -1) + return -1; /* Check msdos magic signature */ if (!msdos_magic_present(ebr)) - return; + return -1; struct part_entry *ptab = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); for (int i = 0; i < 4; i++) { + if (status == -1) + return -1; + if (!is_extended_partition(&ptab[i])) { /* * This EBR partition table entry points to the @@ -81,11 +86,13 @@ static void process_extended_partition(struct driveinfo *drive_info, logical_partition_start, nb_part_seen); } else - process_extended_partition(drive_info, + status = process_extended_partition(drive_info, partition_offset + ptab[i].start_lba, callback, - error, nb_part_seen); + nb_part_seen); } + + return 0; } /** @@ -93,15 +100,15 @@ static void process_extended_partition(struct driveinfo *drive_info, * @drive_info: driveinfo struct describing the drive * @ptab: Pointer to the partition table * @callback: Callback to execute - * @error: Return the error code (I/O), if needed **/ -static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, - void *callback(struct driveinfo *, struct part_entry *, int, int), - int *error) +static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, + void *callback(struct driveinfo *, struct part_entry *, int, int)) { + int status = 0; + for (int i = 0; i < 4; i++) { - if (*error) - return; + if (status == -1) + return -1; if (ptab[i].start_sect > 0) { if (is_extended_partition(&ptab[i])) { @@ -109,7 +116,7 @@ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, &ptab[i], ptab[i].start_lba, i+1); - process_extended_partition(drive_info, ptab[i].start_lba, callback, error, 4); + status = process_extended_partition(drive_info, ptab[i].start_lba, callback, 4); } else callback(drive_info, &ptab[i], @@ -117,6 +124,8 @@ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, i+1); } } + + return 0; } /** @@ -132,10 +141,11 @@ static void process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, * int offset_root, * int nb_part_seen) **/ -int parse_partition_table(struct driveinfo *d, void *callback, int *error) +int parse_partition_table(struct driveinfo *d, void *callback) { - char *mbr = read_mbr(d->disk, error); - if (!mbr) + char *mbr = malloc(SECTOR * sizeof(char)); + + if (read_mbr(d->disk, mbr) == -1) return -1; else { /* Check msdos magic signature */ @@ -143,10 +153,6 @@ int parse_partition_table(struct driveinfo *d, void *callback, int *error) return -1; struct part_entry *ptab = (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); - process_mbr(d, ptab, callback, error); - if (*error) - return -1; - else - return 0; + return process_mbr(d, ptab, callback); } } diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c index 3fc0e0c7..74840829 100644 --- a/com32/gpllib/disk/read.c +++ b/com32/gpllib/disk/read.c @@ -16,61 +16,72 @@ #include #include +#include #include #include #include #include +/* + * TODO: implement file descriptors to cache metadata (geometry, ...) + */ + /** * read_mbr - return a pointer to a malloced buffer containing the mbr * @drive: Drive number - * @error: Return the error code on failure + * @buf: Pre-allocated buffer for output + * + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. **/ -void *read_mbr(int drive, int *error) +int read_mbr(int drive, void *buf) { struct driveinfo drive_info; drive_info.disk = drive; /* MBR: lba = 0, 1 sector */ - return read_sectors(&drive_info, 0, 1, error); + return read_sectors(&drive_info, buf, 0, 1); } /** * dev_read - read from a drive * @drive: Drive number + * @buf: Pre-allocated buffer for output * @lba: Position to start reading from * @sectors: Number of sectors to read - * @error: Return the error code on failure * * High-level routine to read from a hard drive. + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. **/ -void *dev_read(int drive, unsigned int lba, int sectors, int *error) +int dev_read(int drive, void * buf, unsigned int lba, int sectors) { struct driveinfo drive_info; drive_info.disk = drive; - return read_sectors(&drive_info, lba, sectors, error); + return read_sectors(&drive_info, buf, lba, sectors); } /** * read_sectors - read several sectors from disk * @drive_info: driveinfo struct describing the disk + * @data: Pre-allocated buffer for output * @lba: Position to read * @sectors: Number of sectors to read - * @error: Return the error code on failure * - * Return a pointer to a malloc'ed buffer containing the data. + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. **/ -void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, - const int sectors, int *error) +int read_sectors(struct driveinfo* drive_info, void *data, + const unsigned int lba, const int sectors) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; - void *data; + char *bufp = data; if (get_drive_parameters(drive_info) == -1) - return NULL; + return -1; memset(&inreg, 0, sizeof inreg); @@ -88,17 +99,18 @@ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, } else { unsigned int c, h, s; - if (!drive_info->cbios) { + if (!drive_info->cbios) { // XXX errno /* We failed to get the geometry */ if (lba) - return NULL; /* Can only read MBR */ + return -1; /* Can only read MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); + // XXX errno if ( s > 63 || h > 256 || c > 1023 ) - return NULL; + return -1; inreg.eax.w[0] = 0x0201; /* Read one sector */ inreg.ecx.b[1] = c & 0xff; @@ -111,17 +123,11 @@ void *read_sectors(struct driveinfo* drive_info, const unsigned int lba, /* Perform the read */ if (int13_retry(&inreg, &outreg)) { - if (error) - *error = outreg.eax.b[1]; - return NULL; /* Give up */ - } else { - if (error) - *error = 0; + errno_disk = outreg.eax.b[1]; + return -1; /* Give up */ } - data = malloc(sectors * SECTOR); - if (data) - memcpy(data, buf, sectors * SECTOR); + memcpy(bufp, buf, sectors * SECTOR); - return data; + return sectors; } diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c index b772ba72..a236f37d 100644 --- a/com32/gpllib/disk/write.c +++ b/com32/gpllib/disk/write.c @@ -15,10 +15,12 @@ #include #include #include -#include -#include + #include +#include +#include #include +#include /** * write_sectors - write several sectors from disk @@ -26,10 +28,12 @@ * @lba: Position to write * @data: Buffer to write * @size: Size of the buffer (number of sectors) - * @error: Return the error code on failure + * + * Return the number of sectors write on success or -1 on failure. + * errno_disk contains the error number. **/ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, - const void *data, const int size, int *error) + const void *data, const int size) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; @@ -38,7 +42,7 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, memcpy(buf, data, size); memset(&inreg, 0, sizeof inreg); - if ( drive_info->ebios ) { + if (drive_info->ebios) { dapa->len = sizeof(*dapa); dapa->count = size; dapa->off = OFFS(buf); @@ -52,16 +56,16 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, } else { unsigned int c, h, s; - if ( !drive_info->cbios ) { - /* We failed to get the geometry */ - - if ( lba ) - return -1; /* Can only write MBR */ + if (!drive_info->cbios) { // XXX errno + /* We failed to get the geometry */ + if (lba) + return -1; /* Can only write MBR */ - s = 1; h = 0; c = 0; + s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); + // XXX errno if ( s > 63 || h > 256 || c > 1023 ) return -1; @@ -76,14 +80,10 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, /* Perform the write */ if (int13_retry(&inreg, &outreg)) { - if (error) - *error = outreg.eax.b[1]; + errno_disk = outreg.eax.b[1]; return -1; /* Give up */ - } else { - if (error) - *error = 0; - return 0; - } + } else + return size; } /** @@ -94,9 +94,9 @@ int write_sectors(const struct driveinfo* drive_info, const unsigned int lba, **/ int write_verify_sector(struct driveinfo* drive_info, const unsigned int lba, - const void *data, int *error) + const void *data) { - return write_verify_sectors(drive_info, lba, data, SECTOR, error); + return write_verify_sectors(drive_info, lba, data, SECTOR); } /** @@ -108,20 +108,18 @@ int write_verify_sector(struct driveinfo* drive_info, **/ int write_verify_sectors(struct driveinfo* drive_info, const unsigned int lba, - const void *data, const int size, int* error) + const void *data, const int size) { - char *rb; - int rv; + char *rb = malloc(SECTOR * size * sizeof(char)); + int status; - rv = write_sectors(drive_info, lba, data, size, error); - if (rv) - return rv; /* Write failure */ + if (write_sectors(drive_info, lba, data, size) == -1) + return -1; /* Write failure */ - rb = read_sectors(drive_info, lba, size, error); - if (!rb) - return -1; /* Readback failure */ + if (read_sectors(drive_info, rb, lba, size) == -1) + return -1; /* Readback failure */ - rv = memcmp(data, rb, SECTOR * size); + status = memcmp(data, rb, SECTOR * size); free(rb); - return rv ? -1 : 0; + return status ? -1 : 0; } -- cgit v1.2.1 From 4d9e463c3fb68f3c1c967f73c5f39dc43ba9fed1 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 13:48:54 -0700 Subject: gpllib: Fix compilation ata.c was missing the inttypes.h header. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/disk/ata.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com32/gpllib/disk/ata.c b/com32/gpllib/disk/ata.c index f1716ffa..d74dda8f 100644 --- a/com32/gpllib/disk/ata.c +++ b/com32/gpllib/disk/ata.c @@ -1,3 +1,5 @@ +#include + /** * ata_id_string - Convert IDENTIFY DEVICE page into string * @id: IDENTIFY DEVICE results we will examine -- cgit v1.2.1 From 724c1ef7714087cf643bb0b34f92f09eca8c8d39 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 13:49:37 -0700 Subject: gpllib: Enhance Makefile Leverage Make built-ins rather than listing manually all objects files to compile. Signed-off-by: Pierre-Alexandre Meyer --- com32/gpllib/Makefile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile index 8026a45c..fa866dba 100644 --- a/com32/gpllib/Makefile +++ b/com32/gpllib/Makefile @@ -8,12 +8,8 @@ include ../lib/MCONFIG REQFLAGS += -I../gplinclude -LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ - dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ - dmi/dmi_ipmi.o dmi/dmi_cache.o cpuid.o disk/geom.o disk/read.o \ - disk/write.o disk/msdos.o \ - disk/util.o disk/labels.o disk/swsusp.o disk/error.o vpd/vpd.o \ - memory.o +GPLDIRS := . disk dmi vpd +LIBOBJS := $(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))) BINDIR = /usr/bin LIBDIR = /usr/lib -- cgit v1.2.1 From 2acba746d510b460fffd29ec5538962fec3cebda Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 15:09:47 -0700 Subject: gpllib: More errno fixes * Fix header files due to previous commit * Prefix disk errnos with ED to avoid conflicts with classic errno * Fix swsusp code to use errno_disk Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/errno_disk.h | 68 ++++++++++++++++++++------------------ com32/gplinclude/disk/msdos.h | 2 +- com32/gplinclude/disk/swsusp.h | 2 +- com32/gpllib/disk/error.c | 2 +- com32/gpllib/disk/swsusp.c | 16 ++++----- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/com32/gplinclude/disk/errno_disk.h b/com32/gplinclude/disk/errno_disk.h index 0c4dccb6..055eaf58 100644 --- a/com32/gplinclude/disk/errno_disk.h +++ b/com32/gplinclude/disk/errno_disk.h @@ -10,40 +10,44 @@ #ifndef _ERRNO_DISK_H #define _ERRNO_DISK_H +/* Max length of the error string */ +#define MAX_DISK_ERRNO 9 + extern int errno_disk; -#define EINV 0x01 /* Invalid function in AH or invalid parameter */ -#define EADDR 0x02 /* Address mark not found */ -#define ERO 0x03 /* Disk write-protected */ -#define ENOFND 0x04 /* Sector not found/read error */ -#define ERFAIL 0x05 /* Reset failed (hard disk) */ -#define ECHANG 0x06 /* Disk changed (floppy) */ +/* Prefix with ED to avoid confusion with errno */ +#define EDINV 0x01 /* Invalid function in AH or invalid parameter */ +#define EDADDR 0x02 /* Address mark not found */ +#define EDRO 0x03 /* Disk write-protected */ +#define EDNOFND 0x04 /* Sector not found/read error */ +#define EDRFAIL 0x05 /* Reset failed (hard disk) */ +#define EDCHANG 0x06 /* Disk changed (floppy) */ #define EDFAIL 0x07 /* Drive parameter activity failed (hard disk) */ -#define EDMA 0x08 /* DMA overrun */ -#define EBOUND 0x09 /* Data boundary error (attempted DMA across 64K boundary or >80h sectors) */ -#define EBADS 0x0A /* Bad sector detected (hard disk) */ -#define EBADT 0x0B /* Bad track detected (hard disk) */ -#define EINVM 0x0C /* Unsupported track or invalid media */ -#define EINVS 0x0D /* Invalid number of sectors on format (PS/2 hard disk) */ -#define EADDRM 0x0E /* Control data address mark detected (hard disk) */ -#define EDMARG 0x0F /* DMA arbitration level out of range (hard disk) */ -#define ECRCF 0x10 /* Uncorrectable CRC or ECC error on read */ -#define ECRCV 0x11 /* Data ECC corrected (hard disk) */ -#define ECTRL 0x20 /* Controller failure */ -#define EMEDIA 0x31 /* No media in drive (IBM/MS INT 13 extensions) */ -#define ECMOS 0x32 /* Incorrect drive type stored in CMOS (Compaq) */ -#define ESEEKF 0x40 /* Seek failed */ -#define ETIME 0x80 /* Timeout (not ready) */ -#define EREADY 0xAA /* Drive not ready (hard disk) */ -#define ENLOCK 0xB0 /* Volume not locked in drive (INT 13 extensions) */ -#define ELOCK 0xB1 /* Volume locked in drive (INT 13 extensions) */ -#define EREMOV 0xB2 /* Volume not removable (INT 13 extensions) */ -#define EUSED 0xB3 /* Volume in use (INT 13 extensions) */ -#define ECOUNT 0xB4 /* Lock count exceeded (INT 13 extensions) */ -#define EEJF 0xB5 /* Valid eject request failed (INT 13 extensions) */ -#define EUNKOWN 0xBB /* Undefined error (hard disk) */ -#define EWF 0xCC /* Write fault (hard disk) */ -#define ERF 0xE0 /* Status register error (hard disk) */ -#define ESF 0xFF /* Sense operation failed (hard disk) */ +#define EDDMA 0x08 /* DMA overrun */ +#define EDBOUND 0x09 /* Data boundary error (attempted DMA across 64K boundary or >80h sectors) */ +#define EDBADS 0x0A /* Bad sector detected (hard disk) */ +#define EDBADT 0x0B /* Bad track detected (hard disk) */ +#define EDINVM 0x0C /* Unsupported track or invalid media */ +#define EDINVS 0x0D /* Invalid number of sectors on format (PS/2 hard disk) */ +#define EDADDRM 0x0E /* Control data address mark detected (hard disk) */ +#define EDDMARG 0x0F /* DMA arbitration level out of range (hard disk) */ +#define EDCRCF 0x10 /* Uncorrectable CRC or ECC error on read */ +#define EDCRCV 0x11 /* Data ECC corrected (hard disk) */ +#define EDCTRL 0x20 /* Controller failure */ +#define EDMEDIA 0x31 /* No media in drive (IBM/MS INT 13 extensions) */ +#define EDCMOS 0x32 /* Incorrect drive type stored in CMOS (Compaq) */ +#define EDSEEKF 0x40 /* Seek failed */ +#define EDTIME 0x80 /* Timeout (not ready) */ +#define EDREADY 0xAA /* Drive not ready (hard disk) */ +#define EDNLOCK 0xB0 /* Volume not locked in drive (INT 13 extensions) */ +#define EDLOCK 0xB1 /* Volume locked in drive (INT 13 extensions) */ +#define EDREMOV 0xB2 /* Volume not removable (INT 13 extensions) */ +#define EDUSED 0xB3 /* Volume in use (INT 13 extensions) */ +#define EDCOUNT 0xB4 /* Lock count exceeded (INT 13 extensions) */ +#define EDEJF 0xB5 /* Valid eject request failed (INT 13 extensions) */ +#define EDUNKOWN 0xBB /* Undefined error (hard disk) */ +#define EDWF 0xCC /* Write fault (hard disk) */ +#define EDRF 0xE0 /* Status register error (hard disk) */ +#define EDSF 0xFF /* Sense operation failed (hard disk) */ #endif /* _ERRNO_DISK_H */ diff --git a/com32/gplinclude/disk/msdos.h b/com32/gplinclude/disk/msdos.h index 1f565f32..c8dcb1de 100644 --- a/com32/gplinclude/disk/msdos.h +++ b/com32/gplinclude/disk/msdos.h @@ -12,6 +12,6 @@ #include -int parse_partition_table(struct driveinfo *, void *, int *); +int parse_partition_table(struct driveinfo *, void *); #endif /* _MSDOS_H_ */ diff --git a/com32/gplinclude/disk/swsusp.h b/com32/gplinclude/disk/swsusp.h index 54140b3d..1d77c878 100644 --- a/com32/gplinclude/disk/swsusp.h +++ b/com32/gplinclude/disk/swsusp.h @@ -15,5 +15,5 @@ struct swsusp_header { char sig[10]; } __attribute__((packed)); -int swsusp_check(struct driveinfo*, struct part_entry*, int*); +int swsusp_check(struct driveinfo*, struct part_entry*); #endif /* _SWSUSP_H */ diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 5491b994..2b82c359 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -20,5 +20,5 @@ **/ void get_error(void* buffer_ptr) { - sprintf(buffer_ptr, "Disklib: error %d\n", errno_disk); + snprintf(buffer_ptr, MAX_DISK_ERRNO, "Disklib: error %d\n", errno_disk); } diff --git a/com32/gpllib/disk/swsusp.c b/com32/gpllib/disk/swsusp.c index f627aca4..ac9724aa 100644 --- a/com32/gpllib/disk/swsusp.c +++ b/com32/gpllib/disk/swsusp.c @@ -9,23 +9,19 @@ * swsusp_check - check if a (swap) partition contains the swsusp signature * @drive_info: driveinfo struct describing the disk containing the partition * @ptab; Partition table of the partition - * @error: Return the error code on failure **/ -int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab, int *error) +int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab) { - struct swsusp_header *header_p; + struct swsusp_header header_p; int offset; int found; /* Read first page of the swap device */ offset = ptab->start_lba; - header_p = (struct swsusp_header *) read_sectors(drive_info, offset, PAGE_SIZE/SECTOR, error); - - if (!header_p) - return -1; /* The error code has been stored in `error' */ - else { - found = !memcmp(SWSUSP_SIG, header_p->sig, 10); - free(header_p); + if (read_sectors(drive_info, &header_p, offset, PAGE_SIZE/SECTOR) == -1) { + return -1; + } else { + found = !memcmp(SWSUSP_SIG, header_p.sig, 10); return found; } } -- cgit v1.2.1 From d9347453718a27439b33b6020b996621439cebb7 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 15:11:01 -0700 Subject: hdt: Make the menu and cli use the new disk interfaces The disklib interfaces have changed (errno_disk introduced). Update these changes in hdt (nobody else use them). Misc: fix get_error declaration. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/error.h | 2 +- com32/hdt/hdt-cli-disk.c | 24 +++++++++--------------- com32/hdt/hdt-menu-disk.c | 36 +++++++++++++----------------------- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/com32/gplinclude/disk/error.h b/com32/gplinclude/disk/error.h index 5eb54e01..f9e319c4 100644 --- a/com32/gplinclude/disk/error.h +++ b/com32/gplinclude/disk/error.h @@ -9,5 +9,5 @@ #ifndef _ERROR_H_ #define _ERROR_H_ -void get_error(const int, char**); +void get_error(void*); #endif /* _UTIL_H_ */ diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 8e07ed08..197d1703 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -64,7 +65,7 @@ static void show_partition_information(struct driveinfo *drive_info, char size[8]; char *parttype; int error = 0; - char *error_buffer; + char error_buffer[MAX_DISK_ERRNO]; unsigned int start, end; int i = nb_partitions_seen; @@ -86,10 +87,10 @@ static void show_partition_information(struct driveinfo *drive_info, ptab->ostype, parttype); /* Extra info */ - if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab, &error)) { + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) { more_printf("%s", " (Swsusp sig. detected)"); } else if (error) { - get_error(error, &error_buffer); + get_error(&error_buffer); more_printf("%s\n", error_buffer); free(error_buffer); } @@ -117,8 +118,7 @@ void main_show_disk(int argc, char **argv, int i = drive - 0x80; struct driveinfo *d = &hardware->disk_info[i]; - int error; - char *error_buffer; + char error_buffer[MAX_DISK_ERRNO]; char disk_size[8]; detect_disks(hardware); @@ -144,16 +144,10 @@ void main_show_disk(int argc, char **argv, remove_spaces(d->edd_params.interface_type)); more_printf(" # B Start End Size Id Type\n"); - error = 0; - if (parse_partition_table(d, &show_partition_information, &error)) { - if (error) { - more_printf("I/O error: "); - get_error(error, &error_buffer); - more_printf("%s\n", error_buffer); - free(error_buffer); - } else - more_printf("An unknown error occured.\n"); - return; + if (parse_partition_table(d, &show_partition_information) == -1) { + get_error(&error_buffer); + more_printf("%s\n", error_buffer); + free(error_buffer); } } diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 7e60b06e..4915050d 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -85,8 +86,7 @@ static void compute_partition_information(struct driveinfo *drive_info, { char size[8]; char *parttype; - int error = 0; - char *error_buffer; + char error_buffer[MAX_DISK_ERRNO]; unsigned int start, end; char buffer[SUBMENULEN+1]; char statbuffer[STATLEN+1]; @@ -155,16 +155,15 @@ static void compute_partition_information(struct driveinfo *drive_info, free(parttype); /* Extra info */ - if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab, &error)) { + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab) != -1) { snprintf(buffer, sizeof buffer, "%s","Swsusp sig : detected"); snprintf(statbuffer, sizeof statbuffer, "%s","Swsusp sig : detected"); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - } else if (error) { - get_error(error, &error_buffer); + } else { + get_error(&error_buffer); snprintf(buffer, sizeof buffer, "%s",error_buffer); snprintf(statbuffer, sizeof statbuffer, "%s",error_buffer); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - free(error_buffer); } } @@ -224,23 +223,14 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_sep(); dn=disk_number; - int error; - parse_partition_table(&d[disk_number], &show_partition_information, &error); - if (parse_partition_table(&d[disk_number], &compute_partition_information, &error)) { - if (error) { - char *error_buffer; - get_error(error, &error_buffer); - snprintf(buffer, sizeof buffer, "I/O error : %s", error_buffer); - snprintf(statbuffer, sizeof statbuffer, "I/O error : %s", error_buffer); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - free(error_buffer); - } else { - snprintf(buffer, sizeof buffer, "An unknown error occured"); - snprintf(statbuffer, sizeof statbuffer, "An unknown error occured"); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - menu[nb_sub_disk_menu].items_count++; - } + parse_partition_table(&d[disk_number], &show_partition_information); + if (parse_partition_table(&d[disk_number], &compute_partition_information) == -1) { + char error_buffer[MAX_DISK_ERRNO]; + get_error(&error_buffer); + snprintf(buffer, sizeof buffer, "I/O error : %s", error_buffer); + snprintf(statbuffer, sizeof statbuffer, "I/O error : %s", error_buffer); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; } return 0; -- cgit v1.2.1 From f8ac660c0fae6328bde62164f8f01b17b9dc5522 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 15:59:57 -0700 Subject: hdt: Fix disk menu to use the new disklib interfaces Adapt the disk menu to use the new disklib interfaces. This fixes bugs related to the display of partition numbering and swsusp signature. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli.h | 3 --- com32/hdt/hdt-common.h | 3 +++ com32/hdt/hdt-menu-disk.c | 42 +++++++++++++----------------------------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 651575d1..47137cca 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -40,9 +40,6 @@ # define dprintf(f, ...) ((void)0) #endif -/* Declare a variable or data structure as unused. */ -#define __unused __attribute__ (( unused )) - #define MAX_LINE_SIZE 256 #define CLI_SPACE " " diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h index 5118dd6a..2b67f9ca 100644 --- a/com32/hdt/hdt-common.h +++ b/com32/hdt/hdt-common.h @@ -40,6 +40,9 @@ #include "../lib/sys/vesa/vesa.h" #include +/* Declare a variable or data structure as unused. */ +#define __unused __attribute__ (( unused )) + /* This two values are used for switching for the menu to the CLI mode */ #define HDT_SWITCH_TO_CLI "hdt_switch_to_cli" #define HDT_RETURN_TO_CLI 100 diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 4915050d..05aef70a 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -41,27 +41,21 @@ static int dn; static void show_partition_information(struct driveinfo *drive_info, - struct part_entry *ptab, - struct part_entry *ptab_root, - int offset_root, int data_partitions_seen, - int ebr_seen) + struct part_entry *ptab __unused, + int partition_offset __unused, + int nb_partitions_seen) { char menu_title[MENULEN + 1]; char menu_title_ref[MENULEN + 1]; - /* Useless code to prevent warnings */ - ptab=ptab; ptab_root=ptab_root;offset_root=offset_root; - - int i = 1 + ebr_seen * 4 + data_partitions_seen; memset(menu_title,0,sizeof menu_title); memset(menu_title_ref,0,sizeof menu_title_ref); - snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", - drive_info[dn].disk, i); - snprintf(menu_title, sizeof menu_title, "Partition %d", i); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", + drive_info[dn].disk, nb_partitions_seen); + snprintf(menu_title, sizeof menu_title, "Partition %d", nb_partitions_seen); add_item(menu_title, "Partition information (start, end, length, type, ...)", OPT_SUBMENU, menu_title_ref, 0); - } /** * compute_partition_information - print information about a partition @@ -79,34 +73,30 @@ static void show_partition_information(struct driveinfo *drive_info, * at the MBR... but still not absolute! **/ static void compute_partition_information(struct driveinfo *drive_info, - struct part_entry *ptab, - struct part_entry *ptab_root, - int offset_root, int data_partitions_seen, - int ebr_seen) + struct part_entry *ptab, + int partition_offset, + int nb_partitions_seen) { char size[8]; char *parttype; - char error_buffer[MAX_DISK_ERRNO]; unsigned int start, end; char buffer[SUBMENULEN+1]; char statbuffer[STATLEN+1]; char menu_title[MENULEN + 1]; char menu_title_ref[MENULEN + 1]; - int i = 1 + ebr_seen * 4 + data_partitions_seen; - memset(buffer,0,sizeof buffer); memset(statbuffer,0,sizeof statbuffer); memset(menu_title,0,sizeof menu_title); memset(menu_title_ref,0,sizeof menu_title_ref); - snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", drive_info[dn].disk, i); - snprintf(menu_title, sizeof menu_title, "Partition %d", i); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", drive_info[dn].disk, nb_partitions_seen); + snprintf(menu_title, sizeof menu_title, "Partition %d", nb_partitions_seen); add_named_menu(menu_title_ref,menu_title,-1); set_menu_pos(SUBMENU_Y,SUBMENU_X); - start = ptab->start_lba + ptab_root->start_lba + offset_root; - end = (ptab->start_lba + ptab_root->start_lba) + ptab->length + offset_root; + start = partition_offset; + end = start + ptab->length; if (ptab->length > 0) sectors_to_size(ptab->length, size); @@ -159,13 +149,7 @@ static void compute_partition_information(struct driveinfo *drive_info, snprintf(buffer, sizeof buffer, "%s","Swsusp sig : detected"); snprintf(statbuffer, sizeof statbuffer, "%s","Swsusp sig : detected"); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); - } else { - get_error(&error_buffer); - snprintf(buffer, sizeof buffer, "%s",error_buffer); - snprintf(statbuffer, sizeof statbuffer, "%s",error_buffer); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); } - } /* Compute the disk submenu */ -- cgit v1.2.1 From 22a679c93b85c064844b0a12cb1e59eba1cf4aa4 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 19:19:59 -0700 Subject: hdt: Don't show partition header if not needed Don't blindly print the partition header: check if we are able to iterate through them first. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 4 +++- com32/hdt/hdt-menu-disk.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 197d1703..07f72930 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -78,6 +78,9 @@ static void show_partition_information(struct driveinfo *drive_info, else memset(size, 0, sizeof size); + if (i == 1) + more_printf(" # B Start End Size Id Type\n"); + get_label(ptab->ostype, &parttype); more_printf(" %2d %s %11d %11d %s %02X %s", i, (ptab->active_flag == 0x80) ? "x" : " ", @@ -143,7 +146,6 @@ void main_show_disk(int argc, char **argv, remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); - more_printf(" # B Start End Size Id Type\n"); if (parse_partition_table(d, &show_partition_information) == -1) { get_error(&error_buffer); more_printf("%s\n", error_buffer); diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 05aef70a..487d1e45 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -48,6 +48,9 @@ static void show_partition_information(struct driveinfo *drive_info, char menu_title[MENULEN + 1]; char menu_title_ref[MENULEN + 1]; + if (nb_partitions_seen == 1) + add_sep(); + memset(menu_title,0,sizeof menu_title); memset(menu_title_ref,0,sizeof menu_title_ref); snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", @@ -204,7 +207,6 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; - add_sep(); dn=disk_number; parse_partition_table(&d[disk_number], &show_partition_information); -- cgit v1.2.1 From 9636a1bbb1c1394fc9fb7cf66d97ffe5f5f43ff3 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 21:03:04 -0700 Subject: gpllib: Introduce typedefs for callbacks typedefs are evil but useful for function pointers as it makes them more readable and maintainable. This fixes a bug by the way: we had void *callback(struct driveinfo *, struct part_entry *, int, int) where we should have had void (*callback)(struct driveinfo *, struct part_entry *, int, int) Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/msdos.h | 4 +++- com32/gpllib/disk/msdos.c | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/com32/gplinclude/disk/msdos.h b/com32/gplinclude/disk/msdos.h index c8dcb1de..405b9b99 100644 --- a/com32/gplinclude/disk/msdos.h +++ b/com32/gplinclude/disk/msdos.h @@ -11,7 +11,9 @@ #define _MSDOS_H_ #include +#include -int parse_partition_table(struct driveinfo *, void *); +typedef void (*p_callback)(struct driveinfo *, struct part_entry *, int, int); +int parse_partition_table(struct driveinfo *, p_callback); #endif /* _MSDOS_H_ */ diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index 249d39c4..e69aa71b 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -40,7 +41,7 @@ static inline int msdos_magic_present(const char *ptab) **/ static int process_extended_partition(struct driveinfo *drive_info, int partition_offset, - void *callback(struct driveinfo *, struct part_entry *, int, int), + p_callback callback, int nb_part_seen) { int status = 0; @@ -102,7 +103,7 @@ static int process_extended_partition(struct driveinfo *drive_info, * @callback: Callback to execute **/ static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, - void *callback(struct driveinfo *, struct part_entry *, int, int)) + p_callback callback) { int status = 0; @@ -132,7 +133,6 @@ static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, * parse_partition_table - execute a callback for each partition entry * @d: driveinfo struct describing the drive * @callback: Callback to execute - * @error: Return the error code (I/O), if needed * * The signature of the callback should be the following: * @@ -141,7 +141,7 @@ static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, * int offset_root, * int nb_part_seen) **/ -int parse_partition_table(struct driveinfo *d, void *callback) +int parse_partition_table(struct driveinfo *d, p_callback callback) { char *mbr = malloc(SECTOR * sizeof(char)); -- cgit v1.2.1 From 2ce3248c238ee5c74635ce3ded583adcd42d7a48 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 5 Aug 2009 21:31:13 -0700 Subject: hdt: Remove extra more_printf calls Let's rather use string concatenation. Reported-by: Shao Miller Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 07f72930..ffbec4f1 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -133,18 +133,16 @@ void main_show_disk(int argc, char **argv, else memset(disk_size, 0, sizeof disk_size); - more_printf("DISK 0x%X:\n", d->disk); - more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n", - d->legacy_max_cylinder + 1, d->legacy_max_head + 1, - d->legacy_sectors_per_track); - more_printf(" EDD: Version: %X\n", d->edd_version); - more_printf(" Size: %s, %d bytes/sector, %d sectors/track\n", - disk_size, - (int) d->edd_params.bytes_per_sector, - (int) d->edd_params.sectors_per_track); - more_printf(" Host bus: %s, Interface type: %s\n\n", - remove_spaces(d->edd_params.host_bus_type), - remove_spaces(d->edd_params.interface_type)); + more_printf("DISK 0x%X:\n" + " C/H/S: %d cylinders, %d heads, %d sectors/track\n" + " EDD: Version: %X\n" + " Size: %s, %d bytes/sector, %d sectors/track\n" + " Host bus: %s, Interface type: %s\n\n", + d->disk, + d->legacy_max_cylinder + 1, d->legacy_max_head + 1, d->legacy_sectors_per_track, + d->edd_version, + disk_size, (int) d->edd_params.bytes_per_sector, (int) d->edd_params.sectors_per_track, + remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); if (parse_partition_table(d, &show_partition_information) == -1) { get_error(&error_buffer); -- cgit v1.2.1 From 184bc83718963636297d230d8f3846d025942a72 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 6 Aug 2009 15:17:48 +0800 Subject: Core:PXELINUX: try to merge pxelinux the others Syslinux derivative disabled for now --- com32/include/com32.h | 12 +- core/Makefile | 6 +- core/bios.inc | 1 + core/cache.c | 11 +- core/dhcp_option.c | 259 +++++++ core/disk.c | 39 - core/diskio.c | 40 + core/dnsresolv.inc | 4 + core/extern.inc | 3 + core/fs.c | 50 +- core/include/disk.h | 1 + core/include/fs.h | 2 +- core/include/pxe.h | 370 +++++++++ core/parsecmd.inc | 1 + core/pxe.c | 1551 ++++++++++++++++++++++++++++++++++++++ core/pxelinux.asm | 1993 ++----------------------------------------------- 16 files changed, 2301 insertions(+), 2042 deletions(-) create mode 100644 core/dhcp_option.c delete mode 100644 core/disk.c create mode 100644 core/include/pxe.h create mode 100644 core/pxe.c diff --git a/com32/include/com32.h b/com32/include/com32.h index c003f7ca..50485ae3 100644 --- a/com32/include/com32.h +++ b/com32/include/com32.h @@ -153,21 +153,27 @@ static inline void *MK_PTR(uint16_t __seg, uint16_t __offs) /* Some tools to handle 16:16 far pointers in memory */ struct __far_ptr { - uint32_t __ptr; + union { + uint32_t ptr; + struct { + uint16_t offs, seg; + }; + }; } __attribute__ ((packed)); typedef struct __far_ptr far_ptr_t; static inline void *GET_PTR(far_ptr_t __fptr) { - return MK_PTR(__fptr.__ptr >> 16, __fptr.__ptr); + return MK_PTR(__fptr.seg, __fptr.offs); } static inline far_ptr_t FAR_PTR(void *__ptr) { far_ptr_t __fptr; - __fptr.__ptr = (SEG(__ptr) << 16) + OFFS(__ptr); + __fptr.offs = OFFS(__ptr); + __fptr.seg = SEG(__ptr); return __fptr; } diff --git a/core/Makefile b/core/Makefile index 1cb11706..b690ef32 100644 --- a/core/Makefile +++ b/core/Makefile @@ -32,10 +32,10 @@ INCLUDES = -I./include -I$(com32)/include CODEPAGE = cp865 # The targets to build in this directory... -BTARGET = kwdhash.gen \ - extlinux.bin extlinux.bss extlinux.sys \ +BTARGET = kwdhash.gen pxelinux.0 + #extlinux.bin extlinux.bss extlinux.sys \ ldlinux.bss ldlinux.sys ldlinux.bin \ - isolinux.bin isolinux-debug.bin + pxelinux.0 isolinux.bin isolinux-debug.bin # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) diff --git a/core/bios.inc b/core/bios.inc index 987a2166..4c6c5b59 100644 --- a/core/bios.inc +++ b/core/bios.inc @@ -18,6 +18,7 @@ %ifndef _BIOS_INC %define _BIOS_INC + global BIOS_fbm, BIOS_timer absolute 4*1Eh ; In the interrupt table fdctab equ $ diff --git a/core/cache.c b/core/cache.c index b0fbee7e..4be99bb3 100644 --- a/core/cache.c +++ b/core/cache.c @@ -73,11 +73,11 @@ void cache_init(struct device *dev, int block_size_shift) */ struct cache_struct* get_cache_block(struct device *dev, block_t block) { + struct cache_struct *head = (struct cache_struct *)dev->cache_head; + struct cache_struct *last = head->prev; /* let's find it from the end, 'cause the endest is the freshest */ - struct cache_struct *cs = dev->cache_head->prev; - struct cache_struct *head, *last; + struct cache_struct *cs = head->prev; int i; - static int total_read; static int missed; @@ -104,7 +104,7 @@ struct cache_struct* get_cache_block(struct device *dev, block_t block) /* missed, so we need to load it */ if (i == dev->cache_entries) { /* store it at the head of real cache */ - cs = dev->cache_head->next; + cs = head->next; cs->block = block; getoneblk(cs->data, block, dev->cache_block_size); @@ -116,9 +116,6 @@ struct cache_struct* get_cache_block(struct device *dev, block_t block) cs->next->prev = cs->prev; /* add to just before head node */ - last = dev->cache_head->prev; - head = dev->cache_head; - last->next = cs; cs->prev = last; head->prev = cs; diff --git a/core/dhcp_option.c b/core/dhcp_option.c new file mode 100644 index 00000000..f9ff4f22 --- /dev/null +++ b/core/dhcp_option.c @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include + +void subnet_mask(void *data, int opt_len) +{ + if (opt_len != 4) + return; + Netmask = *(uint32_t *)data; +} + +void router(void *data, int opt_len) +{ + if (opt_len != 4) + return; + Gateway = *(uint32_t *)data; +} + +void dns_servers(void *data, int opt_len) +{ + int num = opt_len >> 2; + int i; + + if (num > DNS_MAX_SERVERS) + num = DNS_MAX_SERVERS; + + for (i = 0; i < num; i++) { + DNSServers[i] = *(uint32_t *)data; + data += 4; + } + + /* NOT SURE FOR NOW */ + LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0); +} + +void local_domain(void *data, int opt_len) +{ + com32sys_t regs; + char *p = (char *)data + opt_len; + char end = *p; + + memset(®s, 0, sizeof regs); + *p = '\0'; /* Zero-terminate option */ + regs.esi.w[0] = OFFS_WRT(data, 0); + regs.edi.w[0] = OFFS_WRT(LocalDomain, 0); + call16(dns_mangle, ®s, NULL); + *p = end; /* Resotre ending byte */ +} + +void vendor_encaps(void *data, int opt_len) +{ + /* Only recongnize PXELINUX options */ + parse_dhcp_options(data, opt_len, 208); +} + +void option_overload(void *data, int opt_len) +{ + if (opt_len != 1) + return; + OverLoad = *(uint8_t *)data; +} + + +void server(void *data, int opt_len) +{ + uint32_t ip; + + if (opt_len != 4) + return; + + if (ServerIP) + return; + + ip = *(uint32_t *)data; + if (ip_ok(ip)) + ServerIP = ip; +} + +void client_identifier(void *data, int opt_len) +{ + if (opt_len > MAC_MAX || opt_len < 2 || + MACLen != (opt_len >> 8) || + *(uint8_t *)data != MACType) + return; + + opt_len --; + MACLen = opt_len & 0xff; + memcpy(MAC, data+1, opt_len); + MAC[opt_len] = 0; +} + +void bootfile_name(void *data, int opt_len) +{ + strncpy(BootFile, data, opt_len); + BootFile[opt_len] = 0; +} + +void uuid_client_identifier(void *data, int opt_len) +{ + int type = *(uint8_t *)data; + if (opt_len != 17 || + (type | HaveUUID)) + return; + + HaveUUID = 1; + UUIDType = type; + memcpy(UUID, data+1, 16); + UUID[16] = 0; +} + +void pxelinux_configfile(void *data, int opt_len) +{ + DHCPMagic |= 2; + strncpy(ConfigName, data, opt_len); + ConfigName[opt_len] = 0; +} + +void pxelinux_pathprefix(void *data,int opt_len) +{ + DHCPMagic |= 4; + strncpy(PathPrefix, data, opt_len); + PathPrefix[opt_len] = 0; +} + +void pxelinux_reboottime(void *data, int opt_len) +{ + if ((opt_len && 0xff) != 4) + return ; + + RebootTime = ntohl(*(uint32_t *)data); + DHCPMagic |= 8; /* Got reboot time */ +} + + +struct dhcp_options { + int opt_num; + void (*fun) (void *, int); +}; + +struct dhcp_options dhcp_opts[] = { + {1, subnet_mask}, + {3, router}, + {6, dns_servers}, + {15, local_domain}, + {43, vendor_encaps}, + {52, option_overload}, + {54, server}, + {61, client_identifier}, + {67, bootfile_name}, + {97, uuid_client_identifier}, + {209, pxelinux_configfile}, + {210, pxelinux_pathprefix}, + {211, pxelinux_reboottime} +}; + +/* + * Parse a sequence of DHCP options, pointed to by _option_; + * -- some DHCP servers leave option fields unterminated + * in violation of the spec. + * + * filter contains the minimum value for the option to recognize + * -- this is used to restrict parsing to PXELINUX-specific options only. + */ +void parse_dhcp_options(void *option, int size, int filter) +{ + uint8_t opt_num; + uint8_t opt_len; + uint8_t opt_filter = filter == 208 ? 208 : 0; + int opt_entries = sizeof(dhcp_opts) / sizeof(dhcp_opts[0]); + int i = 0; + char *p = option; + struct dhcp_options *opt; + + if (opt_filter) + printf("***NOTE!:*** we hit a pxelinux-specific options\n"); + + while (size --) { + opt_num = *p++; + + if (!size) + break; + if (opt_num == 0) + continue; + if (opt_num == 0xff) + break; + + /* Anything else will have a lenght filed */ + opt_len = *p++; /* c <- option lenght */ + size = size - opt_len - 1; + if (size < 0) + break; + if (opt_num < opt_filter) { /* Is the option value valid */ + option += opt_len; /* Try next */ + continue; + } + + opt = dhcp_opts; + for (i = 0; i < opt_entries; i++) { + if (opt_num == opt->opt_num) { + opt->fun(p, opt_len); + break; + } + opt ++; + } + + /* parse next */ + p += opt_len; + } +} + +/* + * + ; + ; parse_dhcp + ; + ; Parse a DHCP packet. This includes dealing with "overloaded" + ; option fields (see RFC 2132, section 9.3) + ; + ; This should fill in the following global variables, if the + ; information is present: + ; + ; MyIP - client IP address + ; ServerIP - boot server IP address + ; Netmask - network mask + ; Gateway - default gateway router IP + ; BootFile - boot file name + ; DNSServers - DNS server IPs + ; LocalDomain - Local domain name + ; MACLen, MAC - Client identifier, if MACLen == 0 + ; + ; This assumes the DHCP packet is in "trackbuf". + ; +*/ +void parse_dhcp(int pkt_len) +{ + struct bootp_t *dhcp = (struct bootp_t *)trackbuf; + int opt_len; + + OverLoad = 0; + if (ip_ok(dhcp->yip)) + MyIP = dhcp->yip; + + if (ip_ok(dhcp->sip)) + ServerIP = dhcp->sip; + + opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options; + if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) + parse_dhcp_options(&dhcp->options, opt_len, 0); + + if (OverLoad & 1) + parse_dhcp_options(&dhcp->bootfile, 128, 0); + else if (dhcp->bootfile[0]) + strcpy(BootFile, dhcp->bootfile); + + if (OverLoad & 2) + parse_dhcp_options(dhcp->sname, 64, 0); +} diff --git a/core/disk.c b/core/disk.c deleted file mode 100644 index 69a9c0bf..00000000 --- a/core/disk.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include "core.h" -#include "disk.h" - -void read_sectors(char *buf, sector_t sector_num, int sectors) -{ - com32sys_t regs; - //static __lowmem char low_buf[65536]; - /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ - int high_addr = (buf + (sectors << SECTOR_SHIFT)) > (char *)0x100000; - - memset(®s, 0, sizeof regs); - regs.eax.l = sector_num; - regs.ebp.l = sectors; - - if (high_addr) { - regs.es = SEG(core_xfer_buf); - regs.ebx.w[0] = OFFS(core_xfer_buf); - } else { - regs.es = SEG(buf); - regs.ebx.w[0] = OFFS(core_xfer_buf); - } - - call16(getlinsec, ®s, NULL); - - if (high_addr) - memcpy(buf, core_xfer_buf, sectors << SECTOR_SHIFT); -} - - -void getoneblk(char *buf, block_t block, int block_size) -{ - int sec_per_block = block_size >> SECTOR_SHIFT; - - read_sectors(buf, block * sec_per_block, sec_per_block); -} - - diff --git a/core/diskio.c b/core/diskio.c index bf222203..274157bc 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -303,3 +303,43 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, #endif return &disk; } + + +/* + * initialize the device structure + */ +struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start, + uint16_t bsHeads, uint16_t bsSecPerTrack) +{ + static struct device dev; + + dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack); + + /* for now, isolinux doesn't use cache */ + if (!cdrom) { + /* + * FIX!! I can't use __lowmem here, 'cause it will cause the error: + * "auxseg/lowmem region collides with xfer_buf_seg". + * + * static __lowmem char cache_buf[65536]; + */ + dev.cache_data = core_cache_buf; + dev.cache_size = sizeof core_cache_buf; + } else + dev.cache_data = NULL; + + return &dev; +} + + +/* debug function */ +void dump_dev(struct device *dev) +{ + printf("device type:%s\n", dev->disk->type ? "EDD" : "CHS"); + printf("drive number: 0x%x\n", dev->disk->disk_number); + printf("cache_data: %p\n", dev->cache_data); + printf("cache_head: %p\n", dev->cache_head); + printf("cache_block_size: %d\n", dev->cache_block_size); + printf("cache_entries: %d\n", dev->cache_entries); + printf("cache_size: %d\n", dev->cache_size); +} diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc index 7b632378..9733282b 100644 --- a/core/dnsresolv.inc +++ b/core/dnsresolv.inc @@ -33,6 +33,7 @@ DNS_MAX_SERVERS equ 4 ; Max no of DNS servers ; ; On return, DX contains the number of dots encountered. ; + global dns_mangle dns_mangle: push ax push bx @@ -151,6 +152,7 @@ dns_skiplabel: endstruc section .bss16 + global LocalDomain, DNSServers alignb 2 DNSSendBuf resb DNS_MAX_PACKET DNSRecvBuf resb DNS_MAX_PACKET @@ -176,6 +178,7 @@ pxe_udp_read_pkt_dns: .buffersize: dw DNS_MAX_PACKET ; Max packet size .buffer: dw DNSRecvBuf, 0 ; off, seg of buffer + global LastDNSServer LastDNSServer dw DNSServers ; Actual resolver function @@ -186,6 +189,7 @@ LastDNSServer dw DNSServers ; No segment assumptions permitted. ; section .text16 + global dns_resolv dns_resolv: push ds push es diff --git a/core/extern.inc b/core/extern.inc index 2e6dcd07..a820c9ac 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -18,4 +18,7 @@ ; fat.c extern alloc_fill_dir, readdir + ; pxe.c + extern gendotquad + %endif ; EXTERN_INC diff --git a/core/fs.c b/core/fs.c index 165d07e8..7dc3b2a3 100644 --- a/core/fs.c +++ b/core/fs.c @@ -2,7 +2,7 @@ #include #include #include "fs.h" -#include "cache.h" +//#include "cache.h" /* The this fs pointer */ @@ -75,45 +75,6 @@ void searchdir(com32sys_t *regs) } -/* - * initialize the device structure - */ -struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start, - uint16_t bsHeads, uint16_t bsSecPerTrack) -{ - static struct device dev; - - dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack); - - /* for now, isolinux doesn't use cache */ - if (!cdrom) { - /* - * FIX!! I can't use __lowmem here, 'cause it will cause the error: - * "auxseg/lowmem region collides with xfer_buf_seg". - * - * static __lowmem char cache_buf[65536]; - */ - dev.cache_data = core_cache_buf; - dev.cache_size = sizeof core_cache_buf; - } else - dev.cache_data = NULL; - - return &dev; -} - - -/* debug function */ -void dump_dev(struct device *dev) -{ - printf("device type:%s\n", dev->disk->type ? "EDD" : "CHS"); - printf("drive number: 0x%x\n", dev->disk->disk_number); - printf("cache_data: %p\n", dev->cache_data); - printf("cache_head: %p\n", dev->cache_head); - printf("cache_block_size: %d\n", dev->cache_block_size); - printf("cache_entries: %d\n", dev->cache_entries); - printf("cache_size: %d\n", dev->cache_size); -} - /* * it will do: * set up the vfs fs structure; @@ -130,7 +91,10 @@ void fs_init(com32sys_t *regs) /* set up the fs stucture */ fs.fs_name = ops->fs_name; fs.fs_ops = ops; - fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, + if (1)//! strcmp(fs.fs_name, "pxe")) + fs.fs_dev = NULL; + else + fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, \ regs->esi.w[0], regs->edi.w[0]); this_fs = &fs; @@ -138,6 +102,6 @@ void fs_init(com32sys_t *regs) blk_shift = fs.fs_ops->fs_init(&fs); /* initialize the cache */ - if (fs.fs_dev->cache_data) - cache_init(fs.fs_dev, blk_shift); + //if (fs.fs_dev && fs.fs_dev->cache_data) + // cache_init(fs.fs_dev, blk_shift); } diff --git a/core/include/disk.h b/core/include/disk.h index 386f4f7b..0d8702db 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -35,5 +35,6 @@ extern void getoneblk(char *, block_t, int); /* diskio.c */ struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t); +struct device *device_init(uint8_t, bool, sector_t, uint16_t, uint16_t); #endif /* DISK_H */ diff --git a/core/include/fs.h b/core/include/fs.h index b5128d82..163808e8 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -44,7 +44,7 @@ struct device { /* the cache stuff */ char* cache_data; - struct cache_struct* cache_head; + void* cache_head; uint16_t cache_block_size; uint16_t cache_entries; uint32_t cache_size; diff --git a/core/include/pxe.h b/core/include/pxe.h new file mode 100644 index 00000000..b9c71dfb --- /dev/null +++ b/core/include/pxe.h @@ -0,0 +1,370 @@ + +/** +* ----------------------------------------------------------------------- +* +* Copyright 1999-2008 H. Peter Anvin - All Rights Reserved +* +* 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, Inc., 53 Temple Place Ste 330, +* Boston MA 02111-1307, USA; either version 2 of the License, or +* (at your option) any later version; incorporated herein by reference. +* +* ----------------------------------------------------------------------- + +* +* pxe.inc +* +* PXE opcodes +* +*/ +#ifndef PXE_H +#define PXE_H + + +#define PXENV_TFTP_OPEN 0x0020 +#define PXENV_TFTP_CLOSE 0x0021 +#define PXENV_TFTP_READ 0x0022 +#define PXENV_TFTP_READ_FILE 0x0023 +#define PXENV_TFTP_READ_FILE_PMODE 0x0024 +#define PXENV_TFTP_GET_FSIZE 0x0025 + +#define PXENV_UDP_OPEN 0x0030 +#define PXENV_UDP_CLOSE 0x0031 +#define PXENV_UDP_READ 0x0032 +#define PXENV_UDP_WRITE 0x0033 + +#define PXENV_START_UNDI 0x0000 +#define PXENV_UNDI_STARTUP 0x0001 +#define PXENV_UNDI_CLEANUP 0x0002 +#define PXENV_UNDI_INITIALIZE 0x0003 +#define PXENV_UNDI_RESET_NIC 0x0004 +#define PXENV_UNDI_SHUTDOWN 0x0005 +#define PXENV_UNDI_OPEN 0x0006 +#define PXENV_UNDI_CLOSE 0x0007 +#define PXENV_UNDI_TRANSMIT 0x0008 +#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 +#define PXENV_UNDI_SET_STATION_ADDR 0x000A +#define PXENV_UNDI_SET_PACKET_FILTER 0x000B +#define PXENV_UNDI_GET_INFORMATION 0x000C +#define PXENV_UNDI_GET_STATISTICS 0x000D +#define PXENV_UNDI_CLEAR_STATISTICS 0x000E +#define PXENV_UNDI_INITIATE_DIAGS 0x000F +#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 +#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define PXENV_UNDI_GET_IFACE_INFO 0x0013 +#define PXENV_UNDI_ISR 0x0014 +#define PXENV_STOP_UNDI 0x0015 +#define PXENV_UNDI_GET_STATE 0x0015 + +#define PXENV_UNLOAD_STACK 0x0070 +#define PXENV_GET_CACHED_INFO 0x0071 +#define PXENV_RESTART_DHCP 0x0072 +#define PXENV_RESTART_TFTP 0x0073 +#define PXENV_MODE_SWITCH 0x0074 +#define PXENV_START_BASE 0x0075 +#define PXENV_STOP_BASE 0x0076 + +/* gPXE extensions... */ +#define PXENV_FILE_OPEN 0x00e0 +#define PXENV_FILE_CLOSE 0x00e1 +#define PXENV_FILE_SELECT 0x00e2 +#define PXENV_FILE_READ 0x00e3 +#define PXENV_GET_FILE_SIZE 0x00e4 +#define PXENV_FILE_EXEC 0x00e5 +#define PXENV_FILE_API_CHECK 0x00e6 + +/* Exit codes */ +#define PXENV_EXIT_SUCCESS 0x0000 +#define PXENV_EXIT_FAILURE 0x0001 + +/* Status codes */ +#define PXENV_STATUS_SUCCESS 0x00 +#define PXENV_STATUS_FAILURE 0x01 +#define PXENV_STATUS_BAD_FUNC 0x02 +#define PXENV_STATUS_UNSUPPORTED 0x03 +#define PXENV_STATUS_KEEP_UNDI 0x04 +#define PXENV_STATUS_KEEP_ALL 0x05 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 +#define PXENV_STATUS_ARP_TIMEOUT 0x11 +#define PXENV_STATUS_UDP_CLOSED 0x18 +#define PXENV_STATUS_UDP_OPEN 0x19 +#define PXENV_STATUS_TFTP_CLOSED 0x1a +#define PXENV_STATUS_TFTP_OPEN 0x1b +#define PXENV_STATUS_MCOPY_PROBLEM 0x20 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 + +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f +#define PXENV_STATUS_DHCP_TIMEOUT 0x51 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 +#define PXENV_STATUS_LOADER_UNDI_START 0xca +#define PXENV_STATUS_LOADER_BC_START 0xcb + + + + +/* + * some other defines + */ +#define PKTBUF_SIZE (65536 / MAX_OPEN) + +#define TFTP_BLOCKSIZE_LG2 9 +#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) +#define PKTBUF_SEG 0x4000 +#define DNS_MAX_SERVERS 4 + +#define is_digit(c) (((c) >= '0') && ((c) <= '9')) +#define htons(x) ( ( ((x) & 0xff) << 8) + ( ((x) &0xff00) >> 8) ) +#define ntohs(x) htons(x) +#define htonl(x) ( ( ((x) & 0xff) << 24) + ( ((x) & 0xff00) << 8 ) + \ + ( ((x) & 0xff0000) >> 8 ) + ( ((x) & 0xff000000) >> 24) ) +#define ntohl(x) htonl(x) + +/* + * TFTP operation codes + */ +#define TFTP_RRQ htons(1) // Read rest +#define TFTP_WRQ htons(2) // Write rest +#define TFTP_DATA htons(3) // Data packet +#define TFTP_ACK htons(4) // ACK packet +#define TFTP_ERROR htons(5) // ERROR packet +#define TFTP_OACK htons(6) // OACK packet + +/* + * TFTP error codes + */ +#define TFTP_EUNDEF htons(0) // Unspecified error +#define TFTP_ENOTFOUND htons(1) // File not found +#define TFTP_EACCESS htons(2) // Access violation +#define TFTP_ENOSPACE htons(3) // Disk full +#define TFTP_EBADOP htons(4) // Invalid TFTP operation +#define TFTP_EBADID htons(5) // Unknown transfer +#define TFTP_EEXISTS htons(6) // File exists +#define TFTP_ENOUSER htons(7) // No such user +#define TFTP_EOPTNEG htons(8) // Option negotiation failure + +#define BOOTP_OPTION_MAGIC htonl(0x63825363) + + +/* + * structures + */ +struct bootp_t { + uint8_t opcode; /* BOOTP/DHCP "opcode" */ + uint8_t hardware; /* ARP hreadware type */ + uint8_t hardlen; /* Hardware address length */ + uint8_t gatehops; /* Used by forwarders */ + uint32_t ident; /* Transaction ID */ + uint16_t seconds; /* Seconds elapsed */ + uint16_t flags; /* Broadcast flags */ + uint32_t cip; /* Cient IP */ + uint32_t yip; /* "Your" IP */ + uint32_t sip; /* Next Server IP */ + uint32_t gip; /* Relay agent IP */ + uint8_t macaddr[16]; /* Client MAC address */ + uint8_t sname[64]; /* Server name (optional) */ + char bootfile[128]; /* Boot file name */ + uint32_t option_magic; /* Vendor option magic cookie */ + uint8_t options[1260]; /* Vendor options */ +} __attribute__ ((packed)); + +struct open_file_t { + uint16_t tftp_localport; /* Local port number (0=not in us)*/ + uint16_t tftp_remoteport; /* Remote port number */ + uint32_t tftp_remoteip; /* Remote IP address */ + uint32_t tftp_filepos; /* bytes downloaded (includeing buffer) */ + uint32_t tftp_filesize; /* Total file size(*) */ + uint32_t tftp_blksize; /* Block size for this connection(*) */ + uint16_t tftp_bytesleft; /* Unclaimed data bytes */ + uint16_t tftp_lastpkt; /* Sequence number of last packet (NBO) */ + uint16_t tftp_dataptr; /* Pointer to available data */ + uint8_t tftp_goteof; /* 1 if the EOF packet received */ + uint8_t tftp_unused[3]; /* Currently unused */ + uint16_t tftp_pktbuf; /* Packet buffer offset */ +} __attribute__ ((packed)); +extern char Files[]; + +struct pxe_udp_write_pkt { + uint16_t status; + uint32_t sip; + uint32_t gip; + uint16_t lport; + uint16_t rport; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +struct pxe_udp_read_pkt { + uint16_t status; + uint32_t sip; + uint32_t dip; + uint16_t rport; + uint16_t lport; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +struct pxe_bootp_query_pkt { + uint16_t status; + uint16_t packettype; + uint16_t buffersize; + uint16_t buffer[2]; + uint16_t bufferlimit; +} __attribute__ ((packed)); + +struct pxe_udp_open_pkt { + uint16_t status; + uint32_t sip; +} __attribute__ ((packed)); + +struct gpxe_file_api_check { + uint16_t status; + uint16_t size; + uint32_t magic; + uint32_t provider; + uint32_t apimask; + uint32_t flags; +} __attribute__ ((packed)); + +struct gpxe_file_open { + uint16_t status; + uint16_t filehandle; + uint16_t filename[2]; + uint32_t reserved; +} __attribute__ ((packed)); + +struct gpxe_get_file_size { + uint16_t status; + uint16_t filehandle; + uint32_t filesize; +} __attribute__ ((packed)); + +struct gpxe_file_read { + uint16_t status; + uint16_t filehandle; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +/* + * externs + */ +extern uint32_t ServerIP; +extern uint32_t MyIP; +extern uint32_t Netmask; +extern uint32_t Gateway; +extern uint32_t ServerPort; + +#define MAC_MAX 32 +extern char MACStr[]; /* MAC address as a string */ +extern char MAC[]; /* Actual MAC address */ +extern char BOOTIFStr[]; /* Space for "BOOTIF=" */ +extern uint8_t MACLen; /* MAC address len */ +extern uint8_t MACType; /* MAC address type */ + + +extern uint8_t DHCPMagic; +extern uint8_t OverLoad; +extern uint32_t RebootTime; + + +/* TFTP ACK packet */ +extern uint16_t ack_packet_buf[]; + +extern void kaboom(void); +extern void dns_mangle(void); +extern char trackbuf[]; +extern char BootFile[]; +extern char PathPrefix[]; +extern char CurrentDirName[]; +extern char LocalDomain[]; + +extern char packet_buf[]; + +extern char IPOption[]; +extern char DotQuadBuf[]; + + +extern uint32_t DNSServers[]; +extern uint16_t LastDNSServer; + +extern char ConfigName[]; + +extern uint16_t RealBaseMem; +extern uint16_t APIVer; +extern far_ptr_t PXEEntry; + +extern far_ptr_t InitStack; + +extern int HaveUUID; +extern uint8_t UUIDType; +extern char UUID[]; + +extern volatile uint16_t BIOS_timer; + + +/* + * functions + */ +int ip_ok(uint32_t); +void parse_dhcp(int); +void parse_dhcp_options(void *, int, int); + + + + +#endif /* pxe.h */ diff --git a/core/parsecmd.inc b/core/parsecmd.inc index 94627b8c..7e0ac5c0 100644 --- a/core/parsecmd.inc +++ b/core/parsecmd.inc @@ -111,6 +111,7 @@ err_badcfg db 'Unknown keyword in configuration file: ',0 err_noparm db 'Missing parameter in configuration file. Keyword: ',0 section .uibss + global KernelName alignb 4 vk_size equ (vk_end + 3) & ~3 VKernelBuf: resb vk_size ; "Current" vkernel diff --git a/core/pxe.c b/core/pxe.c new file mode 100644 index 00000000..1a61d96e --- /dev/null +++ b/core/pxe.c @@ -0,0 +1,1551 @@ +#include +#include +#include +#include +#include +#include + +#define MAX_OPEN_LG2 5 +#define MAX_OPEN (1 << MAX_OPEN_LG2) +#define FILENAME_MAX_LG2 7 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) + +#define MAX(a,b) (a > b ? a : b) + +#define GPXE 1 +#define USE_PXE_PROVIDED_STACK 0 + +char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; +char *err_pxefailed = "PXE API call failed, error "; +char *err_udpinit = "Failed to initialize UDP stack\n"; +char *err_noconfig = "Unable to locate configuration file\n"; +char *err_damage = "TFTP server sent an incomprehesible reply\n"; + +char *tftpprefix_msg = "TFTP prefix: "; +char *get_packet_msg = "Getting cached packet "; + +uint16_t NextSocket = 49152; + +int has_gpxe; +int HaveUUID = 0; +uint8_t UUIDType; +uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; + +uint16_t StructPtr[2]; + +static const uint8_t TimeoutTable[] = { + 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, + 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 +}; + +char *mode = "octet"; +char *tsize_str = "tsize"; +int tsize_len = 6; /* We should include the final null here */ + +char *blksize_str = "blksize"; +int blksize_len = 8; + +char *asciidec = "1408"; + + + +/* + * Allocate a local UDP port structure. + * return the socket pointer if success, or null if failure + * + */ +struct open_file_t* allocate_socket() +{ + extern uint16_t NextSocket; + uint16_t i = MAX_OPEN; + struct open_file_t *socket = (struct open_file_t *)&Files; + + for (; i > 0; i--) { + if (*(uint16_t*)socket == 0) + break; + socket ++; + } + + /* Not found */ + if (i == 0) + return NULL; + + /* + * Allocate a socket number. Socket numbers are made guaranteed unique + * by including the socket slot number(inverted, because we use the loop + * counter cx; add a counter value to keep the numbers from being likely + * to get immediately reused. + * + * The NextSocket variable also contains the top two bits set. This + * generates a value in the range 49152 to 57343. + * + */ + i--; + NextSocket = ((NextSocket + 1) & ((1 << (13-MAX_OPEN_LG2))-1)) | 0xc000; + i <<= 13-MAX_OPEN_LG2; + i += NextSocket; + i = ntohs(i) ; /* convet to network byte order, little to big */ + *(uint16_t*)socket = i; /* socket in use */ + + return socket; +} + +/* + * free socket, socket in SI; return SI = 0, ZF = 1 for convenience + */ +void free_socket(struct open_file_t *file) +{ + /* tftp_pktbuf is not cleared */ + memset(file, 0, sizeof(struct open_file_t) - 2); +} + +/** + * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal + * + * @param: dst, output buffer + * @param: src, input buffer + * @param: count, number of bytes + * + */ +void lchexbytes(char *dst, const void *src, int count) +{ + uint8_t half; + uint8_t c; + const uint8_t *s = src; + + for(; count > 0; count--) { + c = *s++; + half = ((c >> 4) & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; + + half = (c & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; + } +} + +/** + * just like the lchexbytes, except to upper-case + * + */ +void uchexbytes(char *dst, const void *src, int count) +{ + uint8_t half; + uint8_t c; + const uint8_t *s = src; + + for(; count > 0; count--) { + c = *s++; + half = ((c >> 4) & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; + + half = (c & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; + } +} + + + + +/* + * + * Tests an IP address in EAX for validity; return with 0 for bad, 1 for good. + * We used to refuse class E, but class E addresses are likely to become + * assignable unicast addresses in the near future. + * + */ +int ip_ok(uint32_t ip) +{ + if (ip == -1) /* Refuse the all-one address */ + goto bad; + if ((ip & 0xff) == 0) /* Refuse network zero */ + goto bad; + if ((ip & 0xff) == 0xff) /* Refuse loopback */ + goto bad; + if ((ip & 0xf0) == 0xe0) /* Refuse class D */ + goto bad; + + return 1; + + bad: + return 0; +} + + +/********************************************************************* +; +; gendotquad +; +; Take an IP address (in network byte order) in EAX and +; output a dotted quad string to ES:DI. +; DI points to terminal null at end of string on exit. +; + *********************************************************************/ +/** + * @param: dst, to store the converted ip string + * @param: ip, the ip address that needed convert. + * + * @return: the ip string length + */ +int gendotquad(char *dst, uint32_t ip) +{ + int part; + int i = 0, j; + char temp[4]; + char *p = dst; + + for (; i < 4; i++) { + j = 0; + part = ip & 0xff; + do { + temp[j++] = (part % 10) + '0'; + }while(part /= 10); + for (; j > 0; j--) + *p++ = temp[j-1]; + *p++ = '.'; + + ip >>= 8; + } + /* drop the last dot '.' and zero-terminate string*/ + *(--p) = 0; + + return p - dst; +} + +/* + * parse the ip_str and return the ip address with *res. + * return the the string address after the ip string + * + */ +char *parse_dotquad(char *ip_str, uint32_t *res) +{ + char *p = ip_str; + int i = 0; + uint8_t part = 0; + uint32_t ip = 0; + + for (; i < 4; i++) { + while (is_digit(*p)) { + part = part * 10 + *p - '0'; + p++; + } + if (i != 3 && *p != '.') + return NULL; + + ip = (ip << 8) | part; + part = 0; + p++; + } + p --; + + *res = ip; + return p; +} + +/* + * the ASM pxenv function wrapper, return 1 if error, or 0 + * + */ +int pxe_call(int opcode, void *data) +{ + extern void pxenv(void); + com32sys_t in_regs, out_regs; + +#if 0 + printf("pxe_call op %04x data %p\n", opcode, data); +#endif + + memset(&in_regs, 0, sizeof in_regs); + + in_regs.ebx.w[0] = opcode; + in_regs.es = SEG(data); + in_regs.edi.w[0] = OFFS(data); + call16(pxenv, &in_regs, &out_regs); + + return out_regs.eflags.l & EFLAGS_CF; /* CF SET for fail */ +} + +/** + * + * Send ACK packet. This is a common operation and so is worth canning. + * + * @param: file, TFTP block pointer + * @param: ack_num, Packet # to ack (network byte order) + * + */ +void ack_packet(struct open_file_t *file, uint16_t ack_num) +{ + int err; + static __lowmem struct pxe_udp_write_pkt uw_pkt; + + /* Packet number to ack */ + ack_packet_buf[1] = ack_num; + uw_pkt.lport = file->tftp_localport; + uw_pkt.rport = file->tftp_remoteport; + uw_pkt.sip = file->tftp_remoteip; + uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; + uw_pkt.buffer[0] = OFFS_WRT(ack_packet_buf, 0); + uw_pkt.buffer[1] = 0; /* seems SEG and OFFS stuff doesn't work here */ + uw_pkt.buffersize = 4; + + err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); +#if 0 + printf("sent %s\n", err ? "FAILED" : "OK"); +#endif +} + + +/** + * Get a DHCP packet from the PXE stack into the trackbuf + * + * @param: type, packet type + * @return: buffer size + * + */ +int pxe_get_cached_info(int type) +{ + int err; + static __lowmem struct pxe_bootp_query_pkt bq_pkt; + printf(" %02x", type); + + bq_pkt.status = 0; + bq_pkt.packettype = type; + bq_pkt.buffersize = 8192; + bq_pkt.buffer[0] = OFFS_WRT(trackbuf, 0); + bq_pkt.buffer[1] = 0; + + err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); + if (err) { + printf("%s %04x\n", err_pxefailed, err); + call16(kaboom, NULL, NULL); + } + + return bq_pkt.buffersize; +} + + + +#if GPXE + +/* + * Return 1 if and only if the buffer pointed to by + * url is a URL (contains ://) + * + */ +int is_url(char *url) +{ + + while (*url) { + if(! strncmp(url, "://", 3)) + return 1; + + url++; + } + return 0; +} + + +/* + * Return CF=0 if and only if the buffer pointed to by DS:SI is a URL + * (contains ://) *and* the gPXE extensions API is available. No + * registers modified. + */ +int is_gpxe(char *url) +{ + int err; + static __lowmem struct gpxe_file_api_check ac; + char *gpxe_warning_msg = "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; + + if (! is_url(url)) + return 0; + + ac.size = 20; + ac.magic = 0x91d447b2; + /* If has_gpxe is greater than one, means the gpxe status is unknow */ + while (has_gpxe > 1) { + err = pxe_call(PXENV_FILE_API_CHECK, &ac); + if (err || ac.magic != 0xe9c17b20) + printf("%s\n", gpxe_warning_msg); + else + has_gpxe = (~ac.provider & 0xffff) & 0x4b ? 0 : 1; + + if (!has_gpxe) + printf("%s\n", gpxe_warning_msg); + } + + if (has_gpxe == 1) + return 1; + else + return 0; +} + +/** + * Get a fresh packet from a gPXE socket + * @param: file -> socket structure + * + */ +void get_packet_gpxe(struct open_file_t *file) +{ + static __lowmem struct gpxe_file_read fr; + int err; + + while (1) { + fr.filehandle = file->tftp_remoteport; + fr.buffer[0] = file->tftp_pktbuf; + fr.buffer[1] = PKTBUF_SEG; + fr.buffersize = PKTBUF_SIZE; + err = pxe_call(PXENV_FILE_READ, &fr); + if (!err) /* successed */ + break; + + if (fr.status == PXENV_STATUS_TFTP_OPEN) + continue; + call16(kaboom, NULL, NULL); + } + + file->tftp_bytesleft = fr.buffersize; + file->tftp_filepos += fr.buffersize; + + if (file->tftp_bytesleft == 0) + file->tftp_filesize = file->tftp_filepos; + + /* if we're done here, close the file */ + if (file->tftp_filesize > file->tftp_filepos) + return; + + /* Got EOF, close it */ + file->tftp_goteof = 1; + pxe_call(PXENV_FILE_CLOSE, &fr); +} +#endif /* GPXE */ + + +/* + * mangle a filename pointed to by _src_ into a buffer pointed + * to by _dst_; ends on encountering any whitespace. + * + * The first four bytes of the manged name is the IP address of + * the download host, 0 for no host, or -1 for a gPXE URL. + * + */ +void pxe_mangle_name(char *dst, char *src) +{ + char *p = src; + uint32_t ip; + int i = 0; + +#if GPXE + if (is_url(src)) + goto prefix_done; +#endif + + ip = ServerIP; + if (*p == 0) + goto noip; + if (! strncmp(p, "::", 2)) + goto gotprefix; + else { + while (*p && strncmp(p, "::", 2)) + p ++; + if (! *p) + goto noip; + /* + * we have a :: prefix of ip sort, it could be either a DNS + * name or dot-quad IP address. Try the dot-quad first. + */ + p = src; + if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) + goto gotprefix; + else { +#if 0 + extern void dns_resolv(void); + call16(dns_resolv, regs, regs); + p = (char *)MK_PTR(regs->ds, regs->esi.w[0]); + ip = regs->eax.l; + if (! strncmp(p, "::", 2)) + if (ip) + goto gotprefix; +#endif + } + } + noip: + p = src; + ip = 0; + goto prefix_done; + + gotprefix: + p += 2; /* skip double colon */ + + prefix_done: + *(uint32_t *)dst = ip; + dst += 4; + i = FILENAME_MAX - 5; + + do { + if (*p <= ' ') + break; + *dst++ = *p++; + }while (i--); + + i ++; + while (i) { + *dst++ = 0; + i --; + } + +#if 0 + printf("the name before mangling: "); + dump16(src); + printf("the name after mangling: "); + dump16((char *)MK_PTR(regs->ds, regs->edi.w[0])); +#endif +} + + +/* + * + ; + ; Get a fresh packet if the buffer is drained, and we haven't hit + ; EOF yet. The buffer should be filled immediately after draining! + ; + ; expects fs -> pktbuf_seg and ds:si -> socket structure + ; +*/ +void fill_buffer(struct open_file_t *file) +{ + int err; + int last_pkt; + const uint8_t *timeout_ptr = TimeoutTable; + uint8_t timeout; + uint16_t buffersize; + uint16_t old_time; + void *data = NULL; + static __lowmem struct pxe_udp_read_pkt pkt; + + if (file->tftp_bytesleft || file->tftp_goteof) + return; + +#if GPXE + if (file->tftp_localport == 0xffff) { + get_packet_gpxe(file); + return; + } +#endif + + + /* + * Start by ACKing the previous packet; this should cause + * the next packet to be sent. + */ + ack_again: + ack_packet(file, file->tftp_lastpkt); + + timeout_ptr = TimeoutTable; + timeout = *timeout_ptr++; + old_time = BIOS_timer; + while (timeout) { + pkt.buffer[0] = file->tftp_pktbuf; + pkt.buffer[1] = PKTBUF_SEG; + pkt.buffersize = PKTBUF_SIZE; + pkt.sip = file->tftp_remoteip; + pkt.dip = MyIP; + pkt.rport = file->tftp_remoteport; + pkt.lport = file->tftp_localport; + err = pxe_call(PXENV_UDP_READ, &pkt); + if (err) { + if (BIOS_timer == old_time) { + printf("."); + continue; + } + printf("+"); + + timeout--; /* decrease one timer tick */ + if (!timeout) { + timeout = *timeout_ptr++; + if (!timeout) + break; + } + continue; + } + + if (pkt.buffersize < 4) /* Bad size for a DATA packet */ + continue; + + data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf); + if (*(uint16_t *)data != TFTP_DATA) /* Not a data packet */ + continue; + + /* If goes here, recevie OK, break */ + break; + } + + /* time runs out */ + if (timeout == 0) + call16(kaboom, NULL, NULL); + + last_pkt = file->tftp_lastpkt; + last_pkt = ntohs(last_pkt); /* Host byte order */ + last_pkt++; + last_pkt = htons(last_pkt); /* Network byte order */ + if (*(uint16_t *)(data + 2) != last_pkt) { + /* + * Wrong packet, ACK the packet and try again. + * This is presumably because the ACK got lost, + * so the server just resent the previous packet. + */ +#if 0 + printf("Wrong packet, wanted %04x, got %04x\n", htons(last_pkt), htons(*(uint16_t *)(data+2))); +#endif + goto ack_again; + } + + /* It's the packet we want. We're also EOF if the size < blocksize */ + file->tftp_lastpkt = last_pkt; /* Update last packet number */ + buffersize = pkt.buffersize - 4; /* Skip TFTP header */ + file->tftp_dataptr = file->tftp_pktbuf + 4; + file->tftp_filepos += buffersize; + file->tftp_bytesleft = buffersize; + if (buffersize < file->tftp_blksize) { + /* it's the last block, ACK packet immediately */ + ack_packet(file, *(uint16_t *)(data + 2)); + + /* Make sure we know we are at end of file */ + file->tftp_filesize = file->tftp_filepos; + file->tftp_goteof = 1; + } +} + + +/** + * getfssec: Get multiple clusters from a file, given the starting cluster. + * In this case, get multiple blocks from a specific TCP connection. + * + * @param: fs, the fs_info structure address, in pxe, we don't use this. + * @param: buf, buffer to store the read data + * @param: openfile, TFTP socket pointer + * @param: blocks, 512-byte block count; 0FFFFh = until end of file + * + * @return: the bytes read + * + */ +uint32_t pxe_getfssec(struct fs_info *fs, char *buf, + void *open_file, int blocks, int *have_more) +{ + struct open_file_t *file = (struct open_file_t *)open_file; + int count = blocks; + int chunk; + int bytes_read = 0; + + sti(); + fs = NULL; /* drop the compile warning message */ + + count <<= TFTP_BLOCKSIZE_LG2; + while (count) { + fill_buffer(file); /* If we have no 'fresh' buffer, get it */ + if (! file->tftp_bytesleft) + break; + + chunk = count; + if (chunk > file->tftp_bytesleft) + chunk = file->tftp_bytesleft; + file->tftp_bytesleft -= chunk; + memcpy(buf, MK_PTR(PKTBUF_SEG, file->tftp_dataptr), chunk); + file->tftp_dataptr += chunk; + buf += chunk; + bytes_read += chunk; + count -= chunk; + } + + + if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) { + fill_buffer(file); + *have_more = 1; + } else if (file->tftp_goteof) { + /* + * The socket is closed and the buffer dranined + * close socket structure and re-init for next user + */ + free_socket(file); + *have_more = 0; + } + + return bytes_read; + } + + + +/* + * Fill the packet tail with the tftp informations then retures the lenght + */ +int fill_tail(char *dst) +{ + char *p = dst; + strcpy(p, mode); + p += strlen(mode) + 1; + + strcpy(p, tsize_str); + p += strlen(tsize_str) + 1; + + strcpy(p, "0"); + p += 2; + + strcpy(p, blksize_str); + p += strlen(blksize_str) + 1; + + strcpy(p, asciidec); + p += strlen(asciidec) + 1; + + return p - dst; +} + + +struct tftp_options { + char *str_ptr; /* string pointer */ + int str_len; /* string lenght */ + int offset; /* offset into socket structre */ +}; +struct tftp_options tftp_options[2]; + +inline void init_options() +{ + tftp_options[0].str_ptr = tsize_str; + tftp_options[0].str_len = tsize_len; + tftp_options[0].offset = (int)&((struct open_file_t *)0)->tftp_filesize; + + tftp_options[1].str_ptr = blksize_str; + tftp_options[1].str_len = blksize_len; + tftp_options[1].offset = (int)&((struct open_file_t *)0)->tftp_blksize; +} + +/* + * + * + * searchdir: + * + * Open a TFTP connection to the server + * + * On entry: + * DS:DI = mangled filename + * If successful: + * ZF clear + * SI = socket pointer + * EAX = file length in bytes, or -1 if unknown + * If unsuccessful + * ZF set + * + */ +void pxe_searchdir(char *filename, struct file *file) +{ + char *buf = packet_buf; + char *p = filename; + char *options; + char *src, *dst; + char *data; + struct open_file_t *open_file; + static __lowmem struct pxe_udp_write_pkt uw_pkt; + static __lowmem struct pxe_udp_read_pkt ur_pkt; + static __lowmem struct gpxe_file_open fo; + static __lowmem struct gpxe_get_file_size gs; + struct tftp_options *tftp_opt = tftp_options; + int i = 0; + int tftp_opts = sizeof tftp_options / sizeof tftp_options[0]; + int err; + int buffersize; + const uint8_t *timeout_ptr; + uint8_t timeout; + uint16_t oldtime; + uint16_t tid; + uint16_t opcode; + uint16_t blk_num; + uint32_t ip; + uint32_t filesize = 0; + uint32_t *data_ptr; + + init_options(); + open_file = allocate_socket(); + if (!open_file) + goto done; + + timeout_ptr = TimeoutTable; /* Reset timeout */ + + sendreq: + uw_pkt.buffer[0] = OFFS_WRT(buf, 0); + uw_pkt.buffer[1] = 0; + *(uint16_t *)buf = TFTP_RRQ; /* TFTP opcode */ + buf += 2; + + ip = *(uint32_t *)p; /* ip <- server override (if any) */ + p += 4; + if (ip == 0) { + /* Have prefix */ + strcpy(buf, PathPrefix); + buf += strlen(PathPrefix); + ip = ServerIP; /* Get the default server */ + } + + strcpy(buf, p); /* Copy the filename */ + buf += strlen(p) + 1; /* advance the pointer, null char included */ + +#if GPXE + if (is_gpxe(packet_buf + 2)) { + fo.status = PXENV_STATUS_BAD_FUNC; + fo.filename[0] = OFFS_WRT(packet_buf + 2, 0); + fo.filename[1] = 0; + err = pxe_call(PXENV_FILE_OPEN, &fo); + if (err) + goto done; + + open_file->tftp_localport = -1; + open_file->tftp_remoteport = fo.filehandle; + gs.filehandle = fo.filehandle; + +#if 0 + err = pxe_call(PXENV_GET_FILE_SIZE, &gs); + if (!err) + filesize = gs.filesize; + else +#endif + filesize = -1; + open_file->tftp_filesize = -1; + goto done; + } +#endif /* GPXE */ + + open_file->tftp_remoteip = ip; + tid = open_file->tftp_localport; /* TID(local port No) */ + uw_pkt.sip = ip; + uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; + uw_pkt.lport = tid; + uw_pkt.rport = ServerPort; + buf += fill_tail(buf); + uw_pkt.buffersize = buf - packet_buf; + err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); + if (err || uw_pkt.status != 0) + goto failure; /* In fact, the 'failure' target will not do a failure thing; + it will move on to the next timeout, then tries again until + _real_ time out */ + + /* + * Danger, Will Robinson! We need to support tiemout + * and retry lest we just lost a packet ... + */ + + /* Packet transmitted OK, now we need to receive */ + timeout = *timeout_ptr++; + oldtime = BIOS_timer; + while (timeout) { + buf = packet_buf; + ur_pkt.buffer[0] = OFFS_WRT(buf, 0); + ur_pkt.buffer[1] = 0; + ur_pkt.buffersize = 2048; + ur_pkt.dip = MyIP; + ur_pkt.lport = tid; + err = pxe_call(PXENV_UDP_READ, &ur_pkt); + if (err) { + if (oldtime == BIOS_timer) + continue; + timeout --; /* Decrease one timer tick */ + if (!timeout) + goto failure; + } + + /* Make sure the packet actually came from the server */ + if (ur_pkt.sip == open_file->tftp_remoteip) + break; + } + + /* Got packet; reset timeout */ + timeout_ptr = TimeoutTable; + open_file->tftp_remoteport = ur_pkt.rport; + + /* filesize <- -1 == unknow */ + open_file->tftp_filesize = -1; + /* Default blksize unless blksize option negotiated */ + open_file->tftp_blksize = TFTP_BLOCKSIZE; + buffersize = ur_pkt.buffersize - 2; /* bytes after opcode */ + if (buffersize < 0) + goto failure; /* Garbled reply */ + + /* + * Get the opcode type, and parse it + */ + opcode = *(uint16_t *)packet_buf; + if (opcode == TFTP_ERROR) { + filesize = 0; + open_file = NULL; + goto done; /* ERROR reply; don't try again */ + } else if (opcode == TFTP_DATA) { + /* + * If the server doesn't support any options, we'll get a + * DATA reply instead of OACK. Stash the data in the file + * buffer and go with the default value for all options... + * + * We got a DATA packet, meaning no options are + * suported. Save the data away and consider the + * length undefined, *unless* this is the only + * data packet... + */ + buffersize -= 2; + if (buffersize < 0) + goto failure; + data = packet_buf + 2; + blk_num = *(uint16_t *)data; + data += 2; + if (blk_num != htons(1)) + goto failure; + open_file->tftp_lastpkt = blk_num; + if (buffersize > TFTP_BLOCKSIZE) + goto err_reply; /* Corrupt */ + else if (buffersize < TFTP_BLOCKSIZE) { + /* + * This is the final EOF packet, already... + * We know the filesize, but we also want to + * ack the packet and set the EOF flag. + */ + open_file->tftp_filesize = buffersize; + open_file->tftp_goteof = 1; + ack_packet(open_file, blk_num); + } + + open_file->tftp_bytesleft = buffersize; + open_file->tftp_dataptr = open_file->tftp_pktbuf; + memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize); + goto done; + + } else if (opcode == TFTP_OACK) { + /* + * Now we need to parse the OACK packet to get the transfer + * and packet sizes. + */ + if (!buffersize) + goto done; /* No options acked */ + + /* + * If we find an option which starts with a NUL byte, + * (a null option), we're either seeing garbage that some + * TFTP servers add to the end of the packet, or we have + * no clue how to parse the rest of the packet (what is + * an option name and what is a value?) In either case, + * discard the rest. + */ + options = packet_buf + 2; + if (*options == 0) + goto done; + + dst = src = options; + while (buffersize--) { + if (*src == 0) + break; /* found a final null */ + *dst++ = *src++ | 0x20; + if (!buffersize) + goto done; /* found no final null */ + } + + /* + * Parse option pointed to by options; guaranteed to be null-terminated + */ + p = options; + do { + tftp_opt = tftp_options; + for (i = 0; i < tftp_opts; i++) { + if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) + break; + tftp_opt++; + } + if (i == tftp_opts) + goto err_reply; /* Non-negotitated option returned, no idea what it means ...*/ + + p += tftp_opt->str_len; + + /* get the address of the filed that we want to write on */ + data_ptr = (uint32_t *)((char *)file + tftp_opt->offset); + *data_ptr = 0; + + /* do convert a number-string to decimal number, just like atoi */ + while (buffersize--) { + if (*p == 0) + break; /* found a final null */ + if (*p > '9') + goto err_reply; /* Not a decimal digit */ + *data_ptr = *data_ptr * 10 + *p++ - '0'; + } + + }while (buffersize); + + } else { + extern char tftp_proto_err[]; + err_reply: + + uw_pkt.rport = open_file->tftp_remoteport; + uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); + uw_pkt.buffer[1] = 0; + uw_pkt.buffersize = 24; + pxe_call(PXENV_UDP_WRITE, &uw_pkt); + printf("TFTP server sent an incomprehesible reply\n"); + call16(kaboom, NULL, NULL); + } + + filesize = open_file->tftp_filesize; + + done: + if (!filesize) + free_socket(open_file); + file->file_len = filesize; + file->open_file = (void *)open_file; + return; + + failure: + timeout_ptr++; + if (*timeout_ptr) + goto sendreq; /* Try again */ +} + + +/* + * Store standard filename prefix + */ +void get_prefix(void) +{ + int len; + char *p; + char c; + + if (DHCPMagic & 0x04) /* Did we get a path prefix option */ + goto got_prefix; + + strcpy(PathPrefix, BootFile); + len = strlen(PathPrefix); + p = &PathPrefix[len - 1]; + + while (len--) { + c = *p--; + c |= 0x20; + + c = (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c == '.' || c == '-'); + if (!c) + break; + }; + + if (len < 0) + p --; + + *(p + 2) = 0; /* Zero-terminate after delimiter */ + + got_prefix: + printf("%s%s\n", tftpprefix_msg, PathPrefix); + strcpy(CurrentDirName, PathPrefix); +} + + /** + * try to load a config file, if found, return 1, or return 0 + * + */ +int try_load(com32sys_t *regs) +{ + extern char KernelName[]; + char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + + get_prefix(); + + printf("Trying to load: %-50s ", config_name); + pxe_mangle_name(KernelName, config_name); + + regs->edi.w[0] = OFFS_WRT(KernelName, 0); + call16(core_open, regs, regs); + if (regs->eflags.l & EFLAGS_ZF) { + printf(" [FAILED]\n"); + return 0; + } else { + printf(" [ OK ]\n"); + return 1; + } +} + + + /* + * load configuration file + * + */ +void pxe_load_config(com32sys_t *regs) +{ + extern void no_config(void); + char *cfgprefix = "pxelinux.cfg/"; + char *default_str = "default"; + char *config_file; /* Pointer to the variable suffix */ + char *p; + + uint8_t *uuid_ptr; + + int tries = 8; + char *last; + + if (DHCPMagic & 0x02) { + /* We got a DHCP option, try it first */ + if (try_load(regs)) + return; + } + + memcpy(ConfigName, cfgprefix, strlen(cfgprefix)); + config_file = ConfigName + strlen(cfgprefix); + /* + * Have to guess config file name ... + */ + + /* Try loading by UUID */ + if (HaveUUID) { + uuid_ptr = uuid_dashes; + p = config_file; + while (*uuid_ptr) { + int len = *uuid_ptr; + char *src = UUID; + + lchexbytes(p, src, len); + p += len * 2; + src += len; + uuid_ptr++; + *p++ = '-'; + } + /* Remove last dash and zero-terminate */ + *--p = '\0'; + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + } + + /* Try loading by MAC address */ + strcpy(config_file, MACStr); + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + +#if 0 + printf("MY IP: %p(%X)\n", MyIP, *(uint32_t *)MyIP); + #endif + + /* Nope, try hexadecimal IP prefixes... */ + uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */ + last = &config_file[8]; + while (tries) { + *last = '\0'; /* Zero-terminate string */ + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + last--; /* Drop one character */ + tries--; + }; + + /* Final attempt: "default" string */ + strcpy(config_file, default_str); + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + + /* call16(no_config, NULL, NULL); */ +} + + + +/* + * Generate the botif string, and the hardware-based config string + */ +void make_bootif_string(void) +{ + char *bootif_str = "BOOTIF="; + uint8_t *src = &MACType; /* MACType just followed by MAC */ + char *dst; + int i = MACLen + 1; /* MACType included */ + + strcpy(BOOTIFStr, bootif_str); + dst = strchr(BOOTIFStr, '\0'); + for (; i > 0; i--) { + lchexbytes(dst, src, 1); + dst += 2; + src += 1; + *dst++ = '-'; + } + *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */ + +#if 0 + printf("%s\n", BOOTIFStr); +#endif +} +/* + ; + ; genipopt + ; + ; Generate an ip=::: + ; option into IPOption based on a DHCP packet in trackbuf. + ; Assumes CS == DS == ES. + ; +*/ +void genipopt(void) +{ + char *p = IPOption; + int ip_len; + + strcpy(p, "ip="); + p += 3; + + ip_len = gendotquad(p, MyIP); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, ServerIP); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, Gateway); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, Netmask); +} + + +/* Generate ip= option and print the ip adress */ +void ip_init(void) +{ + int ip = MyIP; + char *myipaddr_msg = "My IP address seems to be "; + + genipopt(); + + gendotquad(DotQuadBuf, ip); + + ip = ntohl(ip); + printf("%s %08X %s\n", myipaddr_msg, ip, DotQuadBuf); + + printf("%s\n", IPOption); +} + +/* + * Validity check on possible !PXE structure in buf + * return 1 for success, 0 for failure. + * + */ +int is_pxe(char *buf) +{ + int i = buf[4]; + uint8_t sum = 0; + + if (memcmp(buf, "!PXE", 4) || i < 0x58) + return 0; + + while (i--) + sum += *buf++; + + if (sum == 0) + return 1; + else + return 0; +} + +/** + * Just like is_pxe, it checks PXENV+ structure + * + */ +int is_pxenv(char *buf) +{ + int i = buf[8]; + uint8_t sum = 0; + + if (memcmp(buf, "PXENV+", 6) || i < 0x28) + return 0; + + while (i--) + sum += *buf++; + + if (sum == 0) + return 1; + else + return 0; +} + + + +/********************************************************************* +; +; memory_scan_for_pxe_struct: +; memory_scan_for_pxenv_struct: +; +; If none of the standard methods find the !PXE/PXENV+ structure, +; look for it by scanning memory. +; +; On exit, if found: +; ZF = 1, ES:BX -> !PXE structure +; Otherwise: +; ZF = 0 +; +; Assumes DS == CS +; Clobbers AX, BX, CX, DX, SI, ES +; + ********************************************************************/ + +inline int memory_scan(uint16_t seg, int (*func)(char *)) +{ + while (seg < 0xA000) { + if (func(MK_PTR(seg, 0))) + return 1; /* found it */ + seg++; + } + return 0; +} + +int memory_scan_for_pxe_struct() +{ + extern uint16_t BIOS_fbm; /* Starting segment */ + uint16_t seg = BIOS_fbm << (10 - 4); + + return memory_scan(seg, is_pxe); +} + +int memory_scan_for_pxenv_struct() +{ + uint16_t seg = 0x1000; + + return memory_scan(seg, is_pxenv); +} + +/* + * Find the !PXE structure; we search for the following, in order: + * + * a. !PXE structure as SS:[SP + 4] + * b. PXENV+ structure at [ES:BX] + * c. INT 1Ah AX=0x5650 -> PXENV+ + * d. Search memory for !PXE + * e. Search memory for PXENV+ + * + * If we find a PXENV+ structure, we try to find a !PXE structure from + * if if the API version is 2.1 or later + * + */ +void pxe_init() +{ + char plan = 'A'; + uint16_t seg, off; + uint16_t code_seg, code_len; + uint16_t data_seg, data_len; + char *base = GET_PTR(InitStack); + + /* Assume API version 2.1 */ + APIVer = 0x201; + + /* Plan A: !PXE structure as SS:[SP + 4] */ + off = *(uint16_t *)(base + 48); + seg = *(uint16_t *)(base + 50); + if (is_pxe(MK_PTR(seg, off))) + goto have_pxe; + + /* Plan B: PXENV+ structure at [ES:BX] */ + plan++; + off = *(uint16_t *)(base + 24); /* Original BX */ + seg = *(uint16_t *)(base + 4); /* Original ES */ + if (is_pxenv(MK_PTR(seg, off))) + goto have_pxenv; + + /* + * Plan C: PXENV+ structure via INT 1Ah AX=5650h + * + * for now, we just skip it since it must be run in Real mode + */ + extern void plan_c(void); + plan++; +#if 0 + goto plan_D; + call16(plan_c, regs, regs); + if (((regs->eflags.l & EFLAGS_CF) == 0) && (regs->eax.w[0] == 0x564e)) { + seg = regs->es; + off = regs->ebx.w[0]; + if (is_pxenv(MK_PTR(seg, off))) + goto have_pxenv; + } + + plan_D: +#endif + /* Plan D: !PXE memory scan */ + plan++; + if (memory_scan_for_pxe_struct()) + goto have_pxe; + + /* Plan E: PXENV+ memory scan */ + plan++; + if (memory_scan_for_pxenv_struct()) + goto have_pxenv; + + /* Found nothing at all !! */ + printf("%s\n", err_nopxe); + call16(kaboom, NULL, NULL); + + have_pxenv: + StructPtr[0] = off; + StructPtr[1] = seg; + base = MK_PTR(seg, off); + APIVer = *(uint16_t *)(base + 6); + printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer); + + /* if the API version number is 0x0201 or higher, use the !PXE structure */ + if (APIVer >= 0x201) { + if (*(char *)(base + 8) < 0x2c) { /* Length of PXENV+ structure in bytes */ + if (memory_scan_for_pxe_struct()) + goto have_pxe; + } + + off = *(uint16_t *)(base + 0x28); + seg = *(uint16_t *)(base + 0x2a); + if (is_pxe(MK_PTR(seg, off))) + goto have_pxe; + /* + * Nope, !PXE structuremissing despite API 2.1+, or at least + * the pointer is missing. Do a last-ditch attempt to find it + */ + if (memory_scan_for_pxe_struct()) + goto have_pxe; + } + + /* Otherwise, no dice, use PXENV+ structure */ + data_len = *(uint16_t *)(base + 0x22); /* UNDI data len */ + data_seg = *(uint16_t *)(base + 0x20); /* UNDI data seg */ + code_len = *(uint16_t *)(base + 0x26); /* UNDI code len */ + code_seg = *(uint16_t *)(base + 0x24); /* UNDI code seg */ + PXEEntry = *(far_ptr_t *)(base + 0x0a); /* PXENV+ entry point */ + printf("PXENV+ entry point found (we hope) at "); + goto have_entrypoint; + + have_pxe: + StructPtr[0] = off; + StructPtr[1] = seg; + base = MK_PTR(seg, off); + + data_len = *(uint16_t *)(base + 0x2e); /* UNDI data len */ + data_seg = *(uint16_t *)(base + 0x28); /* UNDI data seg */ + code_len = *(uint16_t *)(base + 0x36); /* UNDI code len */ + code_seg = *(uint16_t *)(base + 0x30); /* UNDI code seg */ + PXEEntry = *(far_ptr_t *)(base + 0x10); /* !PXE entry point */ + printf("!PXE entry point found (we hope) at "); + + have_entrypoint: + printf("%04X:%04X via plan %c\n", PXEEntry.seg, PXEEntry.offs, plan); + printf("UNDI code segment at %04X len %04X\n", code_seg, code_len); + code_seg = code_seg + ((code_len + 15) >> 4); + + printf("UNDI data segment at %04X len %04X\n", data_seg, data_len); + data_seg = data_seg + ((data_len + 15) >> 4); + + + RealBaseMem = MAX(code_seg,data_seg) >> 6; /* Convert to kilobytes */ + //regs->es = regs->ds; /* Restore the es segment */ +} + +/* + * Initialize UDP stack + * + */ +void udp_init(void) +{ + int err; + static __lowmem struct pxe_udp_open_pkt uo_pkt; + uo_pkt.sip = MyIP; + err = pxe_call(PXENV_UDP_OPEN, &uo_pkt); + if (err || uo_pkt.status) { + printf("%s", err_udpinit); + printf("%d\n", uo_pkt.status); + call16(kaboom, NULL, NULL); + } +} + + +/* + * Network-specific initialization + */ +void network_init() +{ + struct bootp_t *bp = (struct bootp_t *)trackbuf; + int pkt_len; + + *LocalDomain = 0; /* No LocalDomain received */ + + /* + * Get the DHCP client identifiers (query info 1) + */ + printf("%s", get_packet_msg); + pkt_len = pxe_get_cached_info(1); + parse_dhcp(pkt_len); + /* + ; We don't use flags from the request packet, so + ; this is a good time to initialize DHCPMagic... + ; Initialize it to 1 meaning we will accept options found; + ; in earlier versions of PXELINUX bit 0 was used to indicate + ; we have found option 208 with the appropriate magic number; + ; we no longer require that, but MAY want to re-introduce + ; it in the future for vendor encapsulated options. + */ + *(char *)&DHCPMagic = 1; + + + /* + * Get the BOOTP/DHCP packet that brought us file (and an IP + * address). This lives in the DHCPACK packet (query info 2) + */ + pkt_len = pxe_get_cached_info(2); + parse_dhcp(pkt_len); + /* + * Save away MAC address (assume this is in query info 2. If this + * turns out to be problematic it might be better getting it from + * the query info 1 packet + */ + MACLen = bp->hardlen > 16 ? 0 : bp->hardlen; + MACType = bp->hardware; + memcpy(MAC, bp->macaddr, MACLen); + + + /* + * Get the boot file and other info. This lives in the CACHED_REPLY + * packet (query info 3) + */ + pkt_len = pxe_get_cached_info(3); + parse_dhcp(pkt_len); + + printf("\n"); + + + + make_bootif_string(); + ip_init(); + + /* + * Check to see if we got any PXELINUX-specific DHCP options; in particular, + * if we didn't get the magic enable, do not recognize any other options. + */ + if ((DHCPMagic & 1) == 0) + DHCPMagic = 0; + + udp_init(); +} + +/* + * Initialize pxe fs + * + */ +int pxe_fs_init(struct fs_info *fs) +{ + fs = NULL; /* drop the compile warning message */ + + /* do the pxe initialize */ + pxe_init(); + + /* Network-specific initialization */ + network_init(); + + return 0; +} + +const struct fs_ops pxe_fs_ops = { + .fs_name = "pxe", + .fs_init = pxe_fs_init, + .searchdir = pxe_searchdir, + .getfssec = pxe_getfssec, + .mangle_name = pxe_mangle_name, + .unmangle_name = NULL, + .load_config = pxe_load_config +}; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index b866369c..6c009582 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -161,23 +161,31 @@ tftp_pktbuf resw 1 ; Packet buffer offset ; Memory below this point is reserved for the BIOS and the MBR ; section .earlybss + global trackbuf trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h + ; These fields save information from before the time + ; .bss is zeroed... must be in .earlybss + global InitStack +InitStack resd 1 + section .bss16 + global Files alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size alignb FILENAME_MAX + global BootFile, PathPrefix, DotQuadBuf, IPOption BootFile resb 256 ; Boot file from DHCP packet PathPrefix resb 256 ; Path prefix derived from boot file DotQuadBuf resb 16 ; Buffer for dotted-quad IP address IPOption resb 80 ; ip= option buffer -InitStack resd 1 ; Pointer to reset stack (SS:SP) PXEStack resd 1 ; Saved stack during PXE call alignb 4 + global DHCPMagic, OverLoad, RebootTime, APIVer, RealBaseMem RebootTime resd 1 ; Reboot timeout, if set by option StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure APIVer resw 1 ; PXE API version found @@ -187,6 +195,7 @@ OverLoad resb 1 ; Set if DHCP packet uses "overloading" DHCPMagic resb 1 ; PXELINUX magic flags ; The relative position of these fields matter! + global MACStr, MACLen, MACType, MAC, BOOTIFStr MAC_MAX equ 32 ; Handle hardware addresses this long MACLen resb 1 ; MAC address len MACType resb 1 ; MAC address type @@ -195,6 +204,7 @@ BOOTIFStr resb 7 ; Space for "BOOTIF=" MACStr resb 3*(MAC_MAX+1) ; MAC address as a string ; The relative position of these fields matter! + global UUID UUIDType resb 1 ; Type byte from DHCP option UUID resb 16 ; UUID, from the PXE stack UUIDNull resb 1 ; dhcp_copyoption zero-terminates @@ -212,6 +222,7 @@ pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt ; BOOTP/DHCP packet buffer section .bss16 + global packet_buf alignb 16 packet_buf resb 2048 ; Transfer packet packet_buf_size equ $-packet_buf @@ -277,42 +288,20 @@ _start1: call writestr_early ; -; Assume API version 2.1, in case we find the !PXE structure without -; finding the PXENV+ structure. This should really look at the Base -; Code ROM ID structure in have_pxe, but this is adequate for now -- -; if we have !PXE, we have to be 2.1 or higher, and we don't care -; about higher versions than that. +; do fs initialize ; - mov word [APIVer],0201h + extern pxe_fs_ops + mov eax,pxe_fs_ops + pm_call fs_init + jmp next ; -; Now we need to find the !PXE structure. -; We search for the following, in order: -; -; a. !PXE structure as SS:[SP+4] -; b. PXENV+ structure at [ES:BX] -; c. INT 1Ah AX=5650h -> PXENV+ -; d. Search memory for !PXE -; e. Search memory for PXENV+ +; Plan C, because it must be in real mode, we set it here ; -; If we find a PXENV+ structure, we try to find a !PXE structure from -; it if the API version is 2.1 or later. -; - ; Plan A: !PXE structure as SS:[SP+4] - lgs bp,[InitStack] ; GS:BP -> original stack - les bx,[gs:bp+48] - call is_pxe - je have_pxe - - ; Plan B: PXENV+ structure at [ES:BX] - inc byte [plan] - mov bx,[gs:bp+24] ; Original BX - mov es,[gs:bp+4] ; Original ES - call is_pxenv - je have_pxenv - + global plan_c +plan_c: + ; Plan C: PXENV+ structure via INT 1Ah AX=5650h - inc byte [plan] mov ax, 5650h %if USE_PXE_PROVIDED_STACK == 0 lss sp,[InitStack] @@ -322,285 +311,10 @@ _start1: lss esp,[BaseStack] %endif sti ; Work around Etherboot bug + ret - jc no_int1a - cmp ax,564Eh - jne no_int1a - - call is_pxenv - je have_pxenv - -no_int1a: - ; Plan D: !PXE memory scan - inc byte [plan] - call memory_scan_for_pxe_struct ; !PXE scan - je have_pxe - - ; Plan E: PXENV+ memory scan - inc byte [plan] - call memory_scan_for_pxenv_struct ; PXENV+ scan - je have_pxenv - - ; Found nothing at all!! -no_pxe: - mov si,err_nopxe - call writestr_early - jmp kaboom - -have_pxenv: - mov [StrucPtr],bx - mov [StrucPtr+2],es - - mov si,found_pxenv - call writestr_early - - mov si,apiver_str - call writestr_early - mov ax,[es:bx+6] - mov [APIVer],ax - call writehex4 - call crlf - - cmp ax,0201h ; API version 2.1 or higher - jb .old_api - cmp byte [es:bx+8],2Ch ; Space for !PXE pointer? - jb .pxescan - les bx,[es:bx+28h] ; !PXE structure pointer - call is_pxe - je have_pxe - - ; Nope, !PXE structure missing despite API 2.1+, or at least - ; the pointer is missing. Do a last-ditch attempt to find it. -.pxescan: - call memory_scan_for_pxe_struct - je have_pxe - - ; Otherwise, no dice, use PXENV+ structure -.old_api: - les bx,[StrucPtr] - push word [es:bx+22h] ; UNDI data len - push word [es:bx+20h] ; UNDI data seg - push word [es:bx+26h] ; UNDI code len - push word [es:bx+24h] ; UNDI code seg - push dword [es:bx+0Ah] ; PXENV+ entry point - - mov si,pxenventry_msg - jmp have_entrypoint - -have_pxe: - mov [StrucPtr],bx - mov [StrucPtr+2],es - - push word [es:bx+2Eh] ; UNDI data len - push word [es:bx+28h] ; UNDI data seg - push word [es:bx+36h] ; UNDI code len - push word [es:bx+30h] ; UNDI code seg - push dword [es:bx+10h] ; !PXE entry point - - mov si,pxeentry_msg - -have_entrypoint: - push cs - pop es ; Restore CS == DS == ES - - call writestr_early ; !PXE or PXENV+ entry found - - pop dword [PXEEntry] - mov ax,[PXEEntry+2] - call writehex4 - mov al,':' - call writechr - mov ax,[PXEEntry] - call writehex4 - - mov si,viaplan_msg - call writestr_early - - mov si,undi_code_msg - call writestr_early - pop ax ; UNDI code segment - call writehex4 - xchg dx,ax - mov si,len_msg - call writestr_early - pop ax ; UNDI code length - call writehex4 - call crlf - add ax,15 - shr ax,4 - add dx,ax ; DX = seg of end of UNDI code - - mov si,undi_data_msg - call writestr_early - pop ax ; UNDI data segment - call writehex4 - xchg bx,ax - mov si,len_msg - call writestr_early - pop ax ; UNDI data length - call writehex4 - call crlf - add ax,15 - shr ax,4 - add ax,bx ; AX = seg of end of UNDI data - - cmp ax,dx - ja .data_on_top - xchg ax,dx -.data_on_top: - ; Could we safely add 63 here before the shift? - shr ax,6 ; Convert to kilobytes - mov [RealBaseMem],ax - - -; -; Network-specific initialization -; - xor ax,ax - mov [LocalDomain],al ; No LocalDomain received - -; -; The DHCP client identifiers are best gotten from the DHCPREQUEST -; packet (query info 1). -; -query_bootp_1: - mov si,get_packet_msg - call writestr_early - - mov dl,1 - call pxe_get_cached_info - call parse_dhcp - - ; We don't use flags from the request packet, so - ; this is a good time to initialize DHCPMagic... - ; Initialize it to 1 meaning we will accept options found; - ; in earlier versions of PXELINUX bit 0 was used to indicate - ; we have found option 208 with the appropriate magic number; - ; we no longer require that, but MAY want to re-introduce - ; it in the future for vendor encapsulated options. - mov byte [DHCPMagic],1 - -; -; Now attempt to get the BOOTP/DHCP packet that brought us life (and an IP -; address). This lives in the DHCPACK packet (query info 2). -; -query_bootp_2: - mov dl,2 - call pxe_get_cached_info - call parse_dhcp ; Parse DHCP packet -; -; Save away MAC address (assume this is in query info 2. If this -; turns out to be problematic it might be better getting it from -; the query info 1 packet.) -; -.save_mac: - movzx cx,byte [trackbuf+bootp.hardlen] - cmp cx,16 - jna .mac_ok - xor cx,cx ; Bad hardware address length -.mac_ok: - mov [MACLen],cl - mov al,[trackbuf+bootp.hardware] - mov [MACType],al - mov si,trackbuf+bootp.macaddr - mov di,MAC - rep movsb - -; Enable this if we really need to zero-pad this field... -; mov cx,MAC+MAC_MAX+1 -; sub cx,di -; xor ax,ax -; rep stosb - -; -; Now, get the boot file and other info. This lives in the CACHED_REPLY -; packet (query info 3). -; -query_bootp_3: - mov dl,3 - call pxe_get_cached_info - call parse_dhcp ; Parse DHCP packet - call crlf - -; -; Generate the bootif string, and the hardware-based config string. -; -make_bootif_string: - mov si,bootif_str - mov di,BOOTIFStr - mov cx,bootif_str_len - rep movsb - - movzx cx,byte [MACLen] - mov si,MACType - inc cx -.hexify_mac: - push cx - mov cl,1 ; CH == 0 already - call lchexbytes - mov al,'-' - stosb - pop cx - loop .hexify_mac - mov [di-1],cl ; Null-terminate and strip final dash -; -; Generate ip= option -; - call genipopt - -; -; Print IP address -; - mov eax,[MyIP] - mov di,DotQuadBuf - push di - call gendotquad ; This takes network byte order input - - xchg ah,al ; Convert to host byte order - ror eax,16 ; (BSWAP doesn't work on 386) - xchg ah,al - - mov si,myipaddr_msg - call writestr_early - call writehex8 - mov al,' ' - call writechr - pop si ; DotQuadBuf - call writestr_early - call crlf - - mov si,IPOption - call writestr_early - call crlf - -; -; Check to see if we got any PXELINUX-specific DHCP options; in particular, -; if we didn't get the magic enable, do not recognize any other options. -; -check_dhcp_magic: - test byte [DHCPMagic], 1 ; If we didn't get the magic enable... - jnz .got_magic - mov byte [DHCPMagic], 0 ; If not, kill all other options -.got_magic: - - -; -; Initialize UDP stack -; -udp_init: - mov eax,[MyIP] - mov [pxe_udp_open_pkt.sip],eax - mov di,pxe_udp_open_pkt - mov bx,PXENV_UDP_OPEN - call pxenv - jc .failed - cmp word [pxe_udp_open_pkt.status], byte 0 - je .success -.failed: mov si,err_udpinit - call writestr_early - jmp kaboom -.success: +next: ; ; Common initialization code ; @@ -626,146 +340,10 @@ udp_init: ; to boot ELKS at some point. ; -; -; Store standard filename prefix -; -prefix: test byte [DHCPMagic], 04h ; Did we get a path prefix option - jnz .got_prefix - mov si,BootFile - mov di,PathPrefix - cld - call strcpy - mov cx,di - sub cx,PathPrefix+1 - std - lea si,[di-2] ; Skip final null! -.find_alnum: lodsb - or al,20h - cmp al,'.' ; Count . or - as alphanum - je .alnum - cmp al,'-' - je .alnum - cmp al,'0' - jb .notalnum - cmp al,'9' - jbe .alnum - cmp al,'a' - jb .notalnum - cmp al,'z' - ja .notalnum -.alnum: loop .find_alnum - dec si -.notalnum: mov byte [si+2],0 ; Zero-terminate after delimiter - cld -.got_prefix: - mov si,tftpprefix_msg - call writestr_early - mov si,PathPrefix - call writestr_early - call crlf - - ; Set CurrentDirName - push di - mov si,PathPrefix - mov di,CurrentDirName - call strcpy - pop di - ; ; Load configuration file ; -find_config: - -; -; Begin looking for configuration file -; -config_scan: - test byte [DHCPMagic], 02h - jz .no_option - - ; We got a DHCP option, try it first - call .try - jnz .success - -.no_option: - mov di,ConfigName - mov si,cfgprefix - mov cx,cfgprefix_len - rep movsb - - ; Have to guess config file name... - - ; Try loading by UUID. - cmp byte [HaveUUID],0 - je .no_uuid - - push di - mov bx,uuid_dashes - mov si,UUID -.gen_uuid: - movzx cx,byte [bx] - jcxz .done_uuid - inc bx - call lchexbytes - mov al,'-' - stosb - jmp .gen_uuid -.done_uuid: - mov [di-1],cl ; Remove last dash and zero-terminate - pop di - call .try - jnz .success -.no_uuid: - - ; Try loading by MAC address - push di - mov si,MACStr - call strcpy - pop di - call .try - jnz .success - - ; Nope, try hexadecimal IP prefixes... -.scan_ip: - mov cx,4 - mov si,MyIP - call uchexbytes ; Convert to hex string - - mov cx,8 ; Up to 8 attempts -.tryagain: - mov byte [di],0 ; Zero-terminate string - call .try - jnz .success - dec di ; Drop one character - loop .tryagain - - ; Final attempt: "default" string - mov si,default_str ; "default" string - call strcpy - call .try - jnz .success - - mov si,err_noconfig - call writestr_early - jmp kaboom - -.try: - pusha - mov si,trying_msg - call writestr_early - mov di,ConfigName - mov si,di - call writestr_early - call crlf - mov si,di - mov di,KernelName ; Borrow this buffer for mangled name - call mangle_name - call open - popa - ret - - -.success: + pm_call load_config ; ; Linux kernel loading code is common. However, we need to define @@ -814,6 +392,11 @@ local_boot: ; kaboom: write a message and bail out. Wait for quite a while, ; or a user keypress, then do a hard reboot. ; + global no_config, kaboom +; set the no_config kaboom here +no_config: + mov si, err_noconfig + call writestr_early kaboom: RESET_STACK_AND_SEGS AX .patch: mov si,bailmsg @@ -848,718 +431,6 @@ kaboom: mov word [BIOS_magic],0 ; Cold reboot jmp 0F000h:0FFF0h ; Reset vector address -; -; memory_scan_for_pxe_struct: -; memory_scan_for_pxenv_struct: -; -; If none of the standard methods find the !PXE/PXENV+ structure, -; look for it by scanning memory. -; -; On exit, if found: -; ZF = 1, ES:BX -> !PXE structure -; Otherwise: -; ZF = 0 -; -; Assumes DS == CS -; Clobbers AX, BX, CX, DX, SI, ES -; -memory_scan_for_pxe_struct: - mov dx,is_pxe - mov ax,[BIOS_fbm] ; Starting segment - shl ax,(10-4) ; Kilobytes -> paragraphs - jmp memory_scan_common - -memory_scan_for_pxenv_struct: - mov ax,1000h ; Starting segment - mov dx,is_pxenv - ; fall through - -memory_scan_common: - dec ax ; To skip inc ax -.mismatch: - inc ax - cmp ax,0A000h-1 ; End of memory - ja .not_found ; ZF = 0 on not found - mov es,ax - xor bx,bx - call dx - jne .mismatch -.not_found: - ret - -; -; is_pxe: -; Validity check on possible !PXE structure in ES:BX -; is_pxenv: -; Validity check on possible PXENV+ structure in ES:BX -; -; Return ZF = 1 on success -; -; Clobbers CX and SI -; -is_struc: -.pxe: - cmp dword [es:bx],'!PXE' - jne .bad - movzx cx,byte [es:bx+4] - cmp cx,58h - jae .checksum - ret -.pxenv: - cmp dword [es:bx],'PXEN' - jne .bad - cmp word [es:bx+4],'V+' - jne .bad - movzx cx,[es:bx+8] - cmp cx,28h - jb .bad -.checksum: - push ax - mov si,bx - xor ax,ax -.loop: - es lodsb - add ah,al - loop .loop - pop ax -.bad: - ret - -is_pxe equ is_struc.pxe -is_pxenv equ is_struc.pxenv - -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -; XXX: We should check to see if this file is still open on the server -; side and send a courtesy ERROR packet to the server. -; -close_file: - and si,si - jz .closed - mov word [si],0 ; Not in use -.closed: ret - -; -; searchdir: -; -; Open a TFTP connection to the server -; -; On entry: -; DS:DI = mangled filename -; If successful: -; ZF clear -; SI = socket pointer -; EAX = file length in bytes, or -1 if unknown -; If unsuccessful -; ZF set -; - -searchdir: - push es - push bx - push cx - mov ax,ds - mov es,ax - mov si,di - push bp - mov bp,sp - - call allocate_socket - jz .ret - - mov ax,TimeoutTable ; Reset timeout - -.sendreq: push ax ; [bp-2] - Timeout pointer - push si ; [bp-4] - File name - - mov di,packet_buf - mov [pxe_udp_write_pkt.buffer],di - - mov ax,TFTP_RRQ ; TFTP opcode - stosw - - lodsd ; EAX <- server override (if any) - and eax,eax - jnz .noprefix ; No prefix, and we have the server - - push si ; Add common prefix - mov si,PathPrefix - call strcpy - dec di - pop si - - mov eax,[ServerIP] ; Get default server - -.noprefix: - call strcpy ; Filename -%if GPXE - mov si,packet_buf+2 - call is_gpxe - jnc .gpxe -%endif - - mov [bx+tftp_remoteip],eax - - push bx ; [bp-6] - TFTP block - mov bx,[bx] - push bx ; [bp-8] - TID (local port no) - - mov [pxe_udp_write_pkt.sip],eax - ; Now figure out the gateway - xor eax,[MyIP] - and eax,[Netmask] - jz .nogwneeded - mov eax,[Gateway] -.nogwneeded: - mov [pxe_udp_write_pkt.gip],eax - mov [pxe_udp_write_pkt.lport],bx - mov ax,[ServerPort] - mov [pxe_udp_write_pkt.rport],ax - mov si,tftp_tail - mov cx,tftp_tail_len - rep movsb - sub di,packet_buf ; Get packet size - mov [pxe_udp_write_pkt.buffersize],di - - mov di,pxe_udp_write_pkt - mov bx,PXENV_UDP_WRITE - call pxenv - jc .failure - cmp word [pxe_udp_write_pkt.status],byte 0 - jne .failure - - ; - ; Danger, Will Robinson! We need to support timeout - ; and retry lest we just lost a packet... - ; - - ; Packet transmitted OK, now we need to receive -.getpacket: mov bx,[bp-2] - movzx bx,byte [bx] - push bx ; [bp-10] - timeout in ticks - push word [BIOS_timer] ; [bp-12] - -.pkt_loop: mov bx,[bp-8] ; TID - mov di,packet_buf - mov [pxe_udp_read_pkt.buffer],di - mov [pxe_udp_read_pkt.buffer+2],ds - mov word [pxe_udp_read_pkt.buffersize],packet_buf_size - mov eax,[MyIP] - mov [pxe_udp_read_pkt.dip],eax - mov [pxe_udp_read_pkt.lport],bx - mov di,pxe_udp_read_pkt - mov bx,PXENV_UDP_READ - call pxenv - jnc .got_packet ; Wait for packet -.no_packet: - mov dx,[BIOS_timer] - cmp dx,[bp-12] - je .pkt_loop - mov [bp-12],dx - dec word [bp-10] - jnz .pkt_loop - pop ax ; Adjust stack - pop ax - jmp .failure - -.got_packet: - mov si,[bp-6] ; TFTP pointer - mov bx,[bp-8] ; TID - - ; Make sure the packet actually came from the server - ; This is technically not to the TFTP spec? - mov eax,[si+tftp_remoteip] - cmp [pxe_udp_read_pkt.sip],eax - jne .no_packet - - ; Got packet - reset timeout - mov word [bp-2],TimeoutTable - - pop ax ; Adjust stack - pop ax - - mov ax,[pxe_udp_read_pkt.rport] - mov [si+tftp_remoteport],ax - - ; filesize <- -1 == unknown - mov dword [si+tftp_filesize], -1 - ; Default blksize unless blksize option negotiated - mov word [si+tftp_blksize], TFTP_BLOCKSIZE - - movzx ecx,word [pxe_udp_read_pkt.buffersize] - sub cx,2 ; CX <- bytes after opcode - jb .failure ; Garbled reply - - mov si,packet_buf - lodsw - - cmp ax, TFTP_ERROR - je .bailnow ; ERROR reply: don't try again - - ; If the server doesn't support any options, we'll get - ; a DATA reply instead of OACK. Stash the data in - ; the file buffer and go with the default value for - ; all options... - cmp ax, TFTP_DATA - je .no_oack - - cmp ax, TFTP_OACK - jne .err_reply ; Unknown packet type - - ; Now we need to parse the OACK packet to get the transfer - ; and packet sizes. - ; SI -> first byte of options; [E]CX -> byte count -.parse_oack: - jcxz .done_pkt ; No options acked -.get_opt_name: - mov di,si - mov bx,si -.opt_name_loop: lodsb - and al,al - jz .got_opt_name - or al,20h ; Convert to lowercase - stosb - loop .opt_name_loop - ; We ran out, and no final null - jmp .err_reply -.got_opt_name: ; si -> option value - dec cx ; bytes left in pkt - jz .err_reply ; Option w/o value - - ; Parse option pointed to by bx; guaranteed to be - ; null-terminated. - push cx - push si - mov si,bx ; -> option name - mov bx,tftp_opt_table - mov cx,tftp_opts -.opt_loop: - push cx - push si - mov di,[bx] ; Option pointer - mov cx,[bx+2] ; Option len - repe cmpsb - pop si - pop cx - je .get_value ; OK, known option - add bx,6 - loop .opt_loop - - pop si - pop cx - jmp .err_reply ; Non-negotiated option returned - -.get_value: pop si ; si -> option value - pop cx ; cx -> bytes left in pkt - mov bx,[bx+4] ; Pointer to data target - add bx,[bp-6] ; TFTP socket pointer - xor eax,eax - xor edx,edx -.value_loop: lodsb - and al,al - jz .got_value - sub al,'0' - cmp al, 9 - ja .err_reply ; Not a decimal digit - imul edx,10 - add edx,eax - mov [bx],edx - loop .value_loop - ; Ran out before final null, accept anyway - jmp short .done_pkt - -.got_value: - dec cx - jnz .get_opt_name ; Not end of packet - - ; ZF == 1 - - ; Success, done! -.done_pkt: - pop si ; Junk - pop si ; We want the packet ptr in SI - - mov eax,[si+tftp_filesize] -.got_file: ; SI->socket structure, EAX = size - and eax,eax ; Set ZF depending on file size - jz .error_si ; ZF = 1 need to free the socket -.ret: - leave ; SP <- BP, POP BP - pop cx - pop bx - pop es - ret - - -.no_oack: ; We got a DATA packet, meaning no options are - ; suported. Save the data away and consider the length - ; undefined, *unless* this is the only data packet... - mov bx,[bp-6] ; File pointer - sub cx,2 ; Too short? - jb .failure - lodsw ; Block number - cmp ax,htons(1) - jne .failure - mov [bx+tftp_lastpkt],ax - cmp cx,TFTP_BLOCKSIZE - ja .err_reply ; Corrupt... - je .not_eof - ; This was the final EOF packet, already... - ; We know the filesize, but we also want to ack the - ; packet and set the EOF flag. - mov [bx+tftp_filesize],ecx - mov byte [bx+tftp_goteof],1 - push si - mov si,bx - ; AX = htons(1) already - call ack_packet - pop si -.not_eof: - mov [bx+tftp_bytesleft],cx - mov ax,pktbuf_seg - push es - mov es,ax - mov di,tftp_pktbuf - mov [bx+tftp_dataptr],di - add cx,3 - shr cx,2 - rep movsd - pop es - jmp .done_pkt - -.err_reply: ; Option negotiation error. Send ERROR reply. - ; ServerIP and gateway are already programmed in - mov si,[bp-6] - mov ax,[si+tftp_remoteport] - mov word [pxe_udp_write_pkt.rport],ax - mov word [pxe_udp_write_pkt.buffer],tftp_opt_err - mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len - mov di,pxe_udp_write_pkt - mov bx,PXENV_UDP_WRITE - call pxenv - - ; Write an error message and explode - mov si,err_damage - call writestr_early - jmp kaboom - -.bailnow: - ; Immediate error - no retry - mov word [bp-2],TimeoutTableEnd-1 - -.failure: pop bx ; Junk - pop bx - pop si - pop ax - inc ax - cmp ax,TimeoutTableEnd - jb .sendreq ; Try again - -.error: mov si,bx ; Socket pointer -.error_si: ; Socket pointer already in SI - call free_socket ; ZF <- 1, SI <- 0 - jmp .ret - - -%if GPXE -.gpxe: - push bx ; Socket pointer - mov di,gpxe_file_open - mov word [di],2 ; PXENV_STATUS_BAD_FUNC - mov word [di+4],packet_buf+2 ; Completed URL - mov [di+6],ds - mov bx,PXENV_FILE_OPEN - call pxenv - pop si ; Socket pointer in SI - jc .error_si - - mov ax,[di+2] - mov word [si+tftp_localport],-1 ; gPXE URL - mov [si+tftp_remoteport],ax - mov di,gpxe_get_file_size - mov [di+2],ax - -%if 0 - ; Disable this for now since gPXE doesn't always - ; return valid information in PXENV_GET_FILE_SIZE - mov bx,PXENV_GET_FILE_SIZE - call pxenv - mov eax,[di+4] ; File size - jnc .oksize -%endif - or eax,-1 ; Size unknown -.oksize: - mov [si+tftp_filesize],eax - jmp .got_file -%endif ; GPXE - -; -; allocate_socket: Allocate a local UDP port structure -; -; If successful: -; ZF set -; BX = socket pointer -; If unsuccessful: -; ZF clear -; -allocate_socket: - push cx - mov bx,Files - mov cx,MAX_OPEN -.check: cmp word [bx], byte 0 - je .found - add bx,open_file_t_size - loop .check - xor cx,cx ; ZF = 1 - pop cx - ret - ; Allocate a socket number. Socket numbers are made - ; guaranteed unique by including the socket slot number - ; (inverted, because we use the loop counter cx); add a - ; counter value to keep the numbers from being likely to - ; get immediately reused. - ; - ; The NextSocket variable also contains the top two bits - ; set. This generates a value in the range 49152 to - ; 57343. -.found: - dec cx - push ax - mov ax,[NextSocket] - inc ax - and ax,((1 << (13-MAX_OPEN_LG2))-1) | 0xC000 - mov [NextSocket],ax - shl cx,13-MAX_OPEN_LG2 - add cx,ax ; ZF = 0 - xchg ch,cl ; Convert to network byte order - mov [bx],cx ; Socket in use - pop ax - pop cx - ret - -; -; Free socket: socket in SI; return SI = 0, ZF = 1 for convenience -; -free_socket: - push es - pusha - xor ax,ax - mov es,ax - mov di,si - mov cx,tftp_pktbuf >> 1 ; tftp_pktbuf is not cleared - rep stosw - popa - pop es - xor si,si - ret - -; -; parse_dotquad: -; Read a dot-quad pathname in DS:SI and output an IP -; address in EAX, with SI pointing to the first -; nonmatching character. -; -; Return CF=1 on error. -; -; No segment assumptions permitted. -; -parse_dotquad: - push cx - mov cx,4 - xor eax,eax -.parseloop: - mov ch,ah - mov ah,al - lodsb - sub al,'0' - jb .notnumeric - cmp al,9 - ja .notnumeric - aad ; AL += 10 * AH; AH = 0; - xchg ah,ch - jmp .parseloop -.notnumeric: - cmp al,'.'-'0' - pushf - mov al,ah - mov ah,ch - xor ch,ch - ror eax,8 - popf - jne .error - loop .parseloop - jmp .done -.error: - loop .realerror ; If CX := 1 then we're done - clc - jmp .done -.realerror: - stc -.done: - dec si ; CF unchanged! - pop cx - ret - -; -; is_url: Return CF=0 if and only if the buffer pointed to by -; DS:SI is a URL (contains ://). No registers modified. -; -%if GPXE -is_url: - push si - push eax -.loop: - mov eax,[si] - inc si - and al,al - jz .not_url - and eax,0FFFFFFh - cmp eax,'://' - jne .loop -.done: - ; CF=0 here - pop eax - pop si - ret -.not_url: - stc - jmp .done - -; -; is_gpxe: Return CF=0 if and only if the buffer pointed to by -; DS:SI is a URL (contains ://) *and* the gPXE extensions -; API is available. No registers modified. -; -is_gpxe: - call is_url - jc .ret ; Not a URL, don't bother -.again: - cmp byte [HasGPXE],1 - ja .unknown - ; CF=1 if not available (0), - ; CF=0 if known available (1). -.ret: ret - -.unknown: - ; If we get here, the gPXE status is unknown. - push es - pushad - push ds - pop es - mov di,gpxe_file_api_check - mov bx,PXENV_FILE_API_CHECK ; BH = 0 - call pxenv - jc .nogood - cmp dword [di+4],0xe9c17b20 - jne .nogood - mov ax,[di+12] ; Don't care about the upper half... - not ax ; Set bits of *missing* functions... - and ax,01001011b ; The functions we care about - setz bh - jz .done -.nogood: - mov si,gpxe_warning_msg - call writestr_early -.done: - mov [HasGPXE],bh - popad - pop es - jmp .again - - section .data16 -gpxe_warning_msg: - db 'URL syntax, but gPXE extensions not detected, ' - db 'trying plain TFTP...', CR, LF, 0 -HasGPXE db -1 ; Unknown - section .text16 - -%endif - -; -; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed -; to by ES:DI; ends on encountering any whitespace. -; DI is preserved. -; -; This verifies that a filename is < FILENAME_MAX characters -; and doesn't contain whitespace, and zero-pads the output buffer, -; so "repe cmpsb" can do a compare. -; -; The first four bytes of the manged name is the IP address of -; the download host, 0 for no host, or -1 for a gPXE URL. -; -; No segment assumptions permitted. -; -mangle_name: - push di -%if GPXE - call is_url - jc .not_url - or eax,-1 ; It's a URL - jmp .prefix_done -.not_url: -%endif ; GPXE - push si - mov eax,[cs:ServerIP] - cmp byte [si],0 - je .noip ; Null filename?!?! - cmp word [si],'::' ; Leading ::? - je .gotprefix - -.more: - inc si - cmp byte [si],0 - je .noip - cmp word [si],'::' - jne .more - - ; We have a :: prefix of some sort, it could be either - ; a DNS name or a dot-quad IP address. Try the dot-quad - ; first... -.here: - pop si - push si - call parse_dotquad - jc .notdq - cmp word [si],'::' - je .gotprefix -.notdq: - pop si - push si - call dns_resolv - cmp word [si],'::' - jne .noip - and eax,eax - jnz .gotprefix - -.noip: - pop si - xor eax,eax - jmp .prefix_done - -.gotprefix: - pop cx ; Adjust stack - inc si ; Skip double colon - inc si - -.prefix_done: - stosd ; Save IP address prefix - mov cx,FILENAME_MAX-5 - -.mn_loop: - lodsb - cmp al,' ' ; If control or space, end - jna .mn_end - stosb - loop .mn_loop -.mn_end: - inc cx ; At least one null byte - xor ax,ax ; Zero-fill name - rep stosb ; Doesn't do anything if CX=0 - pop di - ret ; Done ; ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled @@ -1582,7 +453,7 @@ unmangle_name: jz .noip cmp eax,-1 jz .noip ; URL - call gendotquad + pm_call gendotquad mov ax,'::' stosw .noip: @@ -1602,6 +473,7 @@ unmangle_name: ; ; While we're at it, save and restore all registers. ; + global pxenv pxenv: pushfd pushad @@ -1636,250 +508,13 @@ pxenv: ret ; Must be after function def due to NASM bug + global PXEEntry PXEEntry equ pxenv.jump+1 section .bss16 alignb 2 PXEStatus resb 2 - section .text16 - -; -; getfssec: Get multiple clusters from a file, given the starting cluster. -; -; In this case, get multiple blocks from a specific TCP connection. -; -; On entry: -; ES:BX -> Buffer -; SI -> TFTP socket pointer -; CX -> 512-byte block count; 0FFFFh = until end of file -; On exit: -; SI -> TFTP socket pointer (or 0 on EOF) -; CF = 1 -> Hit EOF -; ECX -> number of bytes actually read -; -getfssec: - push eax - push edi - push bx - push si - push fs - mov di,bx - mov ax,pktbuf_seg - mov fs,ax - - xor eax,eax - movzx ecx,cx - shl ecx,TFTP_BLOCKSIZE_LG2 ; Convert to bytes - push ecx ; Initial request size - jz .hit_eof ; Nothing to do? - -.need_more: - call fill_buffer - movzx eax,word [si+tftp_bytesleft] - and ax,ax - jz .hit_eof - - push ecx - cmp ecx,eax - jna .ok_size - mov ecx,eax -.ok_size: - mov ax,cx ; EAX<31:16> == ECX<31:16> == 0 - mov bx,[si+tftp_dataptr] - sub [si+tftp_bytesleft],cx - xchg si,bx - fs rep movsb ; Copy from packet buffer - xchg si,bx - mov [si+tftp_dataptr],bx - - pop ecx - sub ecx,eax - jnz .need_more - -.hit_eof: - call fill_buffer - - pop eax ; Initial request amount - xchg eax,ecx - sub ecx,eax ; ... minus anything not gotten - - pop fs - pop si - - ; Is there anything left of this? - mov eax,[si+tftp_filesize] - sub eax,[si+tftp_filepos] - jnz .bytes_left - - cmp [si+tftp_bytesleft],ax ; AX == 0 - jne .bytes_left - - cmp byte [si+tftp_goteof],0 - je .done - ; I'm 99% sure this can't happen, but... - call fill_buffer ; Receive/ACK the EOF packet -.done: - ; The socket is closed and the buffer drained - ; Close socket structure and re-init for next user - call free_socket - stc - jmp .ret -.bytes_left: - clc -.ret: - pop bx - pop edi - pop eax - ret - -; -; Get a fresh packet if the buffer is drained, and we haven't hit -; EOF yet. The buffer should be filled immediately after draining! -; -; expects fs -> pktbuf_seg and ds:si -> socket structure -; -fill_buffer: - cmp word [si+tftp_bytesleft],0 - je .empty - ret ; Otherwise, nothing to do - -.empty: - push es - pushad - mov ax,ds - mov es,ax - - ; Note: getting the EOF packet is not the same thing - ; as tftp_filepos == tftp_filesize; if the EOF packet - ; is empty the latter condition can be true without - ; having gotten the official EOF. - cmp byte [si+tftp_goteof],0 - jne .ret ; Already EOF - -%if GPXE - cmp word [si+tftp_localport], -1 - jne .get_packet_tftp - call get_packet_gpxe - jmp .ret -.get_packet_tftp: -%endif ; GPXE - - ; TFTP code... -.packet_loop: - ; Start by ACKing the previous packet; this should cause the - ; next packet to be sent. - mov bx,TimeoutTable - -.send_ack: push bx ; Retry pointer - movzx cx,byte [bx] ; Timeout - - mov ax,[si+tftp_lastpkt] - call ack_packet ; Send ACK - - ; We used to test the error code here, but sometimes - ; PXE would return negative status even though we really - ; did send the ACK. Now, just treat a failed send as - ; a normally lost packet, and let it time out in due - ; course of events. - -.send_ok: ; Now wait for packet. - mov dx,[BIOS_timer] ; Get current time - -.wait_data: push cx ; Timeout - push dx ; Old time - - mov bx,[si+tftp_pktbuf] - mov [pxe_udp_read_pkt.buffer],bx - mov [pxe_udp_read_pkt.buffer+2],fs - mov [pxe_udp_read_pkt.buffersize],word PKTBUF_SIZE - mov eax,[si+tftp_remoteip] - mov [pxe_udp_read_pkt.sip],eax - mov eax,[MyIP] - mov [pxe_udp_read_pkt.dip],eax - mov ax,[si+tftp_remoteport] - mov [pxe_udp_read_pkt.rport],ax - mov ax,[si+tftp_localport] - mov [pxe_udp_read_pkt.lport],ax - mov di,pxe_udp_read_pkt - mov bx,PXENV_UDP_READ - call pxenv - jnc .recv_ok - - ; No packet, or receive failure - mov dx,[BIOS_timer] - pop ax ; Old time - pop cx ; Timeout - cmp ax,dx ; Same time -> don't advance timeout - je .wait_data ; Same clock tick - loop .wait_data ; Decrease timeout - - pop bx ; Didn't get any, send another ACK - inc bx - cmp bx,TimeoutTableEnd - jb .send_ack - jmp kaboom ; Forget it... - -.recv_ok: pop dx ; - pop cx ; - - cmp word [pxe_udp_read_pkt.buffersize],byte 4 - jb .wait_data ; Bad size for a DATA packet - - mov bx,[si+tftp_pktbuf] - cmp word [fs:bx],TFTP_DATA ; Not a data packet? - jne .wait_data ; Then wait for something else - - mov ax,[si+tftp_lastpkt] - xchg ah,al ; Host byte order - inc ax ; Which packet are we waiting for? - xchg ah,al ; Network byte order - cmp [fs:bx+2],ax - je .right_packet - - ; Wrong packet, ACK the packet and then try again - ; This is presumably because the ACK got lost, - ; so the server just resent the previous packet - mov ax,[fs:bx+2] - call ack_packet - jmp .send_ok ; Reset timeout - -.right_packet: ; It's the packet we want. We're also EOF if the - ; size < blocksize - - pop cx ; Don't need the retry count anymore - - mov [si+tftp_lastpkt],ax ; Update last packet number - - movzx ecx,word [pxe_udp_read_pkt.buffersize] - sub cx,byte 4 ; Skip TFTP header - - ; Set pointer to data block - lea ax,[bx+4] ; Data past TFTP header - mov [si+tftp_dataptr],ax - - add [si+tftp_filepos],ecx - mov [si+tftp_bytesleft],cx - - cmp cx,[si+tftp_blksize] ; Is it a full block? - jb .last_block ; If not, it's EOF - -.ret: - popad - pop es - ret - - -.last_block: ; Last block - ACK packet immediately - mov ax,[fs:bx+2] - call ack_packet - - ; Make sure we know we are at end of file - mov eax,[si+tftp_filepos] - mov [si+tftp_filesize],eax - mov byte [si+tftp_goteof],1 - - jmp .ret ; ; TimeoutTable: list of timeouts (in 18.2 Hz timer ticks) @@ -1894,96 +529,7 @@ TimeoutTable: TimeoutTableEnd equ $ section .text16 -; -; ack_packet: -; -; Send ACK packet. This is a common operation and so is worth canning. -; -; Entry: -; SI = TFTP block -; AX = Packet # to ack (network byte order) -; Exit: -; All registers preserved -; -; This function uses the pxe_udp_write_pkt but not the packet_buf. -; -ack_packet: - pushad - mov [ack_packet_buf+2],ax ; Packet number to ack - mov ax,[si] - mov [pxe_udp_write_pkt.lport],ax - mov ax,[si+tftp_remoteport] - mov [pxe_udp_write_pkt.rport],ax - mov eax,[si+tftp_remoteip] - mov [pxe_udp_write_pkt.sip],eax - xor eax,[MyIP] - and eax,[Netmask] - jz .nogw - mov eax,[Gateway] -.nogw: - mov [pxe_udp_write_pkt.gip],eax - mov [pxe_udp_write_pkt.buffer],word ack_packet_buf - mov [pxe_udp_write_pkt.buffersize], word 4 - mov di,pxe_udp_write_pkt - mov bx,PXENV_UDP_WRITE - call pxenv - popad - ret - -%if GPXE -; -; Get a fresh packet from a gPXE socket; expects fs -> pktbuf_seg -; and ds:si -> socket structure -; -; Assumes CS == DS == ES. -; -get_packet_gpxe: - mov di,gpxe_file_read - - mov ax,[si+tftp_remoteport] ; gPXE filehandle - mov [di+2],ax - mov ax,[si+tftp_pktbuf] - mov [di+6],ax - mov [si+tftp_dataptr],ax - mov [di+8],fs - -.again: - mov word [di+4],PKTBUF_SIZE - mov bx,PXENV_FILE_READ - call pxenv - jnc .ok ; Got data or EOF - cmp word [di],PXENV_STATUS_TFTP_OPEN ; == EWOULDBLOCK - je .again - jmp kaboom ; Otherwise error... - -.ok: - movzx eax,word [di+4] ; Bytes read - mov [si+tftp_bytesleft],ax ; Bytes in buffer - add [si+tftp_filepos],eax ; Position in file - - and ax,ax ; EOF? - mov eax,[si+tftp_filepos] - - jnz .got_stuff - - ; We got EOF here, make sure the upper layers know - mov [si+tftp_filesize],eax -.got_stuff: - ; If we're done here, close the file - cmp [si+tftp_filesize],eax - ja .done ; Not EOF, there is still data... - - ; Reuse the previous [es:di] structure since the - ; relevant fields are all the same - mov byte [si+tftp_goteof],1 - - mov bx,PXENV_FILE_CLOSE - call pxenv - ; Ignore return... -.done: - ret -%endif ; GPXE ; ; unload_pxe: @@ -2082,460 +628,7 @@ reset_pxe: pop es ret -; -; gendotquad -; -; Take an IP address (in network byte order) in EAX and -; output a dotted quad string to ES:DI. -; DI points to terminal null at end of string on exit. -; -gendotquad: - push eax - push cx - mov cx,4 -.genchar: - push eax - cmp al,10 ; < 10? - jb .lt10 ; If so, skip first 2 digits - - cmp al,100 ; < 100 - jb .lt100 ; If so, skip first digit - - aam 100 - ; Now AH = 100-digit; AL = remainder - add ah,'0' - mov [es:di],ah - inc di - -.lt100: - aam 10 - ; Now AH = 10-digit; AL = remainder - add ah,'0' - mov [es:di],ah - inc di - -.lt10: - add al,'0' - stosb - mov al,'.' - stosb - pop eax - ror eax,8 ; Move next char into LSB - loop .genchar - dec di - mov [es:di], byte 0 - pop cx - pop eax - ret -; -; uchexbytes/lchexbytes -; -; Take a number of bytes in memory and convert to upper/lower-case -; hexadecimal -; -; Input: -; DS:SI = input bytes -; ES:DI = output buffer -; CX = number of bytes -; Output: -; DS:SI = first byte after -; ES:DI = first byte after -; CX = 0 -; -; Trashes AX, DX -; - -lchexbytes: - mov dl,'a'-'9'-1 - jmp xchexbytes -uchexbytes: - mov dl,'A'-'9'-1 -xchexbytes: -.loop: - lodsb - mov ah,al - shr al,4 - call .outchar - mov al,ah - call .outchar - loop .loop - ret -.outchar: - and al,0Fh - add al,'0' - cmp al,'9' - jna .done - add al,dl -.done: - stosb - ret - -; -; pxe_get_cached_info -; -; Get a DHCP packet from the PXE stack into the trackbuf. -; -; Input: -; DL = packet type -; Output: -; CX = buffer size -; -; Assumes CS == DS == ES. -; -pxe_get_cached_info: - pushad - mov al,' ' - call writechr - mov al,dl - call writehex2 - mov di,pxe_bootp_query_pkt - push di - xor ax,ax - stosw ; Status - movzx ax,dl - stosw ; Packet type - mov ax,trackbufsize - stosw ; Buffer size - mov ax,trackbuf - stosw ; Buffer offset - xor ax,ax - stosw ; Buffer segment - pop di ; DI -> parameter set - mov bx,PXENV_GET_CACHED_INFO - call pxenv - jc .err - - popad - mov cx,[pxe_bootp_query_pkt.buffersize] - ret - -.err: - mov si,err_pxefailed - call writestr_early - call writehex4 - call crlf - jmp kaboom - - section .data16 -get_packet_msg db 'Getting cached packet', 0 - - section .text16 -; -; ip_ok -; -; Tests an IP address in EAX for validity; return with ZF=1 for bad. -; We used to refuse class E, but class E addresses are likely to become -; assignable unicast addresses in the near future. -; -ip_ok: - push ax - cmp eax,-1 ; Refuse the all-ones address - jz .out - and al,al ; Refuse network zero - jz .out - cmp al,127 ; Refuse loopback - jz .out - and al,0F0h - cmp al,224 ; Refuse class D -.out: - pop ax - ret - -; -; parse_dhcp -; -; Parse a DHCP packet. This includes dealing with "overloaded" -; option fields (see RFC 2132, section 9.3) -; -; This should fill in the following global variables, if the -; information is present: -; -; MyIP - client IP address -; ServerIP - boot server IP address -; Netmask - network mask -; Gateway - default gateway router IP -; BootFile - boot file name -; DNSServers - DNS server IPs -; LocalDomain - Local domain name -; MACLen, MAC - Client identifier, if MACLen == 0 -; -; This assumes the DHCP packet is in "trackbuf" and the length -; of the packet in in CX on entry. -; - -parse_dhcp: - mov byte [OverLoad],0 ; Assume no overload - mov eax, [trackbuf+bootp.yip] - call ip_ok - jz .noyip - mov [MyIP], eax -.noyip: - mov eax, [trackbuf+bootp.sip] - and eax, eax - call ip_ok - jz .nosip - mov [ServerIP], eax -.nosip: - sub cx, bootp.options - jbe .nooptions - mov si, trackbuf+bootp.option_magic - lodsd - cmp eax, BOOTP_OPTION_MAGIC - jne .nooptions - call parse_dhcp_options -.nooptions: - mov si, trackbuf+bootp.bootfile - test byte [OverLoad],1 - jz .nofileoverload - mov cx,128 - call parse_dhcp_options - jmp short .parsed_file -.nofileoverload: - cmp byte [si], 0 - jz .parsed_file ; No bootfile name - mov di,BootFile - mov cx,32 - rep movsd - xor al,al - stosb ; Null-terminate -.parsed_file: - mov si, trackbuf+bootp.sname - test byte [OverLoad],2 - jz .nosnameoverload - mov cx,64 - call parse_dhcp_options -.nosnameoverload: - ret - -; -; Parse a sequence of DHCP options, pointed to by DS:SI; the field -; size is CX -- some DHCP servers leave option fields unterminated -; in violation of the spec. -; -; For parse_some_dhcp_options, DH contains the minimum value for -; the option to recognize -- this is used to restrict parsing to -; PXELINUX-specific options only. -; -parse_dhcp_options: - xor dx,dx - -parse_some_dhcp_options: -.loop: - and cx,cx - jz .done - - lodsb - dec cx - jz .done ; Last byte; must be PAD, END or malformed - cmp al, 0 ; PAD option - je .loop - cmp al,255 ; END option - je .done - - ; Anything else will have a length field - mov dl,al ; DL <- option number - xor ax,ax - lodsb ; AX <- option length - dec cx - sub cx,ax ; Decrement bytes left counter - jb .done ; Malformed option: length > field size - - cmp dl,dh ; Is the option value valid? - jb .opt_done - - mov bx,dhcp_option_list -.find_option: - cmp bx,dhcp_option_list_end - jae .opt_done - cmp dl,[bx] - je .found_option - add bx,3 - jmp .find_option -.found_option: - pushad - call [bx+1] - popad - -; Fall through - ; Unknown option. Skip to the next one. -.opt_done: - add si,ax - jmp .loop -.done: - ret - - section .data16 -dhcp_option_list: - section .text16 - -%macro dopt 2 - section .data16 - db %1 - dw dopt_%2 - section .text16 -dopt_%2: -%endmacro - -; -; Parse individual DHCP options. SI points to the option data and -; AX to the option length. DL contains the option number. -; All registers are saved around the routine. -; - dopt 1, subnet_mask - mov ebx,[si] - mov [Netmask],ebx - ret - - dopt 3, router - mov ebx,[si] - mov [Gateway],ebx - ret - - dopt 6, dns_servers - mov cx,ax - shr cx,2 - cmp cl,DNS_MAX_SERVERS - jna .oklen - mov cl,DNS_MAX_SERVERS -.oklen: - mov di,DNSServers - rep movsd - mov [LastDNSServer],di - ret - - dopt 15, local_domain - mov bx,si - add bx,ax - xor ax,ax - xchg [bx],al ; Zero-terminate option - mov di,LocalDomain - call dns_mangle ; Convert to DNS label set - mov [bx],al ; Restore ending byte - ret - - dopt 43, vendor_encaps - mov dh,208 ; Only recognize PXELINUX options - mov cx,ax ; Length of option = max bytes to parse - call parse_some_dhcp_options ; Parse recursive structure - ret - - dopt 52, option_overload - mov bl,[si] - mov [OverLoad],bl - ret - - dopt 54, server - mov eax,[si] - cmp dword [ServerIP],0 - jne .skip ; Already have a next server IP - call ip_ok - jz .skip - mov [ServerIP],eax -.skip: ret - - dopt 61, client_identifier - cmp ax,MAC_MAX ; Too long? - ja .skip - cmp ax,2 ; Too short? - jb .skip - cmp [MACLen],ah ; Only do this if MACLen == 0 - jne .skip - push ax - lodsb ; Client identifier type - cmp al,[MACType] - pop ax - jne .skip ; Client identifier is not a MAC - dec ax - mov [MACLen],al - mov di,MAC - jmp dhcp_copyoption -.skip: ret - - dopt 67, bootfile_name - mov di,BootFile - jmp dhcp_copyoption - - dopt 97, uuid_client_identifier - cmp ax,17 ; type byte + 16 bytes UUID - jne .skip - mov dl,[si] ; Must have type 0 == UUID - or dl,[HaveUUID] ; Capture only the first instance - jnz .skip - mov byte [HaveUUID],1 ; Got UUID - mov di,UUIDType - jmp dhcp_copyoption -.skip: ret - - dopt 209, pxelinux_configfile - mov di,ConfigName - or byte [DHCPMagic],2 ; Got config file - jmp dhcp_copyoption - - dopt 210, pxelinux_pathprefix - mov di,PathPrefix - or byte [DHCPMagic],4 ; Got path prefix - jmp dhcp_copyoption - - dopt 211, pxelinux_reboottime - cmp al,4 - jne .done - mov ebx,[si] - xchg bl,bh ; Convert to host byte order - rol ebx,16 - xchg bl,bh - mov [RebootTime],ebx - or byte [DHCPMagic],8 ; Got RebootTime -.done: ret - - ; Common code for copying an option verbatim - ; Copies the option into ES:DI and null-terminates it. - ; Returns with AX=0 and SI past the option. -dhcp_copyoption: - xchg cx,ax ; CX <- option length - rep movsb - xchg cx,ax ; AX <- 0 - stosb ; Null-terminate - ret - - section .data16 -dhcp_option_list_end: - section .text16 - - section .data16 -HaveUUID db 0 -uuid_dashes db 4,2,2,2,6,0 ; Bytes per UUID dashed section - section .text16 - -; -; genipopt -; -; Generate an ip=::: -; option into IPOption based on a DHCP packet in trackbuf. -; Assumes CS == DS == ES. -; -genipopt: - pushad - mov di,IPOption - mov eax,'ip=' - stosd - dec di - mov eax,[MyIP] - call gendotquad - mov al,':' - stosb - mov eax,[ServerIP] - call gendotquad - mov al,':' - stosb - mov eax,[Gateway] - call gendotquad - mov al,':' - stosb - mov eax,[Netmask] - call gendotquad ; Zero-terminates its output - popad - ret ; ----------------------------------------------------------------------------- ; Common modules @@ -2627,6 +720,8 @@ old_api_unload: ; PXE query packets partially filled in ; section .bss16 + global pxe_bootp_query_pkt, pxe_udp_write_pkt + global pxe_udp_open_pkt, pxe_udp_read_pkt pxe_bootp_query_pkt: .status: resw 1 ; Status .packettype: resw 1 ; Boot server packet type @@ -2662,7 +757,7 @@ pxe_udp_read_pkt: %if GPXE section .data16 - + global gpxe_file_api_check gpxe_file_api_check: .status: dw 0 ; Status .size: dw 20 ; Size in bytes @@ -2672,6 +767,8 @@ gpxe_file_api_check: .flags: dd 0 section .bss16 + global gpxe_file_read, gpxe_get_file_size + global gpxe_file_open gpxe_file_open: .status: resw 1 ; Status @@ -2698,9 +795,9 @@ gpxe_file_read: section .data16 alignz 4 + global BaseStack BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack -NextSocket dw 49152 ; Counter for allocating socket numbers KeepPXE db 0 ; Should PXE be kept around? ; @@ -2727,18 +824,22 @@ tftp_opt_table: tftp_opts equ ($-tftp_opt_table)/6 ; -; Error packet to return on options negotiation error +; Error packet to return on TFTP protocol error +; Most of our errors are OACK parsing errors, so use that error code ; -tftp_opt_err dw TFTP_ERROR ; ERROR packet - dw TFTP_EOPTNEG ; ERROR 8: bad options - db 'tsize option required', 0 ; Error message -tftp_opt_err_len equ ($-tftp_opt_err) + global tftp_proto_err, tftp_proto_err_len +tftp_proto_err dw TFTP_ERROR ; ERROR packet + dw TFTP_EOPTNEG ; ERROR 8: OACK error + db 'TFTP protocol error', 0 ; Error message +tftp_proto_err_len equ ($-tftp_proto_err) alignz 4 + global ack_packet_buf ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet ; ; IP information (initialized to "unknown" values) + global MyIP, ServerIP, Netmask, Gateway, ServerPort MyIP dd 0 ; My IP address ServerIP dd 0 ; IP address of boot server Netmask dd 0 ; Netmask of this subnet -- cgit v1.2.1 From 3005ac33860fd714991272e0e97b7337b2c5de73 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 6 Aug 2009 17:27:02 +0800 Subject: Core:PXELINUX: pxelinux derivative merged succeesfully So, now we have all the fs converted, and the rest is to make it better and more simple --- core/Makefile | 6 ++-- core/cache.c | 2 +- core/dhcp_option.c | 30 ++++++++++---------- core/diskio.c | 15 +++++++--- core/extern.inc | 3 ++ core/fat.c | 2 +- core/fs.c | 10 +++---- core/include/core.h | 51 ++++++++++++++++++++++++++++++++++ core/include/disk.h | 2 +- core/include/pxe.h | 56 +------------------------------------ core/pxe.c | 80 ++++++++++++++++++++++++----------------------------- core/pxelinux.asm | 5 ++-- 12 files changed, 132 insertions(+), 130 deletions(-) diff --git a/core/Makefile b/core/Makefile index b690ef32..4711c7df 100644 --- a/core/Makefile +++ b/core/Makefile @@ -32,10 +32,10 @@ INCLUDES = -I./include -I$(com32)/include CODEPAGE = cp865 # The targets to build in this directory... -BTARGET = kwdhash.gen pxelinux.0 - #extlinux.bin extlinux.bss extlinux.sys \ +BTARGET = kwdhash.gen \ + extlinux.bin extlinux.bss extlinux.sys \ ldlinux.bss ldlinux.sys ldlinux.bin \ - pxelinux.0 isolinux.bin isolinux-debug.bin + isolinux.bin isolinux-debug.bin pxelinux.0 # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) diff --git a/core/cache.c b/core/cache.c index 4be99bb3..c55f1603 100644 --- a/core/cache.c +++ b/core/cache.c @@ -106,7 +106,7 @@ struct cache_struct* get_cache_block(struct device *dev, block_t block) /* store it at the head of real cache */ cs = head->next; cs->block = block; - getoneblk(cs->data, block, dev->cache_block_size); + getoneblk(dev->disk, cs->data, block, dev->cache_block_size); missed ++; } diff --git a/core/dhcp_option.c b/core/dhcp_option.c index f9ff4f22..d9d913fb 100644 --- a/core/dhcp_option.c +++ b/core/dhcp_option.c @@ -4,21 +4,23 @@ #include #include -void subnet_mask(void *data, int opt_len) +void parse_dhcp_options(void *, int, int); + +static void subnet_mask(void *data, int opt_len) { if (opt_len != 4) return; Netmask = *(uint32_t *)data; } -void router(void *data, int opt_len) +static void router(void *data, int opt_len) { if (opt_len != 4) return; Gateway = *(uint32_t *)data; } -void dns_servers(void *data, int opt_len) +static void dns_servers(void *data, int opt_len) { int num = opt_len >> 2; int i; @@ -35,7 +37,7 @@ void dns_servers(void *data, int opt_len) LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0); } -void local_domain(void *data, int opt_len) +static void local_domain(void *data, int opt_len) { com32sys_t regs; char *p = (char *)data + opt_len; @@ -49,13 +51,13 @@ void local_domain(void *data, int opt_len) *p = end; /* Resotre ending byte */ } -void vendor_encaps(void *data, int opt_len) +static void vendor_encaps(void *data, int opt_len) { /* Only recongnize PXELINUX options */ parse_dhcp_options(data, opt_len, 208); } -void option_overload(void *data, int opt_len) +static void option_overload(void *data, int opt_len) { if (opt_len != 1) return; @@ -63,7 +65,7 @@ void option_overload(void *data, int opt_len) } -void server(void *data, int opt_len) +static void server(void *data, int opt_len) { uint32_t ip; @@ -78,7 +80,7 @@ void server(void *data, int opt_len) ServerIP = ip; } -void client_identifier(void *data, int opt_len) +static void client_identifier(void *data, int opt_len) { if (opt_len > MAC_MAX || opt_len < 2 || MACLen != (opt_len >> 8) || @@ -91,13 +93,13 @@ void client_identifier(void *data, int opt_len) MAC[opt_len] = 0; } -void bootfile_name(void *data, int opt_len) +static void bootfile_name(void *data, int opt_len) { strncpy(BootFile, data, opt_len); BootFile[opt_len] = 0; } -void uuid_client_identifier(void *data, int opt_len) +static void uuid_client_identifier(void *data, int opt_len) { int type = *(uint8_t *)data; if (opt_len != 17 || @@ -110,21 +112,21 @@ void uuid_client_identifier(void *data, int opt_len) UUID[16] = 0; } -void pxelinux_configfile(void *data, int opt_len) +static void pxelinux_configfile(void *data, int opt_len) { DHCPMagic |= 2; strncpy(ConfigName, data, opt_len); ConfigName[opt_len] = 0; } -void pxelinux_pathprefix(void *data,int opt_len) +static void pxelinux_pathprefix(void *data,int opt_len) { DHCPMagic |= 4; strncpy(PathPrefix, data, opt_len); PathPrefix[opt_len] = 0; } -void pxelinux_reboottime(void *data, int opt_len) +static void pxelinux_reboottime(void *data, int opt_len) { if ((opt_len && 0xff) != 4) return ; @@ -139,7 +141,7 @@ struct dhcp_options { void (*fun) (void *, int); }; -struct dhcp_options dhcp_opts[] = { +static struct dhcp_options dhcp_opts[] = { {1, subnet_mask}, {3, router}, {6, dns_servers}, diff --git a/core/diskio.c b/core/diskio.c index 274157bc..c51f7225 100644 --- a/core/diskio.c +++ b/core/diskio.c @@ -8,7 +8,7 @@ #define RETRY_COUNT 6 -extern uint16_t MaxTransfer; +static uint16_t MaxTransfer = 1 << (16 - 9); static int chs_rdwr_sectors(struct disk *disk, void *buf, sector_t lba, size_t count, bool is_write) @@ -212,7 +212,7 @@ static inline bool is_power_of_2(uint32_t x) return !(x & (x-1)); } -int ilog2(uint32_t num) +static int ilog2(uint32_t num) { int i = 0; @@ -225,7 +225,14 @@ int ilog2(uint32_t num) return i; } -void dump_disk(struct disk *disk) +void getoneblk(struct disk *disk, char *buf, block_t block, int block_size) +{ + int sec_per_block = block_size >> SECTOR_SHIFT; + + disk->rdwr_sectors(disk, buf, block * sec_per_block, sec_per_block, 0); +} + +static void dump_disk(struct disk *disk) { printf("drive number: 0x%x\n", disk->disk_number); printf("disk type: %s(%d)\n", disk->type ? "EDD" : "CHS", disk->type); @@ -333,7 +340,7 @@ struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start, /* debug function */ -void dump_dev(struct device *dev) +static void dump_dev(struct device *dev) { printf("device type:%s\n", dev->disk->type ? "EDD" : "CHS"); printf("drive number: 0x%x\n", dev->disk->disk_number); diff --git a/core/extern.inc b/core/extern.inc index a820c9ac..026b8c1b 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -15,10 +15,13 @@ ; fs.c extern fs_init, searchdir, getfssec, mangle_name, load_config +%if IS_SYSLINUX ; fat.c extern alloc_fill_dir, readdir +%elif IS_PXELINUX ; pxe.c extern gendotquad +%endif %endif ; EXTERN_INC diff --git a/core/fat.c b/core/fat.c index df249a08..ff710636 100644 --- a/core/fat.c +++ b/core/fat.c @@ -54,7 +54,7 @@ char *NameStart; int NameLen; /* do this for readdir, because it called from asm and don't know the fs structure */ -struct fs_info *this_fs = NULL; +static struct fs_info *this_fs = NULL; /** diff --git a/core/fs.c b/core/fs.c index 7dc3b2a3..89e44ce2 100644 --- a/core/fs.c +++ b/core/fs.c @@ -2,11 +2,11 @@ #include #include #include "fs.h" -//#include "cache.h" +#include "cache.h" /* The this fs pointer */ -struct fs_info *this_fs; +struct fs_info *this_fs = NULL; struct fs_info fs; @@ -91,7 +91,7 @@ void fs_init(com32sys_t *regs) /* set up the fs stucture */ fs.fs_name = ops->fs_name; fs.fs_ops = ops; - if (1)//! strcmp(fs.fs_name, "pxe")) + if (! strcmp(fs.fs_name, "pxe")) fs.fs_dev = NULL; else fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, \ @@ -102,6 +102,6 @@ void fs_init(com32sys_t *regs) blk_shift = fs.fs_ops->fs_init(&fs); /* initialize the cache */ - //if (fs.fs_dev && fs.fs_dev->cache_data) - // cache_init(fs.fs_dev, blk_shift); + if (fs.fs_dev && fs.fs_dev->cache_data) + cache_init(fs.fs_dev, blk_shift); } diff --git a/core/include/core.h b/core/include/core.h index f7a7262d..069354bb 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -29,4 +29,55 @@ void call16(void (*)(void), const com32sys_t *, com32sys_t *); #define __lowmem __attribute((nocommon,section(".lowmem"))) +/* + * externs for pxelinux + */ +extern void kaboom(void); +extern void dns_mangle(void); + +extern uint32_t ServerIP; +extern uint32_t MyIP; +extern uint32_t Netmask; +extern uint32_t Gateway; +extern uint32_t ServerPort; + +extern char MACStr[]; /* MAC address as a string */ +extern char MAC[]; /* Actual MAC address */ +extern char BOOTIFStr[]; /* Space for "BOOTIF=" */ +extern uint8_t MACLen; /* MAC address len */ +extern uint8_t MACType; /* MAC address type */ + +extern uint8_t DHCPMagic; +extern uint8_t OverLoad; +extern uint32_t RebootTime; + +/* TFTP ACK packet */ +extern uint16_t ack_packet_buf[]; + +extern char trackbuf[]; +extern char BootFile[]; +extern char PathPrefix[]; +extern char LocalDomain[]; + +extern char packet_buf[]; + +extern char IPOption[]; +extern char DotQuadBuf[]; + +extern uint32_t DNSServers[]; +extern uint16_t LastDNSServer; + +extern uint16_t RealBaseMem; +extern uint16_t APIVer; +extern far_ptr_t PXEEntry; + +extern far_ptr_t InitStack; + +extern int HaveUUID; +extern uint8_t UUIDType; +extern char UUID[]; + +extern volatile uint16_t BIOS_timer; + + #endif /* CORE_H */ diff --git a/core/include/disk.h b/core/include/disk.h index 0d8702db..91f7a57a 100644 --- a/core/include/disk.h +++ b/core/include/disk.h @@ -31,7 +31,7 @@ struct disk { }; extern void read_sectors(char *, sector_t, int); -extern void getoneblk(char *, block_t, int); +extern void getoneblk(struct disk *, char *, block_t, int); /* diskio.c */ struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t); diff --git a/core/include/pxe.h b/core/include/pxe.h index b9c71dfb..1aa05068 100644 --- a/core/include/pxe.h +++ b/core/include/pxe.h @@ -198,6 +198,7 @@ #define TFTP_EOPTNEG htons(8) // Option negotiation failure #define BOOTP_OPTION_MAGIC htonl(0x63825363) +#define MAC_MAX 32 /* @@ -300,61 +301,6 @@ struct gpxe_file_read { uint16_t buffer[2]; } __attribute__ ((packed)); -/* - * externs - */ -extern uint32_t ServerIP; -extern uint32_t MyIP; -extern uint32_t Netmask; -extern uint32_t Gateway; -extern uint32_t ServerPort; - -#define MAC_MAX 32 -extern char MACStr[]; /* MAC address as a string */ -extern char MAC[]; /* Actual MAC address */ -extern char BOOTIFStr[]; /* Space for "BOOTIF=" */ -extern uint8_t MACLen; /* MAC address len */ -extern uint8_t MACType; /* MAC address type */ - - -extern uint8_t DHCPMagic; -extern uint8_t OverLoad; -extern uint32_t RebootTime; - - -/* TFTP ACK packet */ -extern uint16_t ack_packet_buf[]; - -extern void kaboom(void); -extern void dns_mangle(void); -extern char trackbuf[]; -extern char BootFile[]; -extern char PathPrefix[]; -extern char CurrentDirName[]; -extern char LocalDomain[]; - -extern char packet_buf[]; - -extern char IPOption[]; -extern char DotQuadBuf[]; - - -extern uint32_t DNSServers[]; -extern uint16_t LastDNSServer; - -extern char ConfigName[]; - -extern uint16_t RealBaseMem; -extern uint16_t APIVer; -extern far_ptr_t PXEEntry; - -extern far_ptr_t InitStack; - -extern int HaveUUID; -extern uint8_t UUIDType; -extern char UUID[]; - -extern volatile uint16_t BIOS_timer; /* diff --git a/core/pxe.c b/core/pxe.c index 1a61d96e..81d3e235 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -26,13 +26,10 @@ char *get_packet_msg = "Getting cached packet "; uint16_t NextSocket = 49152; -int has_gpxe; +static int has_gpxe; int HaveUUID = 0; -uint8_t UUIDType; uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; -uint16_t StructPtr[2]; - static const uint8_t TimeoutTable[] = { 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 @@ -54,7 +51,7 @@ char *asciidec = "1408"; * return the socket pointer if success, or null if failure * */ -struct open_file_t* allocate_socket() +static struct open_file_t* allocate_socket() { extern uint16_t NextSocket; uint16_t i = MAX_OPEN; @@ -93,7 +90,7 @@ struct open_file_t* allocate_socket() /* * free socket, socket in SI; return SI = 0, ZF = 1 for convenience */ -void free_socket(struct open_file_t *file) +static void free_socket(struct open_file_t *file) { /* tftp_pktbuf is not cleared */ memset(file, 0, sizeof(struct open_file_t) - 2); @@ -107,7 +104,7 @@ void free_socket(struct open_file_t *file) * @param: count, number of bytes * */ -void lchexbytes(char *dst, const void *src, int count) +static void lchexbytes(char *dst, const void *src, int count) { uint8_t half; uint8_t c; @@ -127,7 +124,7 @@ void lchexbytes(char *dst, const void *src, int count) * just like the lchexbytes, except to upper-case * */ -void uchexbytes(char *dst, const void *src, int count) +static void uchexbytes(char *dst, const void *src, int count) { uint8_t half; uint8_t c; @@ -216,7 +213,7 @@ int gendotquad(char *dst, uint32_t ip) * return the the string address after the ip string * */ -char *parse_dotquad(char *ip_str, uint32_t *res) +static char *parse_dotquad(char *ip_str, uint32_t *res) { char *p = ip_str; int i = 0; @@ -245,7 +242,7 @@ char *parse_dotquad(char *ip_str, uint32_t *res) * the ASM pxenv function wrapper, return 1 if error, or 0 * */ -int pxe_call(int opcode, void *data) +static int pxe_call(int opcode, void *data) { extern void pxenv(void); com32sys_t in_regs, out_regs; @@ -272,7 +269,7 @@ int pxe_call(int opcode, void *data) * @param: ack_num, Packet # to ack (network byte order) * */ -void ack_packet(struct open_file_t *file, uint16_t ack_num) +static void ack_packet(struct open_file_t *file, uint16_t ack_num) { int err; static __lowmem struct pxe_udp_write_pkt uw_pkt; @@ -301,7 +298,7 @@ void ack_packet(struct open_file_t *file, uint16_t ack_num) * @return: buffer size * */ -int pxe_get_cached_info(int type) +static int pxe_get_cached_info(int type) { int err; static __lowmem struct pxe_bootp_query_pkt bq_pkt; @@ -331,7 +328,7 @@ int pxe_get_cached_info(int type) * url is a URL (contains ://) * */ -int is_url(char *url) +static int is_url(char *url) { while (*url) { @@ -349,7 +346,7 @@ int is_url(char *url) * (contains ://) *and* the gPXE extensions API is available. No * registers modified. */ -int is_gpxe(char *url) +static int is_gpxe(char *url) { int err; static __lowmem struct gpxe_file_api_check ac; @@ -383,7 +380,7 @@ int is_gpxe(char *url) * @param: file -> socket structure * */ -void get_packet_gpxe(struct open_file_t *file) +static void get_packet_gpxe(struct open_file_t *file) { static __lowmem struct gpxe_file_read fr; int err; @@ -427,10 +424,10 @@ void get_packet_gpxe(struct open_file_t *file) * the download host, 0 for no host, or -1 for a gPXE URL. * */ -void pxe_mangle_name(char *dst, char *src) +static void pxe_mangle_name(char *dst, char *src) { char *p = src; - uint32_t ip; + uint32_t ip = 0; int i = 0; #if GPXE @@ -510,7 +507,7 @@ void pxe_mangle_name(char *dst, char *src) ; expects fs -> pktbuf_seg and ds:si -> socket structure ; */ -void fill_buffer(struct open_file_t *file) +static void fill_buffer(struct open_file_t *file) { int err; int last_pkt; @@ -627,7 +624,7 @@ void fill_buffer(struct open_file_t *file) * @return: the bytes read * */ -uint32_t pxe_getfssec(struct fs_info *fs, char *buf, +static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, void *open_file, int blocks, int *have_more) { struct open_file_t *file = (struct open_file_t *)open_file; @@ -676,7 +673,7 @@ uint32_t pxe_getfssec(struct fs_info *fs, char *buf, /* * Fill the packet tail with the tftp informations then retures the lenght */ -int fill_tail(char *dst) +static int fill_tail(char *dst) { char *p = dst; strcpy(p, mode); @@ -703,9 +700,9 @@ struct tftp_options { int str_len; /* string lenght */ int offset; /* offset into socket structre */ }; -struct tftp_options tftp_options[2]; +static struct tftp_options tftp_options[2]; -inline void init_options() +static inline void init_options() { tftp_options[0].str_ptr = tsize_str; tftp_options[0].str_len = tsize_len; @@ -733,7 +730,7 @@ inline void init_options() * ZF set * */ -void pxe_searchdir(char *filename, struct file *file) +static void pxe_searchdir(char *filename, struct file *file) { char *buf = packet_buf; char *p = filename; @@ -1003,7 +1000,7 @@ void pxe_searchdir(char *filename, struct file *file) /* * Store standard filename prefix */ -void get_prefix(void) +static void get_prefix(void) { int len; char *p; @@ -1041,13 +1038,11 @@ void get_prefix(void) * try to load a config file, if found, return 1, or return 0 * */ -int try_load(com32sys_t *regs) +static int try_load(com32sys_t *regs) { extern char KernelName[]; char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]); - get_prefix(); - printf("Trying to load: %-50s ", config_name); pxe_mangle_name(KernelName, config_name); @@ -1067,7 +1062,7 @@ int try_load(com32sys_t *regs) * load configuration file * */ -void pxe_load_config(com32sys_t *regs) +static void pxe_load_config(com32sys_t *regs) { extern void no_config(void); char *cfgprefix = "pxelinux.cfg/"; @@ -1080,6 +1075,7 @@ void pxe_load_config(com32sys_t *regs) int tries = 8; char *last; + get_prefix(); if (DHCPMagic & 0x02) { /* We got a DHCP option, try it first */ if (try_load(regs)) @@ -1149,7 +1145,7 @@ void pxe_load_config(com32sys_t *regs) /* * Generate the botif string, and the hardware-based config string */ -void make_bootif_string(void) +static void make_bootif_string(void) { char *bootif_str = "BOOTIF="; uint8_t *src = &MACType; /* MACType just followed by MAC */ @@ -1179,7 +1175,7 @@ void make_bootif_string(void) ; Assumes CS == DS == ES. ; */ -void genipopt(void) +static void genipopt(void) { char *p = IPOption; int ip_len; @@ -1204,7 +1200,7 @@ void genipopt(void) /* Generate ip= option and print the ip adress */ -void ip_init(void) +static void ip_init(void) { int ip = MyIP; char *myipaddr_msg = "My IP address seems to be "; @@ -1224,7 +1220,7 @@ void ip_init(void) * return 1 for success, 0 for failure. * */ -int is_pxe(char *buf) +static int is_pxe(char *buf) { int i = buf[4]; uint8_t sum = 0; @@ -1245,7 +1241,7 @@ int is_pxe(char *buf) * Just like is_pxe, it checks PXENV+ structure * */ -int is_pxenv(char *buf) +static int is_pxenv(char *buf) { int i = buf[8]; uint8_t sum = 0; @@ -1282,7 +1278,7 @@ int is_pxenv(char *buf) ; ********************************************************************/ -inline int memory_scan(uint16_t seg, int (*func)(char *)) +static inline int memory_scan(uint16_t seg, int (*func)(char *)) { while (seg < 0xA000) { if (func(MK_PTR(seg, 0))) @@ -1292,7 +1288,7 @@ inline int memory_scan(uint16_t seg, int (*func)(char *)) return 0; } -int memory_scan_for_pxe_struct() +static int memory_scan_for_pxe_struct() { extern uint16_t BIOS_fbm; /* Starting segment */ uint16_t seg = BIOS_fbm << (10 - 4); @@ -1300,7 +1296,7 @@ int memory_scan_for_pxe_struct() return memory_scan(seg, is_pxe); } -int memory_scan_for_pxenv_struct() +static int memory_scan_for_pxenv_struct() { uint16_t seg = 0x1000; @@ -1320,7 +1316,7 @@ int memory_scan_for_pxenv_struct() * if if the API version is 2.1 or later * */ -void pxe_init() +static void pxe_init() { char plan = 'A'; uint16_t seg, off; @@ -1378,8 +1374,6 @@ void pxe_init() call16(kaboom, NULL, NULL); have_pxenv: - StructPtr[0] = off; - StructPtr[1] = seg; base = MK_PTR(seg, off); APIVer = *(uint16_t *)(base + 6); printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer); @@ -1413,8 +1407,6 @@ void pxe_init() goto have_entrypoint; have_pxe: - StructPtr[0] = off; - StructPtr[1] = seg; base = MK_PTR(seg, off); data_len = *(uint16_t *)(base + 0x2e); /* UNDI data len */ @@ -1441,7 +1433,7 @@ void pxe_init() * Initialize UDP stack * */ -void udp_init(void) +static void udp_init(void) { int err; static __lowmem struct pxe_udp_open_pkt uo_pkt; @@ -1458,7 +1450,7 @@ void udp_init(void) /* * Network-specific initialization */ -void network_init() +static void network_init() { struct bootp_t *bp = (struct bootp_t *)trackbuf; int pkt_len; @@ -1527,7 +1519,7 @@ void network_init() * Initialize pxe fs * */ -int pxe_fs_init(struct fs_info *fs) +static int pxe_fs_init(struct fs_info *fs) { fs = NULL; /* drop the compile warning message */ diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 6c009582..34121e59 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -186,8 +186,9 @@ PXEStack resd 1 ; Saved stack during PXE call alignb 4 global DHCPMagic, OverLoad, RebootTime, APIVer, RealBaseMem + global StructPtr RebootTime resd 1 ; Reboot timeout, if set by option -StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure +StrucPtr resw 2 ; Pointer to PXENV+ or !PXE structure APIVer resw 1 ; PXE API version found LocalBootType resw 1 ; Local boot return code RealBaseMem resw 1 ; Amount of DOS memory after freeing @@ -204,7 +205,7 @@ BOOTIFStr resb 7 ; Space for "BOOTIF=" MACStr resb 3*(MAC_MAX+1) ; MAC address as a string ; The relative position of these fields matter! - global UUID + global UUID, UUIDType UUIDType resb 1 ; Type byte from DHCP option UUID resb 16 ; UUID, from the PXE stack UUIDNull resb 1 ; dhcp_copyoption zero-terminates -- cgit v1.2.1 From 115baf602655e84d93b6d26feba16a8fadab1292 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 7 Aug 2009 00:07:02 -0700 Subject: Makefile: add back the gpxe directory Add the gpxe directory back into the build. Signed-off-by: H. Peter Anvin --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fb411e7a..de0d2fda 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ BOBJECTS = $(BTARGET) \ # Note: libinstaller is both a BSUBDIR and an ISUBDIR. It contains # files that depend only on the B phase, but may have to be regenerated # for "make installer". -BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump sample \ +BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump gpxe sample \ libinstaller dos win32 ITARGET = IOBJECTS = $(ITARGET) dos/copybs.com \ -- cgit v1.2.1 From 2f90b35a7292515f26f65b947a9c2f065e9f65e4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 7 Aug 2009 00:11:21 -0700 Subject: extlinux: add ext4 support to the installer The filesystem code now supports ext4, so support it in the installer as well. Signed-off-by: H. Peter Anvin --- extlinux/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/extlinux/main.c b/extlinux/main.c index 476d0063..79ead181 100644 --- a/extlinux/main.c +++ b/extlinux/main.c @@ -14,7 +14,7 @@ /* * extlinux.c * - * Install the extlinux boot block on an ext2/3 filesystem + * Install the extlinux boot block on an ext2/3/4 filesystem */ #define _GNU_SOURCE /* Enable everything */ @@ -618,7 +618,7 @@ int install_bootblock(int fd, const char *device) } if (sb.s_magic != EXT2_SUPER_MAGIC) { - fprintf(stderr, "no ext2/ext3 superblock found on %s\n", device); + fprintf(stderr, "no ext2/3/4 superblock found on %s\n", device); return 1; } @@ -766,7 +766,8 @@ static const char *find_device(const char *mtab_file, dev_t dev) while ((mnt = getmntent(mtab))) { if ((!strcmp(mnt->mnt_type, "ext2") || - !strcmp(mnt->mnt_type, "ext3")) && + !strcmp(mnt->mnt_type, "ext3") || + !strcmp(mnt->mnt_type, "ext4")) && !stat(mnt->mnt_fsname, &dst) && dst.st_rdev == dev) { devname = strdup(mnt->mnt_fsname); break; @@ -796,7 +797,7 @@ int install_loader(const char *path, int update_only) } if (sfs.f_type != EXT2_SUPER_MAGIC) { - fprintf(stderr, "%s: not an ext2/ext3 filesystem: %s\n", program, path); + fprintf(stderr, "%s: not an ext2/3/4 filesystem: %s\n", program, path); return 1; } -- cgit v1.2.1 From 608df81932797cb5725d03699fa2a5a3e21bd44d Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 15:51:34 +0800 Subject: Core: get the rid of the ld warnings we extern the SecPerClust from diskstart.inc and used in fat.c, but we also defined another SecPerClust in ext2.c. So we should be better to make more things in _static_, just like hpa told. --- core/ext2.c | 8 ++++---- core/fat.c | 3 ++- core/fs.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index 115ed218..8c019e22 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -28,10 +28,10 @@ extern char Files[]; struct ext2_inode this_inode; struct ext2_super_block sb; -uint16_t ClustByteShift, ClustShift; -uint32_t SecPerClust, ClustSize, ClustMask; -uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; -int DescPerBlock, InodePerBlock; +static uint16_t ClustByteShift, ClustShift; +static uint32_t SecPerClust, ClustSize, ClustMask; +static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; +static int DescPerBlock, InodePerBlock; extern char trackbuf[8192]; char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; diff --git a/core/fat.c b/core/fat.c index ff710636..9b5117e0 100644 --- a/core/fat.c +++ b/core/fat.c @@ -22,6 +22,7 @@ struct open_file_t { extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; extern char trackbuf[8192]; +extern uint8_t SecPerClust; /* the fat bpb data */ @@ -41,7 +42,7 @@ uint8_t DriveNumber; /* BIOS drive number */ uint8_t ClustShift; /* Shift count for sectors/cluster */ uint8_t ClustByteShift; /* Shift count for bytes/cluster */ -int CurrentDir; +static int CurrentDir; int PrevDir; /* used for long name entry */ diff --git a/core/fs.c b/core/fs.c index 89e44ce2..77e18e20 100644 --- a/core/fs.c +++ b/core/fs.c @@ -91,7 +91,7 @@ void fs_init(com32sys_t *regs) /* set up the fs stucture */ fs.fs_name = ops->fs_name; fs.fs_ops = ops; - if (! strcmp(fs.fs_name, "pxe")) + if (!strcmp(fs.fs_name, "pxe")) fs.fs_dev = NULL; else fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, \ -- cgit v1.2.1 From f7e36b4de4387f8662dbb88b550915a021e8f99b Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 16:05:08 +0800 Subject: core:PXELINUX: fix the OACK option parsing bug. the current code can just handle one option beacuse I put the do-while loop in the wrong position. --- core/pxe.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/core/pxe.c b/core/pxe.c index 81d3e235..bda1a542 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -928,20 +928,20 @@ static void pxe_searchdir(char *filename, struct file *file) if (*options == 0) goto done; - dst = src = options; - while (buffersize--) { - if (*src == 0) - break; /* found a final null */ - *dst++ = *src++ | 0x20; - if (!buffersize) - goto done; /* found no final null */ - } - - /* - * Parse option pointed to by options; guaranteed to be null-terminated - */ - p = options; do { + dst = src = options; + while (buffersize--) { + if (*src == 0) + break; /* found a final null */ + *dst++ = *src++ | 0x20; + if (!buffersize) + goto done; /* found no final null */ + } + + /* + * Parse option pointed to by options; guaranteed to be null-terminated + */ + p = options; tftp_opt = tftp_options; for (i = 0; i < tftp_opts; i++) { if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) -- cgit v1.2.1 From 1f02a2352cc0af8416b911c613f8c77144f72d63 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 16:36:26 +0800 Subject: Core: add _static_ statement to all fs This well let me far away from some werid trouble Signed-off-by: Liu Aleaxander --- core/ext2.c | 50 ++++++++++++++++++++++++-------------------------- core/fat.c | 52 ++++++++++++++++++++++++++-------------------------- core/iso9660.c | 34 +++++++++++++++++----------------- core/pxe.c | 30 +++++++++++++++--------------- 4 files changed, 82 insertions(+), 84 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index 8c019e22..ebb34554 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -23,20 +23,18 @@ struct open_file_t { uint16_t file_in_off; uint16_t file_mode; }; - extern char Files[]; -struct ext2_inode this_inode; -struct ext2_super_block sb; +extern char trackbuf[]; +static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; + +static struct ext2_inode this_inode; +static struct ext2_super_block sb; static uint16_t ClustByteShift, ClustShift; static uint32_t SecPerClust, ClustSize, ClustMask; static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; static int DescPerBlock, InodePerBlock; -extern char trackbuf[8192]; -char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; - - /** * strecpy: @@ -46,7 +44,7 @@ char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; * well, in Syslinux, strcpy() will advance both the dst and src string pointer. * */ -int strecpy(char *dst, char *src, char *end) +static int strecpy(char *dst, char *src, char *end) { while (*src != '\0') *dst++ = *src++; @@ -67,7 +65,7 @@ int strecpy(char *dst, char *src, char *end) * @return: if successful return the file pointer, or return NULL * */ -struct open_file_t *allocate_file() +static struct open_file_t *allocate_file() { struct open_file_t *file = (struct open_file_t *)Files; int i = 0; @@ -90,7 +88,7 @@ struct open_file_t *allocate_file() * @param: file, the file structure we want deallocate * */ -void close_file(struct open_file_t *file) +static void close_file(struct open_file_t *file) { if (file) file->file_bytesleft = 0; @@ -105,7 +103,7 @@ void close_file(struct open_file_t *file) * any whitespace. * */ -void ext2_mangle_name(char *dst, char *src) +static void ext2_mangle_name(char *dst, char *src) { char *p = dst; int i = FILENAME_MAX -1; @@ -147,7 +145,7 @@ void ext2_mangle_name(char *dst, char *src) * @return: the pointer of the group's descriptor * */ -struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) +static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) { block_t block_num; uint32_t offset; @@ -178,7 +176,7 @@ struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) * @param: offset, same as block * */ -void read_inode(struct fs_info *fs, uint32_t inode_offset, +static void read_inode(struct fs_info *fs, uint32_t inode_offset, struct ext2_inode *dst, struct ext2_group_desc *desc, block_t *block, uint32_t *offset) { @@ -210,7 +208,7 @@ void read_inode(struct fs_info *fs, uint32_t inode_offset, * the first 128 bytes of the inode, stores in ThisInode * */ -struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) +static struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) { struct open_file_t *file; struct ext2_group_desc *desc; @@ -248,7 +246,7 @@ struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file -struct ext4_extent_header * +static struct ext4_extent_header * ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) { struct ext4_extent_idx *index; @@ -282,7 +280,7 @@ ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block } /* handle the ext4 extents to get the phsical block number */ -block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) +static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) { struct ext4_extent_header *leaf; struct ext4_extent *ext; @@ -326,7 +324,7 @@ block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *i * * @return: the physic block number */ -block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode) +static block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode) { struct cache_struct *cs; @@ -389,7 +387,7 @@ block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode * * * @return: physic sector number */ -sector_t linsector(struct fs_info *fs, uint32_t lin_sector) +static sector_t linsector(struct fs_info *fs, uint32_t lin_sector) { uint32_t block = lin_sector >> ClustShift; block_t ret; @@ -430,7 +428,7 @@ static inline int ext2_match_entry (const char * const name, /* * p is at least 6 bytes before the end of page */ -inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) +static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) { return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); } @@ -443,7 +441,7 @@ inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) * n ext2 block pointer, i.e. anything *except the superblock * */ -void getlinsec_ext(struct fs_info *fs, char *buf, +static void getlinsec_ext(struct fs_info *fs, char *buf, sector_t sector, int sector_cnt) { int ext_cnt = 0; @@ -480,7 +478,7 @@ void getlinsec_ext(struct fs_info *fs, char *buf, * @return: ECX(of regs), number of bytes read * */ -uint32_t ext2_getfssec(struct fs_info *fs, char *buf, +static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, void *open_file, int sectors, int *have_more) { int sector_left, next_sector, sector_idx; @@ -542,7 +540,7 @@ uint32_t ext2_getfssec(struct fs_info *fs, char *buf, * find a dir entry, if find return it or return NULL * */ -struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) +static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) { int have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; @@ -580,7 +578,7 @@ struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *fi } -char* do_symlink(struct fs_info *fs, struct open_file_t *file, +static char* do_symlink(struct fs_info *fs, struct open_file_t *file, uint32_t file_len, char *filename) { int flag, have_more; @@ -633,7 +631,7 @@ char* do_symlink(struct fs_info *fs, struct open_file_t *file, * @out : file lenght in bytes, stores in eax * */ -void ext2_searchdir(char *filename, struct file *file) +static void ext2_searchdir(char *filename, struct file *file) { extern int CurrentDir; @@ -726,7 +724,7 @@ void ext2_searchdir(char *filename, struct file *file) } -void ext2_load_config(com32sys_t *regs) +static void ext2_load_config(com32sys_t *regs) { char *config_name = "extlinux.conf"; com32sys_t out_regs; @@ -751,7 +749,7 @@ void ext2_load_config(com32sys_t *regs) /** * init. the fs meta data, return the block size bits. */ -int ext2_fs_init(struct fs_info *fs) +static int ext2_fs_init(struct fs_info *fs) { struct disk *disk = fs->fs_dev->disk; #if 0 diff --git a/core/fat.c b/core/fat.c index 9b5117e0..1a21cc70 100644 --- a/core/fat.c +++ b/core/fat.c @@ -26,33 +26,33 @@ extern uint8_t SecPerClust; /* the fat bpb data */ -struct fat_bpb fat; -int FATType = 0; +static struct fat_bpb fat; +static int FATType = 0; /* generic information about FAT fs */ -sector_t FAT; /* Location of (first) FAT */ -sector_t RootDirArea; /* Location of root directory area */ -sector_t RootDir; /* Location of root directory proper */ -sector_t DataArea; /* Location of data area */ -uint32_t TotalSectors; /* Total number of sectors */ -uint32_t ClustSize; /* Bytes/cluster */ -uint32_t ClustMask; /* Sector/cluster - 1 */ -uint8_t CopySuper; /* Distinguish .bs versus .bss */ -uint8_t DriveNumber; /* BIOS drive number */ -uint8_t ClustShift; /* Shift count for sectors/cluster */ -uint8_t ClustByteShift; /* Shift count for bytes/cluster */ +static sector_t FAT; /* Location of (first) FAT */ +static sector_t RootDirArea; /* Location of root directory area */ +static sector_t RootDir; /* Location of root directory proper */ +static sector_t DataArea; /* Location of data area */ +static uint32_t TotalSectors; /* Total number of sectors */ +static uint32_t ClustSize; /* Bytes/cluster */ +static uint32_t ClustMask; /* Sector/cluster - 1 */ +static uint8_t CopySuper; /* Distinguish .bs versus .bss */ +static uint8_t DriveNumber; /* BIOS drive number */ +static uint8_t ClustShift; /* Shift count for sectors/cluster */ +static uint8_t ClustByteShift; /* Shift count for bytes/cluster */ static int CurrentDir; -int PrevDir; +static int PrevDir; /* used for long name entry */ -char MangleBuf[12]; -char entry_name[14]; +static char MangleBuf[12]; +static char entry_name[14]; /* try with the biggest long name */ -char long_name[0x40 * 13]; -char *NameStart; -int NameLen; +static char long_name[0x40 * 13]; +static char *NameStart; +static int NameLen; /* do this for readdir, because it called from asm and don't know the fs structure */ static struct fs_info *this_fs = NULL; @@ -135,7 +135,7 @@ void close_dir(struct fat_dir_entry *dir) * check for a particular sector in the FAT cache. * */ -struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) +static struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) { return get_cache_block(fs->fs_dev, FAT + sector); } @@ -327,7 +327,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, * @return: number of bytes read * */ -uint32_t vfat_getfssec(struct fs_info *fs, char *buf, +static uint32_t vfat_getfssec(struct fs_info *fs, char *buf, void *open_file, int sectors, int *have_more) { uint32_t bytes_read = sectors << SECTOR_SHIFT; @@ -356,7 +356,7 @@ uint32_t vfat_getfssec(struct fs_info *fs, char *buf, * ends on encountering any whitespace. * */ -void vfat_mangle_name(char *dst, char *src) +static void vfat_mangle_name(char *dst, char *src) { char *p = dst; int i = FILENAME_MAX -1; @@ -654,7 +654,7 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, * @return: return the file structure on successful, or NULL. * */ -void vfat_searchdir(char *filename, struct file *file) +static void vfat_searchdir(char *filename, struct file *file) { sector_t dir_sector; uint32_t file_len = 0; @@ -729,7 +729,7 @@ void vfat_searchdir(char *filename, struct file *file) * @param: file * */ -void readdir(com32sys_t *regs)/* +static void readdir(com32sys_t *regs)/* struct fs_info *fs, struct open_file_t* dir_file, char* filename, uint32_t *file_len, uint8_t *attr) */ @@ -853,7 +853,7 @@ void readdir(com32sys_t *regs)/* regs->eax.l = 0; } -void vfat_load_config(com32sys_t *regs) +static void vfat_load_config(com32sys_t *regs) { char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; @@ -902,7 +902,7 @@ static inline void bsr(uint8_t *res, int num) } /* init. the fs meta data, return the block size in bits */ -int vfat_fs_init(struct fs_info *fs) +static int vfat_fs_init(struct fs_info *fs) { int sectors_per_fat; uint32_t clust_num; diff --git a/core/iso9660.c b/core/iso9660.c index 1ce710f7..54fbff06 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -30,23 +30,23 @@ struct dir_t { uint32_t dir_len; /* Length in bytes */ uint32_t dir_clust; /* Length in clusters */ }; -struct dir_t RootDir; -struct dir_t CurrentDir; +static struct dir_t RootDir; +static struct dir_t CurrentDir; extern char trackbuf[TRACKBUF_SIZE]; -uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; -uint16_t BufSafeBytes = TRACKBUF_SIZE; +static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; +static uint16_t BufSafeBytes = TRACKBUF_SIZE; -char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ -char *ISOFileNameEnd = &ISOFileName[64]; +static char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ +static char *ISOFileNameEnd = &ISOFileName[64]; /* * use to store the block shift, since we treat the hd-mode as 512 bytes * sector size, 2048 bytes block size. we still treat the cdrom as 2048 * bytes sector size and also the block size. */ -int block_shift; +static int block_shift; /** * allocate_file: @@ -54,7 +54,7 @@ int block_shift; * allocate a file structure * */ -struct open_file_t *allocate_file() +static struct open_file_t *allocate_file() { struct open_file_t *file; int i = 0; @@ -76,13 +76,13 @@ struct open_file_t *allocate_file() * Deallocates a file structure * */ -void close_file(struct open_file_t *file) +static void close_file(struct open_file_t *file) { if (file) file->file_sector = 0; } -void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) +static void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) { com32sys_t regs; //static __lowmem char low_buf[65536]; @@ -124,7 +124,7 @@ void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) * a bit of an easier job. * */ -void iso_mangle_name(char *dst, char *src) +static void iso_mangle_name(char *dst, char *src) { char *p = dst; int i = FILENAME_MAX - 1; @@ -171,7 +171,7 @@ void iso_mangle_name(char *dst, char *src) * @return: 1 on match, or 0. * */ -int iso_compare_names(char *de_name, int *len, char *file_name) +static int iso_compare_names(char *de_name, int *len, char *file_name) { char *p = ISOFileName; char c1, c2; @@ -244,7 +244,7 @@ static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, in * @param: have_more, to indicate if we have reach the end of the file * */ -uint32_t iso_getfssec(struct fs_info *fs, char *buf, +static uint32_t iso_getfssec(struct fs_info *fs, char *buf, void *open_file, int sectors, int *have_more) { uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; @@ -282,7 +282,7 @@ uint32_t iso_getfssec(struct fs_info *fs, char *buf, * res will return the result. * */ -int do_search_dir(struct fs_info *fs, struct dir_t *dir, +static int do_search_dir(struct fs_info *fs, struct dir_t *dir, char *name, uint32_t *file_len, void **res) { struct open_file_t *file; @@ -423,7 +423,7 @@ int do_search_dir(struct fs_info *fs, struct dir_t *dir, * can read a diretory.(Just thought of mine, liu) * */ -void iso_searchdir(char *filename, struct file *file) +static void iso_searchdir(char *filename, struct file *file) { struct open_file_t *open_file = NULL; struct dir_t *dir; @@ -488,7 +488,7 @@ void iso_searchdir(char *filename, struct file *file) #endif } -void iso_load_config(com32sys_t *regs) +static void iso_load_config(com32sys_t *regs) { char *config_name = "isolinux.cfg"; com32sys_t out_regs; @@ -501,7 +501,7 @@ void iso_load_config(com32sys_t *regs) } -int iso_fs_init(struct fs_info *fs) +static int iso_fs_init(struct fs_info *fs) { char *iso_dir; char *boot_dir = "/boot/isolinux"; diff --git a/core/pxe.c b/core/pxe.c index bda1a542..b73a8fb4 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -15,34 +15,34 @@ #define GPXE 1 #define USE_PXE_PROVIDED_STACK 0 -char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; -char *err_pxefailed = "PXE API call failed, error "; -char *err_udpinit = "Failed to initialize UDP stack\n"; -char *err_noconfig = "Unable to locate configuration file\n"; -char *err_damage = "TFTP server sent an incomprehesible reply\n"; +static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; +static char *err_pxefailed = "PXE API call failed, error "; +static char *err_udpinit = "Failed to initialize UDP stack\n"; +static char *err_noconfig = "Unable to locate configuration file\n"; +static char *err_damage = "TFTP server sent an incomprehesible reply\n"; -char *tftpprefix_msg = "TFTP prefix: "; -char *get_packet_msg = "Getting cached packet "; +static char *tftpprefix_msg = "TFTP prefix: "; +static char *get_packet_msg = "Getting cached packet "; -uint16_t NextSocket = 49152; +static uint16_t NextSocket = 49152; static int has_gpxe; +static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; int HaveUUID = 0; -uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; static const uint8_t TimeoutTable[] = { 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 }; -char *mode = "octet"; -char *tsize_str = "tsize"; -int tsize_len = 6; /* We should include the final null here */ +static char *mode = "octet"; +static char *tsize_str = "tsize"; +static int tsize_len = 6; /* We should include the final null here */ -char *blksize_str = "blksize"; -int blksize_len = 8; +static char *blksize_str = "blksize"; +static int blksize_len = 8; -char *asciidec = "1408"; +static char *asciidec = "1408"; -- cgit v1.2.1 From 99756b937dc3d1f811ec5dc5eb6328b9c3a73708 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 16:53:24 +0800 Subject: Core: move the comman externs to core.h the trackbuf and Files are all uesed in all the four fs, so it would be nice to put the externs in core.h instead in each c file of the four fs Signed-off-by: Liu Aleaxander --- core/ext2.c | 3 +-- core/fat.c | 2 -- core/include/core.h | 5 ++--- core/iso9660.c | 3 --- core/ldlinux.asm | 1 + 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index ebb34554..153f368e 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -23,8 +23,7 @@ struct open_file_t { uint16_t file_in_off; uint16_t file_mode; }; -extern char Files[]; -extern char trackbuf[]; + static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; static struct ext2_inode this_inode; diff --git a/core/fat.c b/core/fat.c index 1a21cc70..f6d8d9f5 100644 --- a/core/fat.c +++ b/core/fat.c @@ -20,8 +20,6 @@ struct open_file_t { uint32_t file_left; /* number of sectors left */ }; -extern char Files[MAX_OPEN * sizeof(struct open_file_t)]; -extern char trackbuf[8192]; extern uint8_t SecPerClust; diff --git a/core/include/core.h b/core/include/core.h index 069354bb..236f8c01 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -6,7 +6,8 @@ extern char core_xfer_buf[65536]; extern char core_cache_buf[65536]; - +extern char trackbuf[]; +extern char Files[]; extern char CurrentDirName[]; extern char ConfigName[]; @@ -50,11 +51,9 @@ extern uint8_t MACType; /* MAC address type */ extern uint8_t DHCPMagic; extern uint8_t OverLoad; extern uint32_t RebootTime; - /* TFTP ACK packet */ extern uint16_t ack_packet_buf[]; -extern char trackbuf[]; extern char BootFile[]; extern char PathPrefix[]; extern char LocalDomain[]; diff --git a/core/iso9660.c b/core/iso9660.c index 54fbff06..2c7e559a 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -23,7 +23,6 @@ struct open_file_t { uint32_t file_bytesleft; uint32_t file_left; }; -extern char Files[]; struct dir_t { uint32_t dir_lba; /* Directory start (LBA) */ @@ -33,8 +32,6 @@ struct dir_t { static struct dir_t RootDir; static struct dir_t CurrentDir; - -extern char trackbuf[TRACKBUF_SIZE]; static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; static uint16_t BufSafeBytes = TRACKBUF_SIZE; diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 5c449044..d834af20 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -74,6 +74,7 @@ vk_end: equ $ ; Should be <= vk_size ; Memory below this point is reserved for the BIOS and the MBR ; section .earlybss + global trackbuf trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h -- cgit v1.2.1 From de0b71af1e9d141c3234aa10376d5bcf79e47c55 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 17:03:56 +0800 Subject: Core:EXTLINUX: fix the bug of open_file_t struct in extlinux The size of open_file_t structure in extlinux is twice than in the others derivatiives. So we should cut the MAX_OPEN to half. Signed-off-by: Liu Aleaxander --- core/ext2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/ext2.c b/core/ext2.c index 153f368e..965f1b43 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -8,7 +8,8 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_OPEN_LG2 6 +/* The size of open_file_t in extlinux is double of in others */ +#define MAX_OPEN_LG2 (6 - 1) #define MAX_OPEN (1 << MAX_OPEN_LG2) #define MAX_SYMLINKS 64 #define SYMLINK_SECTORS 2 @@ -22,6 +23,7 @@ struct open_file_t { sector_t file_in_sec; /* Sector where inode lives */ uint16_t file_in_off; uint16_t file_mode; + uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ }; static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; -- cgit v1.2.1 From 363bb72fd5fa66efeadb03e123ecd99b1a381126 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 17:39:43 +0800 Subject: Core: unmangle_name converted Signed-off-by: Liu Aleaxander --- core/ext2.c | 16 +++++++++++++++- core/extern.inc | 5 +---- core/extlinux.asm | 23 ++++------------------- core/fat.c | 15 ++++++++++++++- core/fs.c | 12 +++++++++--- core/include/fs.h | 2 +- core/iso9660.c | 15 ++++++++++++++- core/isolinux.asm | 15 --------------- core/ldlinux.asm | 17 ----------------- core/parseconfig.inc | 2 +- core/pxe.c | 24 +++++++++++++++++++++++- core/pxelinux.asm | 30 ------------------------------ core/runkernel.inc | 2 +- core/ui.inc | 4 ++-- 14 files changed, 85 insertions(+), 97 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index 965f1b43..66255561 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -136,6 +136,20 @@ static void ext2_mangle_name(char *dst, char *src) *dst++ = '\0'; } +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int ext2_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + + /** * get_group_desc: * @@ -782,6 +796,6 @@ const struct fs_ops ext2_fs_ops = { .searchdir = ext2_searchdir, .getfssec = ext2_getfssec, .mangle_name = ext2_mangle_name, - .unmangle_name = NULL, + .unmangle_name = ext2_unmangle_name, .load_config = ext2_load_config }; diff --git a/core/extern.inc b/core/extern.inc index 026b8c1b..4c7b149a 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -14,14 +14,11 @@ ; fs.c extern fs_init, searchdir, getfssec, mangle_name, load_config + extern unmangle_name %if IS_SYSLINUX ; fat.c extern alloc_fill_dir, readdir - -%elif IS_PXELINUX - ; pxe.c - extern gendotquad %endif %endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 27fbc3e6..d5b9e016 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -32,7 +32,8 @@ retry_count equ 16 ; How patient are we with the disk? %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) +; The size of open_file_t in extlinux is double of in others +MAX_OPEN_LG2 equ (6 - 1) ; log2(Max number of open files) MAX_OPEN equ (1 << MAX_OPEN_LG2) SECTOR_SHIFT equ 9 @@ -71,9 +72,9 @@ trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h section .bss16 - alignb 16 + alignb 32 global Files -Files resb MAX_OPEN*16 ; 16 == open_file_t_size +Files resb MAX_OPEN*32 ; 32 == open_file_t_size ; ; Common bootstrap code for disk-based derivatives @@ -119,22 +120,6 @@ Files resb MAX_OPEN*16 ; 16 == open_file_t_size ; %include "ui.inc" - -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: call strcpy - dec di ; Point to final null byte - ret - ; ; ; kaboom2: once everything is loaded, replace the part of kaboom diff --git a/core/fat.c b/core/fat.c index f6d8d9f5..9fb0f3c5 100644 --- a/core/fat.c +++ b/core/fat.c @@ -390,6 +390,19 @@ static void vfat_mangle_name(char *dst, char *src) } +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int vfat_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + /** * mangle_dos_name: * @@ -941,6 +954,6 @@ const struct fs_ops vfat_fs_ops = { .searchdir = vfat_searchdir, .getfssec = vfat_getfssec, .mangle_name = vfat_mangle_name, - .unmangle_name = NULL, + .unmangle_name = vfat_unmangle_name, .load_config = vfat_load_config }; diff --git a/core/fs.c b/core/fs.c index 77e18e20..03abfd6f 100644 --- a/core/fs.c +++ b/core/fs.c @@ -23,12 +23,18 @@ void mangle_name(com32sys_t *regs) this_fs->fs_ops->mangle_name(dst, src); } -/**** + void unmangle_name(com32sys_t *regs) { - + char *src = MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = MK_PTR(regs->es, regs->edi.w[0]); + int len; + + len = this_fs->fs_ops->unmangle_name(dst, src); + /* Update the di register to point to the last null char */ + regs->edi.w[0] += len; } -****/ + void getfssec(com32sys_t *regs) { diff --git a/core/include/fs.h b/core/include/fs.h index 163808e8..ca4e281a 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -28,7 +28,7 @@ struct fs_ops { void (*searchdir)(char *, struct file *); uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); void (*mangle_name)(char *, char *); - void (*unmangle_name)(void); + int (*unmangle_name)(char *, char *); void (*load_config)(com32sys_t *); }; diff --git a/core/iso9660.c b/core/iso9660.c index 2c7e559a..03beb466 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -156,6 +156,19 @@ static void iso_mangle_name(char *dst, char *src) } +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int iso_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + /** * compare the names si and di and report if they are * equal from an ISO 9600 perspective. @@ -567,6 +580,6 @@ const struct fs_ops iso_fs_ops = { .searchdir = iso_searchdir, .getfssec = iso_getfssec, .mangle_name = iso_mangle_name, - .unmangle_name = NULL, + .unmangle_name = iso_unmangle_name, .load_config = iso_load_config }; diff --git a/core/isolinux.asm b/core/isolinux.asm index 41777d79..21e74740 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -1329,21 +1329,6 @@ is_disk_image: .done_sector: ret -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: call strcpy - dec di ; Point to final null byte - ret - ; ----------------------------------------------------------------------------- ; Common modules diff --git a/core/ldlinux.asm b/core/ldlinux.asm index d834af20..b2c4070a 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -165,23 +165,6 @@ kaboom2: -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; NOTE: A 13-byte buffer is mandatory, even if the string is -; known to be shorter. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: call strcpy - dec di ; Point to final null byte - ret - ; ----------------------------------------------------------------------------- diff --git a/core/parseconfig.inc b/core/parseconfig.inc index 37091c99..af7d514f 100644 --- a/core/parseconfig.inc +++ b/core/parseconfig.inc @@ -409,7 +409,7 @@ commit_vk: mov cx,7 ; "initrd=" rep movsb mov si,InitRD - call unmangle_name + pm_call unmangle_name mov al,' ' stosb diff --git a/core/pxe.c b/core/pxe.c index b73a8fb4..aea1691f 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -497,6 +497,28 @@ static void pxe_mangle_name(char *dst, char *src) #endif } + +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int pxe_unmangle_name(char *dst, char *src) +{ + uint32_t ip = *(uint32_t *)src; + int ip_len = 0; + + if (ip != 0 && ip != -1) { + ip_len = gendotquad(dst, *(uint32_t *)src); + dst += ip_len; + } + src += 4;; + strcpy(dst, src); + + return strlen(src) + ip_len; +} /* * @@ -1538,6 +1560,6 @@ const struct fs_ops pxe_fs_ops = { .searchdir = pxe_searchdir, .getfssec = pxe_getfssec, .mangle_name = pxe_mangle_name, - .unmangle_name = NULL, + .unmangle_name = pxe_unmangle_name, .load_config = pxe_load_config }; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 34121e59..b226a316 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -433,36 +433,6 @@ kaboom: jmp 0F000h:0FFF0h ; Reset vector address -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; -; NOTE: The output buffer needs to be able to hold an -; expanded IP address. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: - push eax - lodsd - and eax,eax - jz .noip - cmp eax,-1 - jz .noip ; URL - pm_call gendotquad - mov ax,'::' - stosw -.noip: - call strcpy - dec di ; Point to final null byte - pop eax - ret - ; ; pxenv ; diff --git a/core/runkernel.inc b/core/runkernel.inc index f44e8b35..68ab9fac 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -585,7 +585,7 @@ loadinitrd: push edi mov si,InitRD mov di,InitRDCName - call unmangle_name ; Create human-readable name + pm_call unmangle_name ; Create human-readable name sub di,InitRDCName mov [InitRDCNameLen],di mov di,InitRD diff --git a/core/ui.inc b/core/ui.inc index 508a6f28..87d0c647 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -472,7 +472,7 @@ bad_kernel: mov si,KernelName mov di,KernelCName push di - call unmangle_name ; Get human form + pm_call unmangle_name ; Get human form mov si,err_notfound ; Complain about missing kernel call writestr pop si ; KernelCName @@ -601,7 +601,7 @@ kernel_good: mov si,KernelName mov di,KernelCName - call unmangle_name + pm_call unmangle_name sub di,KernelCName mov [KernelCNameLen],di -- cgit v1.2.1 From a0a603145eaf41c0650dd9c80002375c8b2cb04f Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 8 Aug 2009 17:49:48 +0800 Subject: Core: code-clean removes the unused variables and functions Signed-off-by: Liu Aleaxander --- core/fat.c | 2 -- core/iso9660.c | 31 +------------------------------ core/pxe.c | 5 ++--- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/core/fat.c b/core/fat.c index 9fb0f3c5..c84d6c92 100644 --- a/core/fat.c +++ b/core/fat.c @@ -35,8 +35,6 @@ static sector_t DataArea; /* Location of data area */ static uint32_t TotalSectors; /* Total number of sectors */ static uint32_t ClustSize; /* Bytes/cluster */ static uint32_t ClustMask; /* Sector/cluster - 1 */ -static uint8_t CopySuper; /* Distinguish .bs versus .bss */ -static uint8_t DriveNumber; /* BIOS drive number */ static uint8_t ClustShift; /* Shift count for sectors/cluster */ static uint8_t ClustByteShift; /* Shift count for bytes/cluster */ diff --git a/core/iso9660.c b/core/iso9660.c index 03beb466..61179c3f 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -33,7 +33,6 @@ static struct dir_t RootDir; static struct dir_t CurrentDir; static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; -static uint16_t BufSafeBytes = TRACKBUF_SIZE; static char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ static char *ISOFileNameEnd = &ISOFileName[64]; @@ -79,34 +78,6 @@ static void close_file(struct open_file_t *file) file->file_sector = 0; } -static void getlinsec_cdrom(char *buf, sector_t sector_num, int sectors) -{ - com32sys_t regs; - //static __lowmem char low_buf[65536]; - /* for safe, we use buf + (sectors << SECTOR_SHIFT) here */ - int high_addr = (buf + (sectors << ISO_SECTOR_SHIFT)) > (char *)0x100000; - - memset(®s, 0, sizeof regs); - regs.eax.l = sector_num; - regs.ebp.l = sectors; - - if (high_addr) { - regs.es = SEG(core_xfer_buf); - regs.ebx.w[0] = OFFS(core_xfer_buf); - } else { - regs.es = SEG(buf); - regs.ebx.w[0] = OFFS(buf); - } - - call16(getlinsec, ®s, NULL); - - if (high_addr) - memcpy(buf, core_xfer_buf, sectors << ISO_SECTOR_SHIFT); -} - - - - /** * mangle_name: * @@ -437,7 +408,7 @@ static void iso_searchdir(char *filename, struct file *file) { struct open_file_t *open_file = NULL; struct dir_t *dir; - uint32_t file_len; + uint32_t file_len = 0; int ret; void *res; diff --git a/core/pxe.c b/core/pxe.c index aea1691f..12c3113e 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -18,8 +18,6 @@ static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; static char *err_pxefailed = "PXE API call failed, error "; static char *err_udpinit = "Failed to initialize UDP stack\n"; -static char *err_noconfig = "Unable to locate configuration file\n"; -static char *err_damage = "TFTP server sent an incomprehesible reply\n"; static char *tftpprefix_msg = "TFTP prefix: "; static char *get_packet_msg = "Getting cached packet "; @@ -1159,7 +1157,8 @@ static void pxe_load_config(com32sys_t *regs) if (try_load(regs)) return; - /* call16(no_config, NULL, NULL); */ + printf("Unable to locate configuration file\n"); + call16(kaboom, NULL, NULL); } -- cgit v1.2.1 From cb76438e0029540a870213fd001c01e77ae7e892 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 9 Aug 2009 14:54:08 +0800 Subject: pxe: fix OACK packet handling The current code only works iff the tsize option is set. This patch fixes the handling of the OACK packet and makes the code work with all combinations of the tsize and blksize options. Signed-off-by: Sebastian Herbszt --- core/pxe.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/pxe.c b/core/pxe.c index 12c3113e..7cf5cc1a 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -933,8 +933,10 @@ static void pxe_searchdir(char *filename, struct file *file) * Now we need to parse the OACK packet to get the transfer * and packet sizes. */ - if (!buffersize) + if (!buffersize) { + filesize = -1; goto done; /* No options acked */ + } /* * If we find an option which starts with a NUL byte, @@ -964,8 +966,10 @@ static void pxe_searchdir(char *filename, struct file *file) p = options; tftp_opt = tftp_options; for (i = 0; i < tftp_opts; i++) { - if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) + if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) { + options += tftp_opt->str_len; break; + } tftp_opt++; } if (i == tftp_opts) @@ -974,11 +978,12 @@ static void pxe_searchdir(char *filename, struct file *file) p += tftp_opt->str_len; /* get the address of the filed that we want to write on */ - data_ptr = (uint32_t *)((char *)file + tftp_opt->offset); + data_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset); *data_ptr = 0; /* do convert a number-string to decimal number, just like atoi */ while (buffersize--) { + options++; if (*p == 0) break; /* found a final null */ if (*p > '9') -- cgit v1.2.1 From cf68539184ac53fb8a29905e87f5f44f24dbcb37 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 9 Aug 2009 15:00:48 +0800 Subject: Core:pxelinux: improves the tftp options parsing Signed-off-by: Liu Aleaxander --- core/pxe.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/core/pxe.c b/core/pxe.c index 7cf5cc1a..96c91ec5 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -949,9 +949,10 @@ static void pxe_searchdir(char *filename, struct file *file) options = packet_buf + 2; if (*options == 0) goto done; - + p = options; + do { - dst = src = options; + dst = src = p; while (buffersize--) { if (*src == 0) break; /* found a final null */ @@ -963,13 +964,10 @@ static void pxe_searchdir(char *filename, struct file *file) /* * Parse option pointed to by options; guaranteed to be null-terminated */ - p = options; tftp_opt = tftp_options; for (i = 0; i < tftp_opts; i++) { - if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) { - options += tftp_opt->str_len; + if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) break; - } tftp_opt++; } if (i == tftp_opts) @@ -983,14 +981,13 @@ static void pxe_searchdir(char *filename, struct file *file) /* do convert a number-string to decimal number, just like atoi */ while (buffersize--) { - options++; if (*p == 0) break; /* found a final null */ if (*p > '9') goto err_reply; /* Not a decimal digit */ *data_ptr = *data_ptr * 10 + *p++ - '0'; } - + p++; }while (buffersize); } else { -- cgit v1.2.1 From 3ec18540fcb8db13ebef5995d834e840fcaac211 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 9 Aug 2009 15:52:26 -0700 Subject: zlib: kill gzio.c Remove gzio.c, which is a zlib-specific stdio-like interface. We implement this in the actual filesystem layer, which is much cleaner. Signed-off-by: H. Peter Anvin --- com32/lib/Makefile | 2 +- com32/lib/zlib/gzio.c | 1017 ------------------------------------------------- 2 files changed, 1 insertion(+), 1018 deletions(-) delete mode 100644 com32/lib/zlib/gzio.c diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 5e0e15ae..2bcffe80 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -63,7 +63,7 @@ LIBOBJS = \ pci/readb.o pci/readw.o pci/readl.o pci/readbios.o \ pci/writeb.o pci/writew.o pci/writel.o pci/writebios.o \ \ - zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/gzio.o \ + zlib/adler32.o zlib/compress.o zlib/crc32.o \ zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o \ zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o \ \ diff --git a/com32/lib/zlib/gzio.c b/com32/lib/zlib/gzio.c deleted file mode 100644 index 9bc8d34e..00000000 --- a/com32/lib/zlib/gzio.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* gzio.c -- IO on .gz files - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. - */ - - -#include - -#include "zutil.h" - -#ifdef NO_DEFLATE /* for compatiblity with old definition */ -# define NO_GZCOMPRESS -#endif - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -#ifndef Z_BUFSIZE -# ifdef MAXSEG_64K -# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ -# else -# define Z_BUFSIZE 16384 -# endif -#endif -#ifndef Z_PRINTF_BUFSIZE -# define Z_PRINTF_BUFSIZE 4096 -#endif - -#ifdef __MVS__ -# pragma map (fdopen , "\174\174FDOPEN") - FILE *fdopen(int, const char *); -#endif - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern void free OF((voidpf ptr)); -#endif - -#define ALLOC(size) malloc(size) -#define TRYFREE(p) {if (p) free(p);} - -static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -typedef struct gz_stream { - z_stream stream; - int z_err; /* error code for last stream operation */ - int z_eof; /* set if end of input file */ - FILE *file; /* .gz file */ - Byte *inbuf; /* input buffer */ - Byte *outbuf; /* output buffer */ - uLong crc; /* crc32 of uncompressed data */ - char *msg; /* error message */ - char *path; /* path name for debugging only */ - int transparent; /* 1 if input file is not a .gz file */ - char mode; /* 'w' or 'r' */ - z_off_t start; /* start of compressed data in file (header skipped) */ - z_off_t in; /* bytes into deflate or inflate */ - z_off_t out; /* bytes out of deflate or inflate */ - int back; /* one character push-back */ - int last; /* true if push-back is last character */ -} gz_stream; - - -local gzFile gz_open OF((const char *path, const char *mode, int fd)); -local int do_flush OF((gzFile file, int flush)); -local int get_byte OF((gz_stream *s)); -local void check_header OF((gz_stream *s)); -local int destroy OF((gz_stream *s)); -local void putLong OF((FILE *file, uLong x)); -local uLong getLong OF((gz_stream *s)); - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb"). The file is given either by file descriptor - or path name (if fd == -1). - gz_open returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). -*/ -local gzFile gz_open (path, mode, fd) - const char *path; - const char *mode; - int fd; -{ - int err; - int level = Z_DEFAULT_COMPRESSION; /* compression level */ - int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ - char *p = (char*)mode; - gz_stream *s; - char fmode[80]; /* copy of mode, without the compression level */ - char *m = fmode; - - if (!path || !mode) return Z_NULL; - - s = (gz_stream *)ALLOC(sizeof(gz_stream)); - if (!s) return Z_NULL; - - s->stream.zalloc = (alloc_func)0; - s->stream.zfree = (free_func)0; - s->stream.opaque = (voidpf)0; - s->stream.next_in = s->inbuf = Z_NULL; - s->stream.next_out = s->outbuf = Z_NULL; - s->stream.avail_in = s->stream.avail_out = 0; - s->file = NULL; - s->z_err = Z_OK; - s->z_eof = 0; - s->in = 0; - s->out = 0; - s->back = EOF; - s->crc = crc32(0L, Z_NULL, 0); - s->msg = NULL; - s->transparent = 0; - - s->path = (char*)ALLOC(strlen(path)+1); - if (s->path == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - strcpy(s->path, path); /* do this early for debugging */ - - s->mode = '\0'; - do { - if (*p == 'r') s->mode = 'r'; - if (*p == 'w' || *p == 'a') s->mode = 'w'; - if (*p >= '0' && *p <= '9') { - level = *p - '0'; - } else if (*p == 'f') { - strategy = Z_FILTERED; - } else if (*p == 'h') { - strategy = Z_HUFFMAN_ONLY; - } else if (*p == 'R') { - strategy = Z_RLE; - } else { - *m++ = *p; /* copy the mode */ - } - } while (*p++ && m != fmode + sizeof(fmode)); - if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateInit2(&(s->stream), level, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); - /* windowBits is passed < 0 to suppress zlib header */ - - s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); -#endif - if (err != Z_OK || s->outbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } else { - s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); - - err = inflateInit2(&(s->stream), -MAX_WBITS); - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are - * present after the compressed stream. - */ - if (err != Z_OK || s->inbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } - s->stream.avail_out = Z_BUFSIZE; - - errno = 0; - s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); - - if (s->file == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - if (s->mode == 'w') { - /* Write a very simple .gz header: - */ - fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], - Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - s->start = 10L; - /* We use 10L instead of ftell(s->file) to because ftell causes an - * fflush on some systems. This version of the library doesn't use - * start anyway in write mode, so this initialization is not - * necessary. - */ - } else { - check_header(s); /* skip the .gz header */ - s->start = ftell(s->file) - s->stream.avail_in; - } - - return (gzFile)s; -} - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. -*/ -gzFile ZEXPORT gzopen (path, mode) - const char *path; - const char *mode; -{ - return gz_open (path, mode, -1); -} - -/* =========================================================================== - Associate a gzFile with the file descriptor fd. fd is not dup'ed here - to mimic the behavio(u)r of fdopen. -*/ -gzFile ZEXPORT gzdopen (fd, mode) - int fd; - const char *mode; -{ - char name[20]; - - if (fd < 0) return (gzFile)Z_NULL; - sprintf(name, "", fd); /* for debugging */ - - return gz_open (name, mode, fd); -} - -/* =========================================================================== - * Update the compression level and strategy - */ -int ZEXPORT gzsetparams (file, level, strategy) - gzFile file; - int level; - int strategy; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - /* Make room to allow flushing */ - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - } - s->stream.avail_out = Z_BUFSIZE; - } - - return deflateParams (&(s->stream), level, strategy); -} - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ -local int get_byte(s) - gz_stream *s; -{ - if (s->z_eof) return EOF; - if (s->stream.avail_in == 0) { - errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - /* klibc hack */ - if (errno) s->z_err = Z_ERRNO; - return EOF; - } - s->stream.next_in = s->inbuf; - } - s->stream.avail_in--; - return *(s->stream.next_in)++; -} - -/* =========================================================================== - Check the gzip header of a gz_stream opened for reading. Set the stream - mode to transparent if the gzip magic header is not present; set s->err - to Z_DATA_ERROR if the magic header is present but the rest of the header - is incorrect. - IN assertion: the stream s has already been created sucessfully; - s->stream.avail_in is zero for the first time, but may be non-zero - for concatenated .gz files. -*/ -local void check_header(s) - gz_stream *s; -{ - int method; /* method byte */ - int flags; /* flags byte */ - uInt len; - int c; - - /* Assure two bytes in the buffer so we can peek ahead -- handle case - where first byte of header is at the end of the buffer after the last - gzip segment */ - len = s->stream.avail_in; - if (len < 2) { - if (len) s->inbuf[0] = s->stream.next_in[0]; - errno = 0; - len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); - /* klibc hack */ - if (len == 0 && errno) s->z_err = Z_ERRNO; - s->stream.avail_in += len; - s->stream.next_in = s->inbuf; - if (s->stream.avail_in < 2) { - s->transparent = s->stream.avail_in; - return; - } - } - - /* Peek ahead to check the gzip magic header */ - if (s->stream.next_in[0] != gz_magic[0] || - s->stream.next_in[1] != gz_magic[1]) { - s->transparent = 1; - return; - } - s->stream.avail_in -= 2; - s->stream.next_in += 2; - - /* Check the rest of the gzip header */ - method = get_byte(s); - flags = get_byte(s); - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return; - } - - /* Discard time, xflags and OS code: */ - for (len = 0; len < 6; len++) (void)get_byte(s); - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(s); - len += ((uInt)get_byte(s))<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(s) != EOF) ; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(s); - } - s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; -} - - /* =========================================================================== - * Cleanup then free the given gz_stream. Return a zlib error code. - Try freeing in the reverse order of allocations. - */ -local int destroy (s) - gz_stream *s; -{ - int err = Z_OK; - - if (!s) return Z_STREAM_ERROR; - - TRYFREE(s->msg); - - if (s->stream.state != NULL) { - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateEnd(&(s->stream)); -#endif - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } - } - if (s->file != NULL && fclose(s->file)) { -#ifdef ESPIPE - if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ -#endif - err = Z_ERRNO; - } - if (s->z_err < 0) err = s->z_err; - - TRYFREE(s->inbuf); - TRYFREE(s->outbuf); - TRYFREE(s->path); - TRYFREE(s); - return err; -} - -/* =========================================================================== - Reads the given number of uncompressed bytes from the compressed file. - gzread returns the number of bytes actually read (0 for end of file). -*/ -int ZEXPORT gzread (file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - Bytef *start = (Bytef*)buf; /* starting point for crc computation */ - Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ - - if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; - - if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; - if (s->z_err == Z_STREAM_END) return 0; /* EOF */ - - next_out = (Byte*)buf; - s->stream.next_out = (Bytef*)buf; - s->stream.avail_out = len; - - if (s->stream.avail_out && s->back != EOF) { - *next_out++ = s->back; - s->stream.next_out++; - s->stream.avail_out--; - s->back = EOF; - s->out++; - if (s->last) { - s->z_err = Z_STREAM_END; - return 1; - } - } - - while (s->stream.avail_out != 0) { - - if (s->transparent) { - /* Copy first the lookahead bytes: */ - uInt n = s->stream.avail_in; - if (n > s->stream.avail_out) n = s->stream.avail_out; - if (n > 0) { - zmemcpy(s->stream.next_out, s->stream.next_in, n); - next_out += n; - s->stream.next_out = next_out; - s->stream.next_in += n; - s->stream.avail_out -= n; - s->stream.avail_in -= n; - } - if (s->stream.avail_out > 0) { - s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, - s->file); - } - len -= s->stream.avail_out; - s->in += len; - s->out += len; - if (len == 0) s->z_eof = 1; - return (int)len; - } - if (s->stream.avail_in == 0 && !s->z_eof) { - - errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (errno) { - s->z_err = Z_ERRNO; - break; - } - } - s->stream.next_in = s->inbuf; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = inflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - - if (s->z_err == Z_STREAM_END) { - /* Check CRC and original size */ - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - start = s->stream.next_out; - - if (getLong(s) != s->crc) { - s->z_err = Z_DATA_ERROR; - } else { - (void)getLong(s); - /* The uncompressed length returned by above getlong() may be - * different from s->out in case of concatenated .gz files. - * Check for such files: - */ - check_header(s); - if (s->z_err == Z_OK) { - inflateReset(&(s->stream)); - s->crc = crc32(0L, Z_NULL, 0); - } - } - } - if (s->z_err != Z_OK || s->z_eof) break; - } - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - - return (int)(len - s->stream.avail_out); -} - - -/* =========================================================================== - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ -int ZEXPORT gzgetc(file) - gzFile file; -{ - unsigned char c; - - return gzread(file, &c, 1) == 1 ? c : -1; -} - - -/* =========================================================================== - Push one byte back onto the stream. -*/ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; - s->back = c; - s->out--; - s->last = (s->z_err == Z_STREAM_END); - if (s->last) s->z_err = Z_OK; - s->z_eof = 0; - return c; -} - - -/* =========================================================================== - Reads bytes from the compressed file until len-1 characters are - read, or a newline character is read and transferred to buf, or an - end-of-file condition is encountered. The string is then terminated - with a null character. - gzgets returns buf, or Z_NULL in case of error. - - The current implementation is not optimized at all. -*/ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ - char *b = buf; - if (buf == Z_NULL || len <= 0) return Z_NULL; - - while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; - *buf = '\0'; - return b == buf && len > 0 ? Z_NULL : b; -} - - -#ifndef NO_GZCOMPRESS -/* =========================================================================== - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of bytes actually written (0 in case of error). -*/ -int ZEXPORT gzwrite (file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.next_in = (Bytef*)buf; - s->stream.avail_in = len; - - while (s->stream.avail_in != 0) { - - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - break; - } - s->stream.avail_out = Z_BUFSIZE; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - if (s->z_err != Z_OK) break; - } - s->crc = crc32(s->crc, (const Bytef *)buf, len); - - return (int)(len - s->stream.avail_in); -} - - -/* =========================================================================== - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ -#ifdef STDC -#include - -int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) -{ - char buf[Z_PRINTF_BUFSIZE]; - va_list va; - int len; - - buf[sizeof(buf) - 1] = 0; - va_start(va, format); -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf(buf, format, va); - va_end(va); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = vsprintf(buf, format, va); - va_end(va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf(buf, sizeof(buf), format, va); - va_end(va); - len = strlen(buf); -# else - len = vsnprintf(buf, sizeof(buf), format, va); - va_end(va); -# endif -#endif - if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, (unsigned)len); -} -#else /* not ANSI C */ - -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - char buf[Z_PRINTF_BUFSIZE]; - int len; - - buf[sizeof(buf) - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(buf); -# else - len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#endif - if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, len); -} -#endif - -/* =========================================================================== - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ - unsigned char cc = (unsigned char) c; /* required for big endian systems */ - - return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; -} - - -/* =========================================================================== - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ - return gzwrite(file, (char*)s, (unsigned)strlen(s)); -} - - -/* =========================================================================== - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. -*/ -local int do_flush (file, flush) - gzFile file; - int flush; -{ - uInt len; - int done = 0; - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.avail_in = 0; /* should be zero already anyway */ - - for (;;) { - len = Z_BUFSIZE - s->stream.avail_out; - - if (len != 0) { - if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { - s->z_err = Z_ERRNO; - return Z_ERRNO; - } - s->stream.next_out = s->outbuf; - s->stream.avail_out = Z_BUFSIZE; - } - if (done) break; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), flush); - s->out -= s->stream.avail_out; - - /* Ignore the second of two consecutive flushes: */ - if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; - - /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: - */ - done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - - if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; - } - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} - -int ZEXPORT gzflush (file, flush) - gzFile file; - int flush; -{ - gz_stream *s = (gz_stream*)file; - int err = do_flush (file, flush); - - if (err) return err; - fflush(s->file); - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} -#endif /* NO_GZCOMPRESS */ - -/* =========================================================================== - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error. - SEEK_END is not implemented, returns error. - In this version of the library, gzseek can be extremely slow. -*/ -#if 0 /* COM32: seek not supported */ - -z_off_t ZEXPORT gzseek (file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || whence == SEEK_END || - s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { - return -1L; - } - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return -1L; -#else - if (whence == SEEK_SET) { - offset -= s->in; - } - if (offset < 0) return -1L; - - /* At this point, offset is the number of zero bytes to write. */ - if (s->inbuf == Z_NULL) { - s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ - if (s->inbuf == Z_NULL) return -1L; - zmemzero(s->inbuf, Z_BUFSIZE); - } - while (offset > 0) { - uInt size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (uInt)offset; - - size = gzwrite(file, s->inbuf, size); - if (size == 0) return -1L; - - offset -= size; - } - return s->in; -#endif - } - /* Rest of function is for reading only */ - - /* compute absolute position */ - if (whence == SEEK_CUR) { - offset += s->out; - } - if (offset < 0) return -1L; - - if (s->transparent) { - /* map to fseek */ - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; - - s->in = s->out = offset; - return offset; - } - - /* For a negative seek, rewind and use positive seek */ - if (offset >= s->out) { - offset -= s->out; - } else if (gzrewind(file) < 0) { - return -1L; - } - /* offset is now the number of bytes to skip. */ - - if (offset != 0 && s->outbuf == Z_NULL) { - s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); - if (s->outbuf == Z_NULL) return -1L; - } - if (offset && s->back != EOF) { - s->back = EOF; - s->out++; - offset--; - if (s->last) s->z_err = Z_STREAM_END; - } - while (offset > 0) { - int size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (int)offset; - - size = gzread(file, s->outbuf, (uInt)size); - if (size <= 0) return -1L; - offset -= size; - } - return s->out; -} - -#endif - -/* =========================================================================== - Rewinds input file. -*/ -#if 0 /* COM32: seek not supported */ - -int ZEXPORT gzrewind (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return -1; - - s->z_err = Z_OK; - s->z_eof = 0; - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - s->crc = crc32(0L, Z_NULL, 0); - if (!s->transparent) (void)inflateReset(&s->stream); - s->in = 0; - s->out = 0; - return fseek(s->file, s->start, SEEK_SET); -} -#endif - -/* =========================================================================== - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. -*/ -#if 0 /* COM32: seek not supported */ - -z_off_t ZEXPORT gztell (file) - gzFile file; -{ - return gzseek(file, 0L, SEEK_CUR); -} -#endif - -/* =========================================================================== - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ -int ZEXPORT gzeof (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - /* With concatenated compressed files that can have embedded - * crc trailers, z_eof is no longer the only/best indicator of EOF - * on a gz_stream. Handle end-of-stream error explicitly here. - */ - if (s == NULL || s->mode != 'r') return 0; - if (s->z_eof) return 1; - return s->z_err == Z_STREAM_END; -} - -/* =========================================================================== - Outputs a long in LSB order to the given file -*/ -local void putLong (file, x) - FILE *file; - uLong x; -{ - int n; - for (n = 0; n < 4; n++) { - fputc((int)(x & 0xff), file); - x >>= 8; - } -} - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets z_err in case - of error. -*/ -local uLong getLong (s) - gz_stream *s; -{ - uLong x = (uLong)get_byte(s); - int c; - - x += ((uLong)get_byte(s))<<8; - x += ((uLong)get_byte(s))<<16; - c = get_byte(s); - if (c == EOF) s->z_err = Z_DATA_ERROR; - x += ((uLong)c)<<24; - return x; -} - -/* =========================================================================== - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. -*/ -int ZEXPORT gzclose (file) - gzFile file; -{ - int err; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return Z_STREAM_ERROR; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return Z_STREAM_ERROR; -#else - err = do_flush (file, Z_FINISH); - if (err != Z_OK) return destroy((gz_stream*)file); - - putLong (s->file, s->crc); - putLong (s->file, (uLong)(s->in & 0xffffffff)); -#endif - } - return destroy((gz_stream*)file); -} - -/* =========================================================================== - Returns the error message for the last error which occured on the - given compressed file. errnum is set to zlib error number. If an - error occured in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ -const char * ZEXPORT gzerror (file, errnum) - gzFile file; - int *errnum; -{ - char *m; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) { - *errnum = Z_STREAM_ERROR; - return (const char*)ERR_MSG(Z_STREAM_ERROR); - } - *errnum = s->z_err; - if (*errnum == Z_OK) return (const char*)""; - - m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); - - if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); - - TRYFREE(s->msg); - s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); - if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); - strcpy(s->msg, s->path); - strcat(s->msg, ": "); - strcat(s->msg, m); - return (const char*)s->msg; -} - -/* =========================================================================== - Clear the error and end-of-file flags, and do the same for the real file. -*/ -void ZEXPORT gzclearerr (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return; - if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; - s->z_eof = 0; - /* klibc hack */ - /* clearerr(s->file); */ -} -- cgit v1.2.1 From d74cbcd018244a834c60842b16ee18966a6ec020 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 9 Aug 2009 19:47:24 -0700 Subject: core: merge ldlinux.asm and extlinux.asm ldlinux.asm and extlinux.asm are by now extremely similar. Merge them. Signed-off-by: H. Peter Anvin --- core/comboot.inc | 10 +-- core/diskfs.inc | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ core/extlinux.asm | 190 +------------------------------------------------ core/ldlinux.asm | 204 +---------------------------------------------------- 4 files changed, 210 insertions(+), 401 deletions(-) create mode 100644 core/diskfs.inc diff --git a/core/comboot.inc b/core/comboot.inc index 7c2b6e66..da3c2399 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -942,15 +942,7 @@ comapi_readdir equ comapi_err ; ; INT 22h AX=0022h Close directory ; -%if IS_SYSLINUX -comapi_closedir: - mov si,P_SI - call close_dir - clc - ret -%else -comapi_closedir equ comapi_err -%endif +comapi_closedir equ comapi_close ; ; INT 22h AX=0023h Query shuffler size diff --git a/core/diskfs.inc b/core/diskfs.inc new file mode 100644 index 00000000..603ada9b --- /dev/null +++ b/core/diskfs.inc @@ -0,0 +1,207 @@ +; -*- fundamental -*- (asm-mode sucks) +; ----------------------------------------------------------------------- +; +; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +; Copyright 2009 Intel Corporation; author: H. Peter Anvin +; +; 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, Inc., 51 Franklin St, Fifth Floor, +; Boston MA 02110-1301, USA; either version 2 of the License, or +; (at your option) any later version; incorporated herein by reference. +; +; ----------------------------------------------------------------------- + +; +; diskfs.inc +; +; Common code for conventional disk-based filesystems +; + +; +; Some semi-configurable constants... change on your own risk. +; +FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size +NULLFILE equ 0 ; Null character == empty filename +NULLOFFSET equ 0 ; Position in which to look +retry_count equ 16 ; How patient are we with the disk? +%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top +LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with + +MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) +MAX_OPEN equ (1 << MAX_OPEN_LG2) + +SECTOR_SHIFT equ 9 +SECTOR_SIZE equ (1 << SECTOR_SHIFT) + +; +; The following structure is used for "virtual kernels"; i.e. LILO-style +; option labels. The options we permit here are `kernel' and `append +; Since there is no room in the bottom 64K for all of these, we +; stick them in high memory and copy them down before we need them. +; + struc vkernel +vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!** +vk_rname: resb FILENAME_MAX ; Real name +vk_appendlen: resw 1 +vk_type: resb 1 ; Type of file + alignb 4 +vk_append: resb max_cmd_len+1 ; Command line + alignb 4 +vk_end: equ $ ; Should be <= vk_size + endstruc + + + +; --------------------------------------------------------------------------- +; BEGIN CODE +; --------------------------------------------------------------------------- + +; +; Memory below this point is reserved for the BIOS and the MBR +; + section .earlybss + global trackbuf +trackbufsize equ 8192 +trackbuf resb trackbufsize ; Track buffer goes here + ; ends at 2800h + + section .bss16 + alignb 16 + global Files +Files resb MAX_OPEN*16 ; 16 == open_file_t_size + +; +; Common bootstrap code for disk-based derivatives +; +%include "diskstart.inc" + + +; +; Now, everything is "up and running"... patch kaboom for more +; verbosity and using the full screen system +; + ; E9 = JMP NEAR + mov di,kaboom.patch + mov al,0e9h + stosb + mov ax,kaboom2-2 + sub ax,di + stosw + +; +; Now we're all set to start with our *real* business. First load the +; configuration file (if any) and parse it. +; +; In previous versions I avoided using 32-bit registers because of a +; rumour some BIOSes clobbered the upper half of 32-bit registers at +; random. I figure, though, that if there are any of those still left +; they probably won't be trying to install Linux on them... +; +; The code is still ripe with 16-bitisms, though. Not worth the hassle +; to take'm out. In fact, we may want to put them back if we're going +; to boot ELKS at some point. +; + +; +; Load configuration file +; + pm_call load_config + jz no_config_file + +; +; Now we have the config file open. Parse the config file and +; run the user interface. +; +%include "ui.inc" + + +; +; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled +; filename to the conventional representation. This is needed +; for the BOOT_IMAGE= parameter for the kernel. +; +; DS:SI -> input mangled file name +; ES:DI -> output buffer +; +; On return, DI points to the first byte after the output name, +; which is set to a null byte. +; +unmangle_name: call strcpy + dec di ; Point to final null byte + ret + +; +; +; kaboom2: once everything is loaded, replace the part of kaboom +; starting with "kaboom.patch" with this part + +kaboom2: + mov si,err_bootfailed + call writestr + cmp byte [kaboom.again+1],18h ; INT 18h version? + je .int18 + call getchar + call vgaclearmode + int 19h ; And try once more to boot... +.norge: jmp short .norge ; If int 19h returned; this is the end +.int18: + call vgaclearmode + int 18h +.noreg: jmp short .noreg ; Nynorsk + +; ----------------------------------------------------------------------------- +; Common modules +; ----------------------------------------------------------------------------- + +%include "common.inc" ; Universal modules +%include "plaincon.inc" ; writechr +%include "writestr.inc" ; String output +%include "writehex.inc" ; Hexadecimal output +%include "localboot.inc" ; Disk-based local boot + +; ----------------------------------------------------------------------------- +; Begin data section +; ----------------------------------------------------------------------------- + + section .data16 +copyright_str db ' Copyright (C) 1994-' + asciidec YEAR + db ' H. Peter Anvin et al', CR, LF, 0 +err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' + db 'a key to continue.', CR, LF, 0 + +; +; Config file keyword table +; +%include "keywords.inc" + +; +; Extensions to search for (in *forward* order). +; + alignz 4 +exten_table: db '.cbt' ; COMBOOT (specific) +%if IS_SYSLINUX + db '.bss' ; Boot sector (add superblock) +%endif + db '.bs', 0 ; Boot sector + db '.com' ; COMBOOT (same as DOS) + db '.c32' ; COM32 +exten_table_end: + dd 0, 0 ; Need 8 null bytes here + +; +; Misc initialized (data) variables +; +%ifdef debug ; This code for debugging only +debug_magic dw 0D00Dh ; Debug code sentinel +%endif + + alignz 4 +BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf +BufSafeBytes dw trackbufsize ; = how many bytes? +%ifndef DEPEND +%if ( trackbufsize % SECTOR_SIZE ) != 0 +%error trackbufsize must be a multiple of SECTOR_SIZE +%endif +%endif diff --git a/core/extlinux.asm b/core/extlinux.asm index 27fbc3e6..2a5526b8 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -23,194 +23,6 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ extlinux_id -; NASM 0.98.38 croaks if these are equ's rather than macros... FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) -FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size -NULLFILE equ 0 ; Null character == empty filename -NULLOFFSET equ 0 ; Position in which to look -retry_count equ 16 ; How patient are we with the disk? -%assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top -LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) -MAX_OPEN equ (1 << MAX_OPEN_LG2) - -SECTOR_SHIFT equ 9 -SECTOR_SIZE equ (1 << SECTOR_SHIFT) - -; -; The following structure is used for "virtual kernels"; i.e. LILO-style -; option labels. The options we permit here are `kernel' and `append -; Since there is no room in the bottom 64K for all of these, we -; stick them in high memory and copy them down before we need them. -; - struc vkernel -vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!** -vk_rname: resb FILENAME_MAX ; Real name -vk_appendlen: resw 1 -vk_type: resb 1 ; Type of file - alignb 4 -vk_append: resb max_cmd_len+1 ; Command line - alignb 4 -vk_end: equ $ ; Should be <= vk_size - endstruc - - - -; --------------------------------------------------------------------------- -; BEGIN CODE -; --------------------------------------------------------------------------- - -; -; Memory below this point is reserved for the BIOS and the MBR -; - section .earlybss - global trackbuf -trackbufsize equ 8192 -trackbuf resb trackbufsize ; Track buffer goes here - ; ends at 2800h - - section .bss16 - alignb 16 - global Files -Files resb MAX_OPEN*16 ; 16 == open_file_t_size - -; -; Common bootstrap code for disk-based derivatives -; -%include "diskstart.inc" - - -; -; Now, everything is "up and running"... patch kaboom for more -; verbosity and using the full screen system -; - ; E9 = JMP NEAR - mov di,kaboom.patch - mov al,0e9h - stosb - mov ax,kaboom2-2 - sub ax,di - stosw - -; -; Now we're all set to start with our *real* business. First load the -; configuration file (if any) and parse it. -; -; In previous versions I avoided using 32-bit registers because of a -; rumour some BIOSes clobbered the upper half of 32-bit registers at -; random. I figure, though, that if there are any of those still left -; they probably won't be trying to install Linux on them... -; -; The code is still ripe with 16-bitisms, though. Not worth the hassle -; to take'm out. In fact, we may want to put them back if we're going -; to boot ELKS at some point. -; - -; -; Load configuration file -; - pm_call load_config - jz no_config_file - -; -; Now we have the config file open. Parse the config file and -; run the user interface. -; -%include "ui.inc" - - -; -; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled -; filename to the conventional representation. This is needed -; for the BOOT_IMAGE= parameter for the kernel. -; -; DS:SI -> input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: call strcpy - dec di ; Point to final null byte - ret - -; -; -; kaboom2: once everything is loaded, replace the part of kaboom -; starting with "kaboom.patch" with this part - -kaboom2: - mov si,err_bootfailed - call writestr - cmp byte [kaboom.again+1],18h ; INT 18h version? - je .int18 - call getchar - call vgaclearmode - int 19h ; And try once more to boot... -.norge: jmp short .norge ; If int 19h returned; this is the end -.int18: - call vgaclearmode - int 18h -.noreg: jmp short .noreg ; Nynorsk - - - -build_curdir_str: - ret - -; ----------------------------------------------------------------------------- -; Common modules -; ----------------------------------------------------------------------------- - -%include "common.inc" ; Universal modules -%include "plaincon.inc" ; writechr -%include "writestr.inc" ; String output -%include "writehex.inc" ; Hexadecimal output -%include "strecpy.inc" ; strcpy with end pointer check -%include "localboot.inc" ; Disk-based local boot - -; ----------------------------------------------------------------------------- -; Begin data section -; ----------------------------------------------------------------------------- - - section .data16 -copyright_str db ' Copyright (C) 1994-' - asciidec YEAR - db ' H. Peter Anvin et al', CR, LF, 0 -err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' - db 'a key to continue.', CR, LF, 0 -config_name db 'extlinux.conf',0 ; Unmangled form - -; -; Config file keyword table -; -%include "keywords.inc" - -; -; Extensions to search for (in *forward* order). -; - alignz 4 -exten_table: db '.cbt' ; COMBOOT (specific) - db '.img' ; Disk image - db '.bs', 0 ; Boot sector - db '.com' ; COMBOOT (same as DOS) - db '.c32' ; COM32 -exten_table_end: - dd 0, 0 ; Need 8 null bytes here - -; -; Misc initialized (data) variables -; -%ifdef debug ; This code for debugging only -debug_magic dw 0D00Dh ; Debug code sentinel -%endif - - alignz 4 -BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf -BufSafeBytes dw trackbufsize ; = how many bytes? -%ifndef DEPEND -%if ( trackbufsize % SECTOR_SIZE ) != 0 -%error trackbufsize must be a multiple of SECTOR_SIZE -%endif -%endif +%include "diskfs.inc" diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 5c449044..183262a3 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -22,9 +22,7 @@ ; ; **************************************************************************** -%ifndef IS_MDSLINUX %define IS_SYSLINUX 1 -%endif %include "head.inc" ; @@ -32,205 +30,5 @@ ; my_id equ syslinux_id FILENAME_MAX_LG2 equ 6 ; log2(Max filename size Including final null) -FILENAME_MAX equ (1< input mangled file name -; ES:DI -> output buffer -; -; On return, DI points to the first byte after the output name, -; which is set to a null byte. -; -unmangle_name: call strcpy - dec di ; Point to final null byte - ret - - - -; ----------------------------------------------------------------------------- -; Common modules -; ----------------------------------------------------------------------------- - -%include "common.inc" ; Universal modules -%include "plaincon.inc" ; writechr -%include "writestr.inc" ; String output -%include "writehex.inc" ; Hexadecimal output -%include "localboot.inc" ; Disk-based local boot - -; ----------------------------------------------------------------------------- -; Begin data section -; ----------------------------------------------------------------------------- - - section .data16 -copyright_str db ' Copyright (C) 1994-' - asciidec YEAR - db ' H. Peter Anvin et al', CR, LF, 0 -err_bootfailed db CR, LF, 'Boot failed: please change disks and press ' - db 'a key to continue.', CR, LF, 0 -; -; Config file keyword table -; -%include "keywords.inc" - -; -; Extensions to search for (in *forward* order). -; -exten_table: db '.cbt' ; COMBOOT (specific) - db '.bss' ; Boot Sector (add superblock) - db '.bs', 0 ; Boot Sector - db '.com' ; COMBOOT (same as DOS) - db '.c32' ; COM32 -exten_table_end: - dd 0, 0 ; Need 8 null bytes here - -; -; Misc initialized (data) variables -; -%ifdef debug ; This code for debugging only -debug_magic dw 0D00Dh ; Debug code sentinel -%endif - - alignz 4 -BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf -BufSafeBytes dw trackbufsize ; = how many bytes? -%ifndef DEPEND -%if ( trackbufsize % SECTOR_SIZE ) != 0 -%error trackbufsize must be a multiple of SECTOR_SIZE -%endif -%endif +%include "diskfs.inc" -- cgit v1.2.1 From 77632adf09dbf7d4d72ce3763566f1dade3bb0e2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 11:18:12 -0700 Subject: zlib: remove unused sample programs Remove unused sample programs (example.c, minigzip.c); we don' tuse them and they are just noise. Signed-off-by: H. Peter Anvin --- com32/lib/zlib/example.c | 566 ---------------------------------------------- com32/lib/zlib/minigzip.c | 322 -------------------------- 2 files changed, 888 deletions(-) delete mode 100644 com32/lib/zlib/example.c delete mode 100644 com32/lib/zlib/minigzip.c diff --git a/com32/lib/zlib/example.c b/com32/lib/zlib/example.c deleted file mode 100644 index 14614b74..00000000 --- a/com32/lib/zlib/example.c +++ /dev/null @@ -1,566 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - - -#include -#include "zlib.h" - -#ifdef STDC -# include -# include -#else - extern void exit OF((int)); -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -const char dictionary[] = "hello"; -uLong dictId; /* Adler32 value of the dictionary */ - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = (uLong)strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - int len = (int)strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - strcpy((char*)uncompr, "garbage"); - - if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - if (gzungetc(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - - gzclose(file); -#endif -} - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uLong len = (uLong)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uInt len = (uInt)strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (Bytef*)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/com32/lib/zlib/minigzip.c b/com32/lib/zlib/minigzip.c deleted file mode 100644 index 077e2e12..00000000 --- a/com32/lib/zlib/minigzip.c +++ /dev/null @@ -1,322 +0,0 @@ -/* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * minigzip is a minimal implementation of the gzip utility. This is - * only an example of using zlib and isn't meant to replace the - * full-featured gzip. No attempt is made to deal with file systems - * limiting names to 14 or 8+3 characters, etc... Error checking is - * very limited. So use minigzip only for testing; use gzip for the - * real thing. On MSDOS, use only on file names without extension - * or in pipe mode. - */ - - -#include -#include "zlib.h" - -#ifdef STDC -# include -# include -#else - extern void exit OF((int)); -#endif - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#ifdef VMS -# define unlink delete -# define GZ_SUFFIX "-gz" -#endif -#ifdef RISCOS -# define unlink remove -# define GZ_SUFFIX "-gz" -# define fileno(file) file->__file -#endif -#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fileno */ -#endif - -#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); -#endif - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#define BUFLEN 16384 -#define MAX_NAME_LEN 1024 - -#ifdef MAXSEG_64K -# define local static - /* Needed for systems with limitation on stack size. */ -#else -# define local -#endif - -char *prog; - -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -#ifdef USE_MMAP -int gz_compress_mmap OF((FILE *in, gzFile out)); -#endif -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file, char *mode)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Display error message and exit - */ -void error(msg) - const char *msg; -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - errno = 0; - len = (int)fread(buf, 1, sizeof(buf), in); - if (!len && errno) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(in, out) - FILE *in; - gzFile out; -{ - int len; - int err; - int ifd = fileno(in); - caddr_t buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (caddr_t)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = gzwrite(out, (char *)buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(gzerror(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ - local char buf[BUFLEN]; - int len; - int err; - - for (;;) { - len = gzread(in, buf, sizeof(buf)); - if (len < 0) error (gzerror(in, &err)); - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - error("failed fwrite"); - } - } - if (fclose(out)) error("failed fclose"); - - if (gzclose(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(file, mode) - char *file; - char *mode; -{ - local char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - strcpy(outfile, file); - strcat(outfile, GZ_SUFFIX); - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = gzopen(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(file) - char *file; -{ - local char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - uInt len = (uInt)strlen(file); - - strcpy(buf, file); - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; - strcat(infile, GZ_SUFFIX); - } - in = gzopen(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - unlink(infile); -} - - -/* =========================================================================== - * Usage: minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...] - * -d : decompress - * -f : compress with Z_FILTERED - * -h : compress with Z_HUFFMAN_ONLY - * -r : compress with Z_RLE - * -1 to -9 : compression level - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - int uncompr = 0; - gzFile file; - char outmode[20]; - - strcpy(outmode, "wb6 "); - - prog = argv[0]; - argc--, argv++; - - while (argc > 0) { - if (strcmp(*argv, "-d") == 0) - uncompr = 1; - else if (strcmp(*argv, "-f") == 0) - outmode[3] = 'f'; - else if (strcmp(*argv, "-h") == 0) - outmode[3] = 'h'; - else if (strcmp(*argv, "-r") == 0) - outmode[3] = 'R'; - else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && - (*argv)[2] == 0) - outmode[2] = (*argv)[1]; - else - break; - argc--, argv++; - } - if (argc == 0) { - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (uncompr) { - file = gzdopen(fileno(stdin), "rb"); - if (file == NULL) error("can't gzdopen stdin"); - gz_uncompress(file, stdout); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - gz_compress(stdin, file); - } - } else { - do { - if (uncompr) { - file_uncompress(*argv); - } else { - file_compress(*argv, outmode); - } - } while (argv++, --argc); - } - return 0; -} -- cgit v1.2.1 From f87413e6b7a60e9cfc086232953b7f32a4d1c5f2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 14:27:21 -0700 Subject: core/diskstart.inc: make the root filesystem a configurable Instead of using conditional compilation, just set the root filesystem type in the assembly stub. Signed-off-by: H. Peter Anvin --- core/diskstart.inc | 24 +++++------------------- core/extlinux.asm | 3 +++ core/ldlinux.asm | 3 +++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/core/diskstart.inc b/core/diskstart.inc index c160c8d5..36d513ed 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -722,26 +722,12 @@ expand_super: pushad -%if IS_PXELINUX - extern pxe_fs_ops - mov eax,pxe_fs_ops -%else - %if IS_EXTLINUX - extern ext2_fs_ops - mov eax,ext2_fs_ops - %elif IS_SYSLINUX - extern vfat_fs_ops - mov eax,vfat_fs_ops - %elif IS_ISOLINUX - extern iso_fs_ops - mov eax,iso_fs_ops - %endif - mov dl,[DriveNumber] - mov dh,0 ; we are boot from disk not CDROM - mov ecx,[bsHidden] - mov ebx,[bsHidden+4] + mov eax,ROOT_FS_OPS + movzx dx,byte [DriveNumber] + ; DH = 0: we are boot from disk not CDROM + mov ecx,[bsHidden] + mov ebx,[bsHidden+4] mov si,[bsHeads] mov di,[bsSecPerTrack] -%endif pm_call fs_init popad diff --git a/core/extlinux.asm b/core/extlinux.asm index 2a5526b8..0048cc1b 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -25,4 +25,7 @@ my_id equ extlinux_id FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) + extern ext2_fs_ops +ROOT_FS_OPS equ ext2_fs_ops + %include "diskfs.inc" diff --git a/core/ldlinux.asm b/core/ldlinux.asm index 183262a3..b8b86b2e 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -31,4 +31,7 @@ my_id equ syslinux_id FILENAME_MAX_LG2 equ 6 ; log2(Max filename size Including final null) + extern vfat_fs_ops +ROOT_FS_OPS equ vfat_fs_ops + %include "diskfs.inc" -- cgit v1.2.1 From 62bfc2dc87cfd752856e2b5aeecc790255143523 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 16:42:53 -0700 Subject: ext2: fix missing (void), use standard form for loop Use the standard form for a for loop; add missing (void). Signed-off-by: H. Peter Anvin --- core/ext2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/ext2.c b/core/ext2.c index 787a6f18..b57f1e70 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -68,15 +68,15 @@ static int strecpy(char *dst, char *src, char *end) * @return: if successful return the file pointer, or return NULL * */ -static struct open_file_t *allocate_file() +static struct open_file_t *allocate_file(void) { - struct open_file_t *file = (struct open_file_t *)Files; - int i = 0; + struct open_file_t *file = Files; + int i; - for (; i < MAX_OPEN; i ++) { + for (i = 0; i < MAX_OPEN; i++) { if (file->file_bytesleft == 0) /* found it */ return file; - file ++; + file++; } return NULL; /* not found */ -- cgit v1.2.1 From b88ef2b963207617b81ecf3475d418f7c25d0518 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 16:45:44 -0700 Subject: core: add missing (void), drop casts for Files[], cleanups Add missing (void) on no-argument functions, drop casts for Files (it's now a properly typed array), clean up loop forms. Signed-off-by: H. Peter Anvin --- core/iso9660.c | 11 +++++------ core/pxe.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/iso9660.c b/core/iso9660.c index b1fe64eb..c7e4041b 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -52,16 +52,15 @@ static int block_shift; * allocate a file structure * */ -static struct open_file_t *allocate_file() +static struct open_file_t *allocate_file(void) { - struct open_file_t *file; - int i = 0; + struct open_file_t *file = Files; + int i; - file = (struct open_file_t *)Files; - for (; i < MAX_OPEN; i ++ ) { + for (i = 0; i < MAX_OPEN; i++) { if ( file->file_sector == 0 ) /* found it */ return file; - file ++; + file++; } return NULL; /* not found */ diff --git a/core/pxe.c b/core/pxe.c index 997d6c95..f4e872e8 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -51,16 +51,16 @@ static char *asciidec = "1408"; * return the socket pointer if success, or null if failure * */ -static struct open_file_t* allocate_socket() +static struct open_file_t *allocate_socket(void) { extern uint16_t NextSocket; uint16_t i = MAX_OPEN; - struct open_file_t *socket = (struct open_file_t *)&Files; + struct open_file_t *socket = Files; for (; i > 0; i--) { if (*(uint16_t*)socket == 0) break; - socket ++; + socket++; } /* Not found */ @@ -724,7 +724,7 @@ struct tftp_options { }; static struct tftp_options tftp_options[2]; -static inline void init_options() +static inline void init_options(void) { tftp_options[0].str_ptr = tsize_str; tftp_options[0].str_len = tsize_len; @@ -1313,7 +1313,7 @@ static inline int memory_scan(uint16_t seg, int (*func)(char *)) return 0; } -static int memory_scan_for_pxe_struct() +static int memory_scan_for_pxe_struct(void) { extern uint16_t BIOS_fbm; /* Starting segment */ uint16_t seg = BIOS_fbm << (10 - 4); @@ -1321,7 +1321,7 @@ static int memory_scan_for_pxe_struct() return memory_scan(seg, is_pxe); } -static int memory_scan_for_pxenv_struct() +static int memory_scan_for_pxenv_struct(void) { uint16_t seg = 0x1000; @@ -1341,7 +1341,7 @@ static int memory_scan_for_pxenv_struct() * if if the API version is 2.1 or later * */ -static void pxe_init() +static void pxe_init(void) { char plan = 'A'; uint16_t seg, off; @@ -1475,7 +1475,7 @@ static void udp_init(void) /* * Network-specific initialization */ -static void network_init() +static void network_init(void) { struct bootp_t *bp = (struct bootp_t *)trackbuf; int pkt_len; -- cgit v1.2.1 From ddd56ac530ff2ba81e350d3481e009f7dd8b0570 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 16:56:06 -0700 Subject: MCONFIG: update GCCOPT Add -fwrapv, -freg-struct-return, -fno-exceptions, -fno-asynchronous-unwind-tables, -fno-strict-aliasing. Signed-off-by: H. Peter Anvin --- MCONFIG.embedded | 5 +++++ com32/MCONFIG | 5 +++++ com32/lib/MCONFIG | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/MCONFIG.embedded b/MCONFIG.embedded index b5c8f5da..bb718963 100644 --- a/MCONFIG.embedded +++ b/MCONFIG.embedded @@ -19,8 +19,13 @@ include $(topdir)/MCONFIG GCCOPT := $(call gcc_ok,-m32,) GCCOPT += $(call gcc_ok,-ffreestanding,) GCCOPT += $(call gcc_ok,-fno-stack-protector,) +GCCOPT += $(call gcc_ok,-fwrapv,) +GCCOPT += $(call gcc_ok,-freg-struct-return,) GCCOPT += -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3 \ -msoft-float +GCCOPT += $(call gcc_ok,-fno-exceptions,) +GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) +GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) diff --git a/com32/MCONFIG b/com32/MCONFIG index 0fa78028..3af015e1 100644 --- a/com32/MCONFIG +++ b/com32/MCONFIG @@ -20,8 +20,13 @@ include $(topdir)/MCONFIG GCCOPT := $(call gcc_ok,-std=gnu99,) GCCOPT += $(call gcc_ok,-m32,) GCCOPT += $(call gcc_ok,-fno-stack-protector,) +GCCOPT += $(call gcc_ok,-fwrapv,) +GCCOPT += $(call gcc_ok,-freg-struct-return,) GCCOPT += -mregparm=3 -DREGPARM=3 -march=i386 -Os GCCOPT += $(call gcc_ok,-fPIE,-fPIC) +GCCOPT += $(call gcc_ok,-fno-exceptions,) +GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) +GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG index d5395294..7e092df3 100644 --- a/com32/lib/MCONFIG +++ b/com32/lib/MCONFIG @@ -5,7 +5,12 @@ include $(topdir)/MCONFIG GCCOPT := $(call gcc_ok,-std=gnu99,) GCCOPT += $(call gcc_ok,-m32,) GCCOPT += $(call gcc_ok,-fno-stack-protector,) +GCCOPT += $(call gcc_ok,-fwrapv,) +GCCOPT += $(call gcc_ok,-freg-struct-return,) GCCOPT += $(call gcc_ok,-fPIE,-fPIC) +GCCOPT += $(call gcc_ok,-fno-exceptions,) +GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) +GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) -- cgit v1.2.1 From 5d7d50a01de8282a0e910beb0a9f151e526dcb62 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Aug 2009 17:30:25 -0700 Subject: core: remove assembly definition of Files in iso/pxelinux Remove the assembly definition of Files in isolinux and pxelinux. Still to do: remove dependencies on Files living in .bss16 space. Signed-off-by: H. Peter Anvin --- core/include/pxe.h | 4 +++- core/init.inc | 13 ----------- core/isolinux.asm | 5 ---- core/ldlinux.asm | 2 +- core/pxe.c | 67 +++++++++++++++++++++++++++++++----------------------- core/pxelinux.asm | 4 ---- 6 files changed, 42 insertions(+), 53 deletions(-) diff --git a/core/include/pxe.h b/core/include/pxe.h index 76fcf14a..06cea0a3 100644 --- a/core/include/pxe.h +++ b/core/include/pxe.h @@ -234,7 +234,9 @@ struct open_file_t { uint16_t tftp_lastpkt; /* Sequence number of last packet (NBO) */ uint16_t tftp_dataptr; /* Pointer to available data */ uint8_t tftp_goteof; /* 1 if the EOF packet received */ - uint8_t tftp_unused[3]; /* Currently unused */ + uint8_t tftp_unused; /* Currently unused */ + /* These values are preinitialized and not zeroed on close */ + uint16_t tftp_nextport; /* Next port number for this slot (HBO) */ uint16_t tftp_pktbuf; /* Packet buffer offset */ } __attribute__ ((packed)); diff --git a/core/init.inc b/core/init.inc index ec8c7b3b..5617a697 100644 --- a/core/init.inc +++ b/core/init.inc @@ -33,19 +33,6 @@ common_init: ; call reset_config -; -; Initialize Files structures (other than zeroing) -; -%if IS_PXELINUX - mov di,Files+tftp_pktbuf - mov cx,MAX_OPEN -.setbufptr: - mov [di],ax - add di,open_file_t_size - add ax,PKTBUF_SIZE - loop .setbufptr -%endif - ; ; Set up the COMBOOT APIs ; diff --git a/core/isolinux.asm b/core/isolinux.asm index 21e74740..91541bc6 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -191,11 +191,6 @@ dsp_dummy: resb 1 ; Scratch, safe to overwrite _spec_end equ $ _spec_len equ _spec_end - _spec_start - section .bss16 - global Files - alignb open_file_t_size -Files resb MAX_OPEN*open_file_t_size - section .init ;; ;; Primary entry point. Because BIOSes are buggy, we only load the first diff --git a/core/ldlinux.asm b/core/ldlinux.asm index b8b86b2e..f57b2390 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -29,7 +29,7 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ syslinux_id -FILENAME_MAX_LG2 equ 6 ; log2(Max filename size Including final null) +FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) extern vfat_fs_ops ROOT_FS_OPS equ vfat_fs_ops diff --git a/core/pxe.c b/core/pxe.c index f4e872e8..f4afc087 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -24,8 +24,6 @@ static char *err_udpinit = "Failed to initialize UDP stack\n"; static char *tftpprefix_msg = "TFTP prefix: "; static char *get_packet_msg = "Getting cached packet "; -static uint16_t NextSocket = 49152; - static int has_gpxe; static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; int HaveUUID = 0; @@ -44,7 +42,24 @@ static int blksize_len = 8; static char *asciidec = "1408"; - +/* + * Initialize the Files structure + */ +static void files_init(void) +{ + int i; + struct open_file_t *socket = Files; + uint16_t pktbuf = 0; + uint16_t nextport = 49152; + + for (i = 0; i < MAX_OPEN; i++) { + socket->tftp_pktbuf = pktbuf; + socket->tftp_nextport = nextport; + pktbuf += PKTBUF_SIZE; + nextport++; + socket++; + } +} /* * Allocate a local UDP port structure. @@ -53,37 +68,28 @@ static char *asciidec = "1408"; */ static struct open_file_t *allocate_socket(void) { - extern uint16_t NextSocket; - uint16_t i = MAX_OPEN; + int i; struct open_file_t *socket = Files; + uint16_t nextport; - for (; i > 0; i--) { - if (*(uint16_t*)socket == 0) - break; + for (i = 0; i < MAX_OPEN; i++) { + if (!socket->tftp_localport) + break; socket++; } - /* Not found */ - if (i == 0) - return NULL; - + if (i == MAX_OPEN) + return NULL; + /* - * Allocate a socket number. Socket numbers are made guaranteed unique - * by including the socket slot number(inverted, because we use the loop - * counter cx; add a counter value to keep the numbers from being likely - * to get immediately reused. - * - * The NextSocket variable also contains the top two bits set. This - * generates a value in the range 49152 to 57343. - * + * Allocate a socket number. Socket numbers are made guaranteed + * unique by including the socket slot number; add a counter value + * to keep the numbers from being likely to get immediately + * reused. The mask enforces wraparound to the range 49152-57343. */ - i--; - NextSocket = ((NextSocket + 1) & ((1 << (13-MAX_OPEN_LG2))-1)) | 0xc000; - i <<= 13-MAX_OPEN_LG2; - i += NextSocket; - i = ntohs(i) ; /* convet to network byte order, little to big */ - *(uint16_t*)socket = i; /* socket in use */ - + nextport = socket->tftp_nextport; + socket->tftp_nextport = (nextport + (1 << MAX_OPEN_LG2)) & 0xdfff; + socket->tftp_localport = htons(nextport); /* Socket now in use */ return socket; } @@ -93,7 +99,7 @@ static struct open_file_t *allocate_socket(void) static void free_socket(struct open_file_t *file) { /* tftp_pktbuf is not cleared */ - memset(file, 0, sizeof(struct open_file_t) - 2); + memset(file, 0, offsetof(struct open_file_t, tftp_nextport)); } /** @@ -1546,8 +1552,11 @@ static void network_init(void) */ static int pxe_fs_init(struct fs_info *fs) { - fs = NULL; /* drop the compile warning message */ + (void)fs; /* drop the compile warning message */ + /* Initialize the Files structure */ + files_init(); + /* do the pxe initialize */ pxe_init(); diff --git a/core/pxelinux.asm b/core/pxelinux.asm index cfaf5db6..b8077fd9 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -172,10 +172,6 @@ trackbuf resb trackbufsize ; Track buffer goes here InitStack resd 1 section .bss16 - global Files - alignb open_file_t_size -Files resb MAX_OPEN*open_file_t_size - alignb FILENAME_MAX global BootFile, PathPrefix, DotQuadBuf, IPOption BootFile resb 256 ; Boot file from DHCP packet -- cgit v1.2.1 From db6bc6f4eb6a10fd4af96c5068d651ad4aca95aa Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 11 Aug 2009 14:16:23 +0800 Subject: Core:SYSLINUX: fix the vfat_searchdir This makes the searchdir can find a dir; it's also prepared for the readdir function used in rosh Signed-off-by: Liu Aleaxander --- com32/rosh/rosh.c | 2 +- com32/rosh/rosh.h | 2 ++ core/comboot.inc | 5 ++--- core/extern.inc | 2 +- core/fat.c | 40 ++++++++++++++++++++-------------------- core/fs.c | 4 ++-- 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 9a4edae2..fe37d727 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -428,7 +428,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) filepos = 0; d = opendir(filestr); if (d != NULL) { - printf("DIR:'%s' %8d %8d\n", d->dd_name, d->dd_fd, + printf("DIR:'%s' %08x %8d\n", d->dd_name, d->dd_fd, d->dd_sect); de = readdir(d); while (de != NULL) { diff --git a/com32/rosh/rosh.h b/com32/rosh/rosh.h index 64b0564c..0c41bac9 100644 --- a/com32/rosh/rosh.h +++ b/com32/rosh/rosh.h @@ -47,6 +47,8 @@ #error SYSLINUX (I believe) requires __GNUC__ #endif /* __GNUC__ */ +#define DO_DEBUG 1 + #ifdef DO_DEBUG #define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) #ifdef DO_DEBUG2 diff --git a/core/comboot.inc b/core/comboot.inc index da3c2399..a8c8323c 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -908,11 +908,10 @@ comapi_opendir: pop ds pm_call searchdir jnz comapi_err ; Didn't find a directory + mov eax,[si] ; the sector number where the dir stores cmp eax,0 jz comapi_err ; Found nothing - ;ZF is unset - pm_call alloc_fill_dir - mov P_EAX,eax + mov P_EAX,eax mov P_CX,SECTOR_SIZE mov P_SI,si clc diff --git a/core/extern.inc b/core/extern.inc index 4c7b149a..1e011c9e 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -18,7 +18,7 @@ %if IS_SYSLINUX ; fat.c - extern alloc_fill_dir, readdir + extern readdir %endif %endif ; EXTERN_INC diff --git a/core/fat.c b/core/fat.c index 57278d03..3cf9594b 100644 --- a/core/fat.c +++ b/core/fat.c @@ -89,22 +89,18 @@ static struct open_file_t *allocate_file(void) * structure, or return NULL. * */ -void alloc_fill_dir(com32sys_t *regs) +static struct open_file_t *alloc_fill_dir(sector_t sector) { - sector_t sector = regs->eax.l; struct open_file_t *file; file = allocate_file(); - if ( !file ) { - regs->esi.w[0] = 0; - return; - } + if ( !file ) + return NULL; file->file_sector = sector; /* current sector */ file->file_bytesleft = 0; /* current offset */ file->file_left = sector; /* beginning sector */ - - regs->esi.w[0] = OFFS_WRT(file, 0); + return file; } @@ -681,39 +677,43 @@ static void vfat_searchdir(char *filename, struct file *file) dir_sector = RootDir; filename ++; } + if (*filename == 0) /* root dir is what we need */ + goto found_dir; while ( *filename ) { p = filename; + PrevDir = dir_sector; /* try to find the end */ while ( (*p > ' ') && (*p != '/') ) p ++; - if (filename == p) - //return NULL; - goto fail; - - PrevDir = dir_sector; + if (filename == p) { + /* found a dir */ + dir_sector = PrevDir; + goto found_dir; + } + //*p = 0; /* null-terminate the current path part */ mangle_dos_name(MangleBuf, filename); open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); if (! open_file) goto fail; - - if ( *p != '/' ) /* we got a file */ + + if ( *p == 0 ) /* we got a file */ break; - if ( (attr & 0x10) == 0 ) /* subdirectory */ - //return NULL; - goto fail; - dir_sector = open_file->file_sector; close_file(open_file); filename = p + 1; /* search again */ } - if ( (attr & 0x18) || (file_len == 0) ) { + if (attr & 0x10) { + dir_sector = PrevDir; + found_dir: + open_file = alloc_fill_dir(dir_sector); + } else if ( (attr & 0x18) || (file_len == 0) ) { fail: file_len = 0; open_file = NULL; diff --git a/core/fs.c b/core/fs.c index 03abfd6f..0bfa1557 100644 --- a/core/fs.c +++ b/core/fs.c @@ -64,7 +64,7 @@ void searchdir(com32sys_t *regs) char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]);; struct file file; -#if 0 +#if 1 printf("filename: %s\n", filename); #endif @@ -74,7 +74,7 @@ void searchdir(com32sys_t *regs) this_fs->fs_ops->searchdir(filename, &file); regs->esi.w[0] = OFFS_WRT(file.open_file, 0); regs->eax.l = file.file_len; - if (file.file_len) + if (file.open_file) regs->eflags.l &= ~EFLAGS_ZF; else regs->eflags.l |= EFLAGS_ZF; -- cgit v1.2.1 From 37003eb7e984370fad9407ce5db341b720e9d4cd Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 11 Aug 2009 17:18:38 +0800 Subject: Core:SYSLINUX: make searchdir do work well, still get lots of bugs, like when we execute dir /boot/syslinux in fact, it will list the file in /boot/ directory but not in /boot/syslinux/ Signed-off-by: Liu Aleaxander --- com32/rosh/rosh.c | 8 ++++---- core/comboot.inc | 4 ++-- core/extern.inc | 2 +- core/fat.c | 45 ++++++++++++++++++++++++--------------------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index fe37d727..631c780e 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -391,10 +391,10 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) fd = open(filestr, O_RDONLY); if (fd != -1) { status = fstat(fd, &fdstat); - if (S_ISDIR(fdstat.st_mode)) { + if (S_ISDIR(fdstat.st_mode)) { ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr); d = fdopendir(fd); - de = readdir(d); + de = readdir(d); while (de != NULL) { #ifdef DO_DEBUG filestr2[0] = 0; @@ -423,10 +423,10 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) } } else { #ifdef __COM32__ - if (filestr[strlen(filestr) - 1] == SEP) { + if (filestr[strlen(filestr) - 1] == SEP) { /* Directory */ filepos = 0; - d = opendir(filestr); + d = opendir(filestr); if (d != NULL) { printf("DIR:'%s' %08x %8d\n", d->dd_name, d->dd_fd, d->dd_sect); diff --git a/core/comboot.inc b/core/comboot.inc index a8c8323c..007c3836 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -907,7 +907,7 @@ comapi_opendir: pm_call mangle_name pop ds pm_call searchdir - jnz comapi_err ; Didn't find a directory + jz comapi_err ; Didn't find a directory mov eax,[si] ; the sector number where the dir stores cmp eax,0 jz comapi_err ; Found nothing @@ -928,7 +928,7 @@ comapi_readdir: mov es,P_ES mov di,P_DI mov si,P_SI - pm_call readdir + pm_call vfat_readdir mov P_EAX,eax mov P_DL,dl mov P_EBX,ebx diff --git a/core/extern.inc b/core/extern.inc index 1e011c9e..eb238be0 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -18,7 +18,7 @@ %if IS_SYSLINUX ; fat.c - extern readdir + extern vfat_readdir %endif %endif ; EXTERN_INC diff --git a/core/fat.c b/core/fat.c index 3cf9594b..c1847308 100644 --- a/core/fat.c +++ b/core/fat.c @@ -675,13 +675,16 @@ static void vfat_searchdir(char *filename, struct file *file) dir_sector = CurrentDir; if ( *filename == '/' ) { dir_sector = RootDir; - filename ++; + if (*(filename + 1) == 0) /* root dir is what we need */ + goto found_dir; } - if (*filename == 0) /* root dir is what we need */ - goto found_dir; - + while ( *filename ) { + if (*filename == '/') + filename++; /* skip '/' */ p = filename; + if (*p == 0) + break; PrevDir = dir_sector; /* try to find the end */ @@ -694,19 +697,15 @@ static void vfat_searchdir(char *filename, struct file *file) goto found_dir; } - //*p = 0; /* null-terminate the current path part */ mangle_dos_name(MangleBuf, filename); + /* close it before open a new dir file */ + close_file(open_file); open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); if (! open_file) goto fail; - if ( *p == 0 ) /* we got a file */ - break; - dir_sector = open_file->file_sector; - close_file(open_file); - - filename = p + 1; /* search again */ + filename = p; } if (attr & 0x10) { @@ -740,21 +739,20 @@ static void vfat_searchdir(char *filename, struct file *file) * @param: file * */ -static void readdir(com32sys_t *regs)/* +void vfat_readdir(com32sys_t *regs)/* struct fs_info *fs, struct open_file_t* dir_file, char* filename, uint32_t *file_len, uint8_t *attr) */ { - uint32_t sector, sec_off; - + uint32_t sector, sec_off; /* make it to be 1 to check if we have met a long name entry before */ uint8_t id = 1; uint8_t init_id, next_id; uint8_t entries_left; int i; - char *filename = (char *)MK_PTR(regs->es, regs->edi.w[0]); - struct open_file_t *dir_file = (struct open_file_t *)MK_PTR(regs->ds, regs->esi.w[0]); + char *filename = MK_PTR(regs->es, regs->edi.w[0]); + struct open_file_t *dir_file = MK_PTR(regs->ds, regs->esi.w[0]); struct cache_struct *cs; struct fat_dir_entry *dir; @@ -763,7 +761,7 @@ static void readdir(com32sys_t *regs)/* sector = dir_file->file_sector; sec_off = dir_file->file_bytesleft; - if ( !sector ) + if (!sector) goto fail; entries_left = (SECTOR_SIZE - sec_off) >> 5; @@ -813,7 +811,7 @@ static void readdir(com32sys_t *regs)/* } *filename++ = '.'; - + for ( i = 8; i < 11; i ++) { if ( dir->name[i] == ' ' ) break; @@ -821,8 +819,8 @@ static void readdir(com32sys_t *regs)/* } /* check if we have got an extention */ - if ( ! *(filename - 1) ) - *(filename -2) = '\0'; + if (*(filename - 1) == '.') + *(filename - 1) = '\0'; else *filename = '\0'; @@ -848,7 +846,10 @@ static void readdir(com32sys_t *regs)/* sector = nextsector(this_fs, sector); if ( !sector ) goto fail; - } + dir_file->file_bytesleft = 0; + } else + dir_file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); + dir_file->file_sector = sector; file.file_sector = sector; file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT) ) & 0xffff; @@ -862,6 +863,8 @@ static void readdir(com32sys_t *regs)/* fail: //close_dir(dir); regs->eax.l = 0; + regs->esi.w[0] = 0; + regs->eflags.l |= EFLAGS_CF; } static void vfat_load_config(com32sys_t *regs) -- cgit v1.2.1 From e32f5182161fd5210e67ae57136e929dc20e0776 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 Aug 2009 11:49:04 -0700 Subject: pxe: clean up C code; reimplement "Plan C"; share PXE API definitions Minor cleanups to the C code. Reimplement "Plan C" for finding the entry point. Share the PXE API definitions between com32 and the core. Signed-off-by: H. Peter Anvin --- com32/include/syslinux/pxe.h | 487 +---------------------------------- com32/include/syslinux/pxe_api.h | 531 +++++++++++++++++++++++++++++++++++++++ core/include/pxe.h | 234 +++++------------ core/pxe.c | 159 ++++++------ core/pxelinux.asm | 39 ++- 5 files changed, 695 insertions(+), 755 deletions(-) create mode 100644 com32/include/syslinux/pxe_api.h diff --git a/com32/include/syslinux/pxe.h b/com32/include/syslinux/pxe.h index 037642bc..041e0ae1 100644 --- a/com32/include/syslinux/pxe.h +++ b/com32/include/syslinux/pxe.h @@ -34,493 +34,10 @@ #ifndef _SYSLINUX_PXE_H #define _SYSLINUX_PXE_H -#include -#include -#include - -/* PXE spec structures and definitions. These mostly follow the PXE - spec, except when the PXE spec is unnecessarily stupid. Of course, - that is most of the time. */ - -/* Basic types; use Unix-like _t convention instead of SCREAMING; also - re-use types we already have, like in_addr_t. */ - -typedef uint16_t pxenv_status_t; - -#define MAC_ADDR_LEN 16 -typedef uint8_t mac_addr_t[MAC_ADDR_LEN]; - -/* "Protected mode segment descriptor" according to PXE... */ -typedef struct { - uint16_t segaddr; - uint32_t physaddr; - uint16_t segsize; -} __packed pxe_segdesc_t; - -typedef struct { - uint16_t offs; - uint16_t seg; -} segoff16_t; - -typedef struct { - uint8_t opcode; -#define BOOTP_REQ 1 -#define BOOTP_REP 2 - uint8_t Hardware; - uint8_t Hardlen; - uint8_t Gatehops; - uint32_t ident; - uint16_t seconds; - uint16_t Flags; -#define BOOTP_BCAST 0x8000 - in_addr_t cip; /* Client IP address */ - in_addr_t yip; /* You IP address */ - in_addr_t sip; /* next server IP address */ - in_addr_t gip; /*relay agent IP address */ - mac_addr_t CAddr; - uint8_t Sname[64]; - uint8_t bootfile[128]; - union { -#define BOOTP_DHCPVEND 1024 - uint8_t d[BOOTP_DHCPVEND]; - struct { - uint8_t magic[4]; -#define VM_RFC1048 0x63825363L - uint32_t flags; - uint8_t pad[56]; - } v; - } vendor; -} __packed pxe_bootp_t; - -/* Function calling structures and constants */ - -typedef struct s_PXENV_GET_CACHED_INFO { - pxenv_status_t Status; - uint16_t PacketType; -#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 -#define PXENV_PACKET_TYPE_DHCP_ACK 2 -#define PXENV_PACKET_TYPE_CACHED_REPLY 3 - uint16_t BufferSize; - segoff16_t Buffer; - uint16_t BufferLimit; -} __packed t_PXENV_GET_CACHED_INFO; - -typedef struct s_PXENV_START_UNDI { - pxenv_status_t Status; - uint16_t AX; - uint16_t BX; - uint16_t DX; - uint16_t DI; - uint16_t ES; -} __packed t_PXENV_START_UNDI; - -typedef struct s_PXENV_STOP_UNDI { - pxenv_status_t Status; -} __packed t_PXENV_STOP_UNDI; - -typedef struct s_PXENV_START_BASE { - pxenv_status_t Status; -} __packed t_PXENV_START_BASE; - -typedef struct s_PXENV_STOP_BASE { - pxenv_status_t Status; -} __packed t_PXENV_STOP_BASE; - -typedef struct s_PXENV_TFTP_OPEN { - pxenv_status_t Status; - in_addr_t ServerIPAddress; - in_addr_t GatewayIPAddress; - uint8_t FileName[128]; - in_port_t TFTPPort; - uint16_t PacketSize; -} __packed t_PXENV_TFTP_OPEN; - -typedef struct s_PXENV_TFTP_CLOSE { - pxenv_status_t Status; -} __packed t_PXENV_TFTP_CLOSE; - -typedef struct s_PXENV_TFTP_READ { - pxenv_status_t Status; - uint16_t PacketNumber; - uint16_t BufferSize; - segoff16_t Buffer; -} __packed t_PXENV_TFTP_READ; - -typedef struct s_PXENV_TFTP_READ_FILE { - pxenv_status_t Status; - uint8_t FileName[128]; - uint32_t BufferSize; - void *Buffer; - in_addr_t ServerIPAddress; - in_addr_t GatewayIPAddress; - in_addr_t McastIPAddress; - in_port_t TFTPClntPort; - in_port_t TFTPSrvPort; - uint16_t TFTPOpenTimeOut; - uint16_t TFTPReopenDelay; -} __packed t_PXENV_TFTP_READ_FILE; - -typedef struct s_PXENV_TFTP_GET_FSIZE { - pxenv_status_t Status; - in_addr_t ServerIPAddress; - in_addr_t GatewayIPAddress; - uint8_t FileName[128]; - uint32_t FileSize; -} __packed t_PXENV_TFTP_GET_FSIZE; - -typedef struct s_PXENV_UDP_OPEN { - pxenv_status_t status; - in_addr_t src_ip; -} __packed t_PXENV_UDP_OPEN; - -typedef struct s_PXENV_UDP_CLOSE { - pxenv_status_t status; -} __packed t_PXENV_UDP_CLOSE; - -typedef struct s_PXENV_UDP_WRITE { - pxenv_status_t status; - in_addr_t ip; - in_addr_t gw; - in_port_t src_port; - in_port_t dst_port; - uint16_t buffer_size; - segoff16_t buffer; -} __packed t_PXENV_UDP_WRITE; - -typedef struct s_PXENV_UDP_READ { - pxenv_status_t status; - in_addr_t src_ip; - in_addr_t dest_ip; - in_port_t s_port; - in_port_t d_port; - uint16_t buffer_size; - segoff16_t buffer; -} __packed t_PXENV_UDP_READ; - -typedef struct s_PXENV_UNDI_STARTUP { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_STARTUP; - -typedef struct s_PXENV_UNDI_CLEANUP { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_CLEANUP; - -typedef struct s_PXENV_UNDI_INITIALIZE { - pxenv_status_t Status; - void *ProtocolIni; - uint8_t reserved[8]; -} __packed t_PXENV_UNDI_INITIALIZE; - -#define MAXNUM_MCADDR 8 -typedef struct s_PXENV_UNDI_MCAST_ADDRESS { - uint16_t MCastAddrCount; - mac_addr_t McastAddr[MAXNUM_MCADDR]; -} __packed t_PXENV_UNDI_MCAST_ADDRESS; - -typedef struct s_PXENV_UNDI_RESET { - pxenv_status_t Status; - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} __packed t_PXENV_UNDI_RESET; - -typedef struct s_PXENV_UNDI_SHUTDOWN { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_SHUTDOWN; - -typedef struct s_PXENV_UNDI_OPEN { - pxenv_status_t Status; - uint16_t OpenFlag; - uint16_t PktFilter; -#define FLTR_DIRECTED 0x0001 -#define FLTR_BRDCST 0x0002 -#define FLTR_PRMSCS 0x0004 -#define FLTR_SRC_RTG 0x0008 - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} __packed t_PXENV_UNDI_OPEN; - -typedef struct s_PXENV_UNDI_CLOSE { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_CLOSE; - -typedef struct s_PXENV_UNDI_TRANSMIT { - pxenv_status_t Status; - uint8_t Protocol; -#define P_UNKNOWN 0 -#define P_IP 1 -#define P_ARP 2 -#define P_RARP 3 - uint8_t XmitFlag; -#define XMT_DESTADDR 0x0000 -#define XMT_BROADCAST 0x0001 - segoff16_t DestAddr; - segoff16_t TBD; - uint32_t Reserved[2]; -} __packed t_PXENV_UNDI_TRANSMIT; -#define MAX_DATA_BLKS 8 -typedef struct s_PXENV_UNDI_TBD { - uint16_t ImmedLength; - segoff16_t Xmit; - uint16_t DataBlkCount; - struct DataBlk { - uint8_t TDPtrType; - uint8_t TDRsvdByte; - uint16_t TDDataLen; - segoff16_t TDDataPtr; - } DataBlock[MAX_DATA_BLKS]; -} __packed t_PXENV_UNDI_TBD; - -typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS { - pxenv_status_t Status; - t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; -} __packed t_PXENV_UNDI_SET_MCAST_ADDR; - -typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS { - pxenv_status_t Status; - mac_addr_t StationAddress; -} __packed t_PXENV_UNDI_SET_STATION_ADDR; - -typedef struct s_PXENV_UNDI_SET_PACKET_FILTER { - pxenv_status_t Status; - uint8_t filter; -} __packed t_PXENV_UNDI_SET_PACKET_FILTER; - -typedef struct s_PXENV_UNDI_GET_INFORMATION { - pxenv_status_t Status; - uint16_t BaseIo; - uint16_t IntNumber; - uint16_t MaxTranUnit; - uint16_t HwType; -#define ETHER_TYPE 1 -#define EXP_ETHER_TYPE 2 -#define IEEE_TYPE 6 -#define ARCNET_TYPE 7 - uint16_t HwAddrLen; - mac_addr_t CurrentNodeAddress; - mac_addr_t PermNodeAddress; - uint16_t ROMAddress; - uint16_t RxBufCt; - uint16_t TxBufCt; -} __packed t_PXENV_UNDI_GET_INFORMATION; - -typedef struct s_PXENV_UNDI_GET_STATISTICS { - pxenv_status_t Status; - uint32_t XmtGoodFrames; - uint32_t RcvGoodFrames; - uint32_t RcvCRCErrors; - uint32_t RcvResourceErrors; -} __packed t_PXENV_UNDI_GET_STATISTICS; - -typedef struct s_PXENV_UNDI_CLEAR_STATISTICS { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_CLEAR_STATISTICS; - -typedef struct s_PXENV_UNDI_INITIATE_DIAGS { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_INITIATE_DIAGS; - -typedef struct s_PXENV_UNDI_FORCE_INTERRUPT { - pxenv_status_t Status; -} __packed t_PXENV_UNDI_FORCE_INTERRUPT; - -typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS { - pxenv_status_t Status; - in_addr_t InetAddr; - mac_addr_t MediaAddr; -} __packed t_PXENV_UNDI_GET_MCAST_ADDR; - -typedef struct s_PXENV_UNDI_GET_NIC_TYPE { - pxenv_status_t Status; - uint8_t NicType; -#define PCI_NIC 2 -#define PnP_NIC 3 -#define CardBus_NIC 4 - union { - struct { - uint16_t Vendor_ID; - uint16_t Dev_ID; - uint8_t Base_Class; - uint8_t Sub_Class; - uint8_t Prog_Intf; - uint8_t Rev; - uint16_t BusDevFunc; - uint16_t SubVendor_ID; - uint16_t SubDevice_ID; - } pci, cardbus; - struct { - uint32_t EISA_Dev_ID; - uint8_t Base_Class; - uint8_t Sub_Class; - uint8_t Prog_Intf; - uint16_t CardSelNum; - } __packed pnp; - } __packed info; -} __packed t_PXENV_UNDI_GET_NIC_TYPE; - -typedef struct s_PXENV_UNDI_GET_IFACE_INFO { - pxenv_status_t Status; - uint8_t IfaceType[16]; - uint32_t LinkSpeed; - uint32_t ServiceFlags; - uint32_t Reserved[4]; -} __packed t_PXENV_UNDI_GET_NDIS_INFO; - -typedef struct s_PXENV_UNDI_GET_STATE { -#define PXE_UNDI_GET_STATE_STARTED 1 -#define PXE_UNDI_GET_STATE_INITIALIZED 2 -#define PXE_UNDI_GET_STATE_OPENED 3 - pxenv_status_t Status; - uint8_t UNDIstate; -} __packed t_PXENV_UNDI_GET_STATE; - -typedef struct s_PXENV_UNDI_ISR { - pxenv_status_t Status; - uint16_t FuncFlag; - uint16_t BufferLength; - uint16_t FrameLength; - uint16_t FrameHeaderLength; - segoff16_t Frame; - uint8_t ProtType; - uint8_t PktType; -} __packed t_PXENV_UNDI_ISR; -#define PXENV_UNDI_ISR_IN_START 1 -#define PXENV_UNDI_ISR_IN_PROCESS 2 -#define PXENV_UNDI_ISR_IN_GET_NEXT 3 -/* One of these will be returned for - PXENV_UNDI_ISR_IN_START */ -#define PXENV_UNDI_ISR_OUT_OURS 0 -#define PXENV_UNDI_USR_OUT_NOT_OURS 1 -/* One of these will be returned for - PXENV_UNDI_ISR_IN_PROCESS and - PXENV_UNDI_ISR_IN_GET_NEXT */ -#define PXENV_UNDI_ISR_OUT_DONE 0 -#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 -#define PXENV_UNDI_ISR_OUT_RECEIVE 3 -#define PXENV_UNDI_ISR_OUT_BUSY 4 - -/* Function numbers and error codes */ - -#define PXENV_TFTP_OPEN 0x0020 -#define PXENV_TFTP_CLOSE 0x0021 -#define PXENV_TFTP_READ 0x0022 -#define PXENV_TFTP_READ_FILE 0x0023 -#define PXENV_TFTP_READ_FILE_PMODE 0x0024 -#define PXENV_TFTP_GET_FSIZE 0x0025 - -#define PXENV_UDP_OPEN 0x0030 -#define PXENV_UDP_CLOSE 0x0031 -#define PXENV_UDP_READ 0x0032 -#define PXENV_UDP_WRITE 0x0033 - -#define PXENV_START_UNDI 0x0000 -#define PXENV_UNDI_STARTUP 0x0001 -#define PXENV_UNDI_CLEANUP 0x0002 -#define PXENV_UNDI_INITIALIZE 0x0003 -#define PXENV_UNDI_RESET_NIC 0x0004 -#define PXENV_UNDI_SHUTDOWN 0x0005 -#define PXENV_UNDI_OPEN 0x0006 -#define PXENV_UNDI_CLOSE 0x0007 -#define PXENV_UNDI_TRANSMIT 0x0008 -#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 -#define PXENV_UNDI_SET_STATION_ADDR 0x000A -#define PXENV_UNDI_SET_PACKET_FILTER 0x000B -#define PXENV_UNDI_GET_INFORMATION 0x000C -#define PXENV_UNDI_GET_STATISTICS 0x000D -#define PXENV_UNDI_CLEAR_STATISTICS 0x000E -#define PXENV_UNDI_INITIATE_DIAGS 0x000F -#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 -#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 -#define PXENV_UNDI_GET_IFACE_INFO 0x0013 -#define PXENV_UNDI_ISR 0x0014 -#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */ -#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */ - -#define PXENV_UNLOAD_STACK 0x0070 -#define PXENV_GET_CACHED_INFO 0x0071 -#define PXENV_RESTART_DHCP 0x0072 -#define PXENV_RESTART_TFTP 0x0073 -#define PXENV_MODE_SWITCH 0x0074 -#define PXENV_START_BASE 0x0075 -#define PXENV_STOP_BASE 0x0076 - -#define PXENV_EXIT_SUCCESS 0x0000 -#define PXENV_EXIT_FAILURE 0x0001 - -#define PXENV_STATUS_SUCCESS 0x00 -#define PXENV_STATUS_FAILURE 0x01 -#define PXENV_STATUS_BAD_FUNC 0x02 -#define PXENV_STATUS_UNSUPPORTED 0x03 -#define PXENV_STATUS_KEEP_UNDI 0x04 -#define PXENV_STATUS_KEEP_ALL 0x05 -#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 -#define PXENV_STATUS_ARP_TIMEOUT 0x11 -#define PXENV_STATUS_UDP_CLOSED 0x18 -#define PXENV_STATUS_UDP_OPEN 0x19 -#define PXENV_STATUS_TFTP_CLOSED 0x1A -#define PXENV_STATUS_TFTP_OPEN 0x1B -#define PXENV_STATUS_MCOPY_PROBLEM 0x20 -#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 -#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 -#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 -#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 -#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 -#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 -#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 -#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 -#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 -#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 - -#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 -#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 -#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 -#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 -#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 -#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3A -#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B -#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C -#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D -#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3E -#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3F -#define PXENV_STATUS_DHCP_TIMEOUT 0x51 -#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 -#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 -#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 -#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 -#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x6A -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B -#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C -#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 -#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 -#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 -#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 -#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 -#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xA0 -#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1 -#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xA2 -#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xA3 -#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xB0 -#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xC0 -#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1 -#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2 -#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xC3 -#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4 -#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5 -#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xC6 -#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8 -#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xC9 -#define PXENV_STATUS_LOADER_UNDI_START 0xCA -#define PXENV_STATUS_LOADER_BC_START 0xCB +#include /* SYSLINUX-defined PXE utility functions */ -int pxe_get_cached_info(int level, void **buf, size_t * len); +int pxe_get_cached_info(int level, void **buf, size_t *len); int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE * gnt); #endif /* _SYSLINUX_PXE_H */ diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h new file mode 100644 index 00000000..5fd102ef --- /dev/null +++ b/com32/include/syslinux/pxe_api.h @@ -0,0 +1,531 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/pxe_api.h + * + * PXE type and constant definitions for SYSLINUX + */ + +#ifndef _SYSLINUX_PXE_API_H +#define _SYSLINUX_PXE_API_H + +#include +#include +#include +#include + +/* PXE spec structures and definitions. These mostly follow the PXE + spec, except when the PXE spec is unnecessarily stupid. Of course, + that is most of the time. */ + +/* Basic types; use Unix-like _t convention instead of SCREAMING; also + re-use types we already have, like in_addr_t. */ + +typedef uint16_t pxenv_status_t; + +#define MAC_ADDR_LEN 16 +typedef uint8_t mac_addr_t[MAC_ADDR_LEN]; + +/* "Protected mode segment descriptor" according to PXE... */ +typedef struct { + uint16_t sel; + uint32_t base; + uint16_t size; +} __packed pxe_segdesc_t; + +typedef far_ptr_t segoff16_t; + +typedef struct { + uint8_t opcode; +#define BOOTP_REQ 1 +#define BOOTP_REP 2 + uint8_t Hardware; + uint8_t Hardlen; + uint8_t Gatehops; + uint32_t ident; + uint16_t seconds; + uint16_t Flags; +#define BOOTP_BCAST 0x8000 + in_addr_t cip; /* Client IP address */ + in_addr_t yip; /* You IP address */ + in_addr_t sip; /* next server IP address */ + in_addr_t gip; /*relay agent IP address */ + mac_addr_t CAddr; + uint8_t Sname[64]; + uint8_t bootfile[128]; + union { +#define BOOTP_DHCPVEND 1024 + uint8_t d[BOOTP_DHCPVEND]; + struct { + uint8_t magic[4]; +#define VM_RFC1048 0x63825363L + uint32_t flags; + uint8_t pad[56]; + } v; + } vendor; +} __packed pxe_bootp_t; + +/* Function calling structures and constants */ + +typedef struct s_PXENV_GET_CACHED_INFO { + pxenv_status_t Status; + uint16_t PacketType; +#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 +#define PXENV_PACKET_TYPE_DHCP_ACK 2 +#define PXENV_PACKET_TYPE_CACHED_REPLY 3 + uint16_t BufferSize; + segoff16_t Buffer; + uint16_t BufferLimit; +} __packed t_PXENV_GET_CACHED_INFO; + +typedef struct s_PXENV_START_UNDI { + pxenv_status_t Status; + uint16_t AX; + uint16_t BX; + uint16_t DX; + uint16_t DI; + uint16_t ES; +} __packed t_PXENV_START_UNDI; + +typedef struct s_PXENV_STOP_UNDI { + pxenv_status_t Status; +} __packed t_PXENV_STOP_UNDI; + +typedef struct s_PXENV_START_BASE { + pxenv_status_t Status; +} __packed t_PXENV_START_BASE; + +typedef struct s_PXENV_STOP_BASE { + pxenv_status_t Status; +} __packed t_PXENV_STOP_BASE; + +typedef struct s_PXENV_TFTP_OPEN { + pxenv_status_t Status; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + uint8_t FileName[128]; + in_port_t TFTPPort; + uint16_t PacketSize; +} __packed t_PXENV_TFTP_OPEN; + +typedef struct s_PXENV_TFTP_CLOSE { + pxenv_status_t Status; +} __packed t_PXENV_TFTP_CLOSE; + +typedef struct s_PXENV_TFTP_READ { + pxenv_status_t Status; + uint16_t PacketNumber; + uint16_t BufferSize; + segoff16_t Buffer; +} __packed t_PXENV_TFTP_READ; + +typedef struct s_PXENV_TFTP_READ_FILE { + pxenv_status_t Status; + uint8_t FileName[128]; + uint32_t BufferSize; + void *Buffer; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + in_addr_t McastIPAddress; + in_port_t TFTPClntPort; + in_port_t TFTPSrvPort; + uint16_t TFTPOpenTimeOut; + uint16_t TFTPReopenDelay; +} __packed t_PXENV_TFTP_READ_FILE; + +typedef struct s_PXENV_TFTP_GET_FSIZE { + pxenv_status_t Status; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + uint8_t FileName[128]; + uint32_t FileSize; +} __packed t_PXENV_TFTP_GET_FSIZE; + +typedef struct s_PXENV_UDP_OPEN { + pxenv_status_t status; + in_addr_t src_ip; +} __packed t_PXENV_UDP_OPEN; + +typedef struct s_PXENV_UDP_CLOSE { + pxenv_status_t status; +} __packed t_PXENV_UDP_CLOSE; + +typedef struct s_PXENV_UDP_WRITE { + pxenv_status_t status; + in_addr_t ip; + in_addr_t gw; + in_port_t src_port; + in_port_t dst_port; + uint16_t buffer_size; + segoff16_t buffer; +} __packed t_PXENV_UDP_WRITE; + +typedef struct s_PXENV_UDP_READ { + pxenv_status_t status; + in_addr_t src_ip; + in_addr_t dest_ip; + in_port_t s_port; + in_port_t d_port; + uint16_t buffer_size; + segoff16_t buffer; +} __packed t_PXENV_UDP_READ; + +typedef struct s_PXENV_UNDI_STARTUP { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_STARTUP; + +typedef struct s_PXENV_UNDI_CLEANUP { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLEANUP; + +typedef struct s_PXENV_UNDI_INITIALIZE { + pxenv_status_t Status; + void *ProtocolIni; + uint8_t reserved[8]; +} __packed t_PXENV_UNDI_INITIALIZE; + +#define MAXNUM_MCADDR 8 +typedef struct s_PXENV_UNDI_MCAST_ADDRESS { + uint16_t MCastAddrCount; + mac_addr_t McastAddr[MAXNUM_MCADDR]; +} __packed t_PXENV_UNDI_MCAST_ADDRESS; + +typedef struct s_PXENV_UNDI_RESET { + pxenv_status_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_RESET; + +typedef struct s_PXENV_UNDI_SHUTDOWN { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_SHUTDOWN; + +typedef struct s_PXENV_UNDI_OPEN { + pxenv_status_t Status; + uint16_t OpenFlag; + uint16_t PktFilter; +#define FLTR_DIRECTED 0x0001 +#define FLTR_BRDCST 0x0002 +#define FLTR_PRMSCS 0x0004 +#define FLTR_SRC_RTG 0x0008 + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_OPEN; + +typedef struct s_PXENV_UNDI_CLOSE { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLOSE; + +typedef struct s_PXENV_UNDI_TRANSMIT { + pxenv_status_t Status; + uint8_t Protocol; +#define P_UNKNOWN 0 +#define P_IP 1 +#define P_ARP 2 +#define P_RARP 3 + uint8_t XmitFlag; +#define XMT_DESTADDR 0x0000 +#define XMT_BROADCAST 0x0001 + segoff16_t DestAddr; + segoff16_t TBD; + uint32_t Reserved[2]; +} __packed t_PXENV_UNDI_TRANSMIT; +#define MAX_DATA_BLKS 8 +typedef struct s_PXENV_UNDI_TBD { + uint16_t ImmedLength; + segoff16_t Xmit; + uint16_t DataBlkCount; + struct DataBlk { + uint8_t TDPtrType; + uint8_t TDRsvdByte; + uint16_t TDDataLen; + segoff16_t TDDataPtr; + } DataBlock[MAX_DATA_BLKS]; +} __packed t_PXENV_UNDI_TBD; + +typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS { + pxenv_status_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_SET_MCAST_ADDR; + +typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS { + pxenv_status_t Status; + mac_addr_t StationAddress; +} __packed t_PXENV_UNDI_SET_STATION_ADDR; + +typedef struct s_PXENV_UNDI_SET_PACKET_FILTER { + pxenv_status_t Status; + uint8_t filter; +} __packed t_PXENV_UNDI_SET_PACKET_FILTER; + +typedef struct s_PXENV_UNDI_GET_INFORMATION { + pxenv_status_t Status; + uint16_t BaseIo; + uint16_t IntNumber; + uint16_t MaxTranUnit; + uint16_t HwType; +#define ETHER_TYPE 1 +#define EXP_ETHER_TYPE 2 +#define IEEE_TYPE 6 +#define ARCNET_TYPE 7 + uint16_t HwAddrLen; + mac_addr_t CurrentNodeAddress; + mac_addr_t PermNodeAddress; + uint16_t ROMAddress; + uint16_t RxBufCt; + uint16_t TxBufCt; +} __packed t_PXENV_UNDI_GET_INFORMATION; + +typedef struct s_PXENV_UNDI_GET_STATISTICS { + pxenv_status_t Status; + uint32_t XmtGoodFrames; + uint32_t RcvGoodFrames; + uint32_t RcvCRCErrors; + uint32_t RcvResourceErrors; +} __packed t_PXENV_UNDI_GET_STATISTICS; + +typedef struct s_PXENV_UNDI_CLEAR_STATISTICS { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLEAR_STATISTICS; + +typedef struct s_PXENV_UNDI_INITIATE_DIAGS { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_INITIATE_DIAGS; + +typedef struct s_PXENV_UNDI_FORCE_INTERRUPT { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_FORCE_INTERRUPT; + +typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS { + pxenv_status_t Status; + in_addr_t InetAddr; + mac_addr_t MediaAddr; +} __packed t_PXENV_UNDI_GET_MCAST_ADDR; + +typedef struct s_PXENV_UNDI_GET_NIC_TYPE { + pxenv_status_t Status; + uint8_t NicType; +#define PCI_NIC 2 +#define PnP_NIC 3 +#define CardBus_NIC 4 + union { + struct { + uint16_t Vendor_ID; + uint16_t Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint8_t Rev; + uint16_t BusDevFunc; + uint16_t SubVendor_ID; + uint16_t SubDevice_ID; + } pci, cardbus; + struct { + uint32_t EISA_Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint16_t CardSelNum; + } __packed pnp; + } __packed info; +} __packed t_PXENV_UNDI_GET_NIC_TYPE; + +typedef struct s_PXENV_UNDI_GET_IFACE_INFO { + pxenv_status_t Status; + uint8_t IfaceType[16]; + uint32_t LinkSpeed; + uint32_t ServiceFlags; + uint32_t Reserved[4]; +} __packed t_PXENV_UNDI_GET_NDIS_INFO; + +typedef struct s_PXENV_UNDI_GET_STATE { +#define PXE_UNDI_GET_STATE_STARTED 1 +#define PXE_UNDI_GET_STATE_INITIALIZED 2 +#define PXE_UNDI_GET_STATE_OPENED 3 + pxenv_status_t Status; + uint8_t UNDIstate; +} __packed t_PXENV_UNDI_GET_STATE; + +typedef struct s_PXENV_UNDI_ISR { + pxenv_status_t Status; + uint16_t FuncFlag; + uint16_t BufferLength; + uint16_t FrameLength; + uint16_t FrameHeaderLength; + segoff16_t Frame; + uint8_t ProtType; + uint8_t PktType; +} __packed t_PXENV_UNDI_ISR; +#define PXENV_UNDI_ISR_IN_START 1 +#define PXENV_UNDI_ISR_IN_PROCESS 2 +#define PXENV_UNDI_ISR_IN_GET_NEXT 3 +/* One of these will be returned for + PXENV_UNDI_ISR_IN_START */ +#define PXENV_UNDI_ISR_OUT_OURS 0 +#define PXENV_UNDI_USR_OUT_NOT_OURS 1 +/* One of these will be returned for + PXENV_UNDI_ISR_IN_PROCESS and + PXENV_UNDI_ISR_IN_GET_NEXT */ +#define PXENV_UNDI_ISR_OUT_DONE 0 +#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 +#define PXENV_UNDI_ISR_OUT_RECEIVE 3 +#define PXENV_UNDI_ISR_OUT_BUSY 4 + +/* Function numbers and error codes */ + +#define PXENV_TFTP_OPEN 0x0020 +#define PXENV_TFTP_CLOSE 0x0021 +#define PXENV_TFTP_READ 0x0022 +#define PXENV_TFTP_READ_FILE 0x0023 +#define PXENV_TFTP_READ_FILE_PMODE 0x0024 +#define PXENV_TFTP_GET_FSIZE 0x0025 + +#define PXENV_UDP_OPEN 0x0030 +#define PXENV_UDP_CLOSE 0x0031 +#define PXENV_UDP_READ 0x0032 +#define PXENV_UDP_WRITE 0x0033 + +#define PXENV_START_UNDI 0x0000 +#define PXENV_UNDI_STARTUP 0x0001 +#define PXENV_UNDI_CLEANUP 0x0002 +#define PXENV_UNDI_INITIALIZE 0x0003 +#define PXENV_UNDI_RESET_NIC 0x0004 +#define PXENV_UNDI_SHUTDOWN 0x0005 +#define PXENV_UNDI_OPEN 0x0006 +#define PXENV_UNDI_CLOSE 0x0007 +#define PXENV_UNDI_TRANSMIT 0x0008 +#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 +#define PXENV_UNDI_SET_STATION_ADDR 0x000A +#define PXENV_UNDI_SET_PACKET_FILTER 0x000B +#define PXENV_UNDI_GET_INFORMATION 0x000C +#define PXENV_UNDI_GET_STATISTICS 0x000D +#define PXENV_UNDI_CLEAR_STATISTICS 0x000E +#define PXENV_UNDI_INITIATE_DIAGS 0x000F +#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 +#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define PXENV_UNDI_GET_IFACE_INFO 0x0013 +#define PXENV_UNDI_ISR 0x0014 +#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */ +#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */ + +#define PXENV_UNLOAD_STACK 0x0070 +#define PXENV_GET_CACHED_INFO 0x0071 +#define PXENV_RESTART_DHCP 0x0072 +#define PXENV_RESTART_TFTP 0x0073 +#define PXENV_MODE_SWITCH 0x0074 +#define PXENV_START_BASE 0x0075 +#define PXENV_STOP_BASE 0x0076 + +/* gPXE extensions... */ +#define PXENV_FILE_OPEN 0x00e0 +#define PXENV_FILE_CLOSE 0x00e1 +#define PXENV_FILE_SELECT 0x00e2 +#define PXENV_FILE_READ 0x00e3 +#define PXENV_GET_FILE_SIZE 0x00e4 +#define PXENV_FILE_EXEC 0x00e5 +#define PXENV_FILE_API_CHECK 0x00e6 + +/* Exit codes */ +#define PXENV_EXIT_SUCCESS 0x0000 +#define PXENV_EXIT_FAILURE 0x0001 + +/* Status codes */ +#define PXENV_STATUS_SUCCESS 0x00 +#define PXENV_STATUS_FAILURE 0x01 +#define PXENV_STATUS_BAD_FUNC 0x02 +#define PXENV_STATUS_UNSUPPORTED 0x03 +#define PXENV_STATUS_KEEP_UNDI 0x04 +#define PXENV_STATUS_KEEP_ALL 0x05 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 +#define PXENV_STATUS_ARP_TIMEOUT 0x11 +#define PXENV_STATUS_UDP_CLOSED 0x18 +#define PXENV_STATUS_UDP_OPEN 0x19 +#define PXENV_STATUS_TFTP_CLOSED 0x1a +#define PXENV_STATUS_TFTP_OPEN 0x1b +#define PXENV_STATUS_MCOPY_PROBLEM 0x20 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 + +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f +#define PXENV_STATUS_DHCP_TIMEOUT 0x51 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 +#define PXENV_STATUS_LOADER_UNDI_START 0xca +#define PXENV_STATUS_LOADER_BC_START 0xcb + +#endif /* _SYSLINUX_PXE_API_H */ diff --git a/core/include/pxe.h b/core/include/pxe.h index 06cea0a3..1f66032e 100644 --- a/core/include/pxe.h +++ b/core/include/pxe.h @@ -1,164 +1,28 @@ +/* ----------------------------------------------------------------------- + * + * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ -/** -* ----------------------------------------------------------------------- -* -* Copyright 1999-2008 H. Peter Anvin - All Rights Reserved -* -* 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, Inc., 53 Temple Place Ste 330, -* Boston MA 02111-1307, USA; either version 2 of the License, or -* (at your option) any later version; incorporated herein by reference. -* -* ----------------------------------------------------------------------- - -* -* pxe.inc -* -* PXE opcodes -* -*/ +/* + * pxe.h + * + * PXE opcodes + * + */ #ifndef PXE_H #define PXE_H - -#define PXENV_TFTP_OPEN 0x0020 -#define PXENV_TFTP_CLOSE 0x0021 -#define PXENV_TFTP_READ 0x0022 -#define PXENV_TFTP_READ_FILE 0x0023 -#define PXENV_TFTP_READ_FILE_PMODE 0x0024 -#define PXENV_TFTP_GET_FSIZE 0x0025 - -#define PXENV_UDP_OPEN 0x0030 -#define PXENV_UDP_CLOSE 0x0031 -#define PXENV_UDP_READ 0x0032 -#define PXENV_UDP_WRITE 0x0033 - -#define PXENV_START_UNDI 0x0000 -#define PXENV_UNDI_STARTUP 0x0001 -#define PXENV_UNDI_CLEANUP 0x0002 -#define PXENV_UNDI_INITIALIZE 0x0003 -#define PXENV_UNDI_RESET_NIC 0x0004 -#define PXENV_UNDI_SHUTDOWN 0x0005 -#define PXENV_UNDI_OPEN 0x0006 -#define PXENV_UNDI_CLOSE 0x0007 -#define PXENV_UNDI_TRANSMIT 0x0008 -#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 -#define PXENV_UNDI_SET_STATION_ADDR 0x000A -#define PXENV_UNDI_SET_PACKET_FILTER 0x000B -#define PXENV_UNDI_GET_INFORMATION 0x000C -#define PXENV_UNDI_GET_STATISTICS 0x000D -#define PXENV_UNDI_CLEAR_STATISTICS 0x000E -#define PXENV_UNDI_INITIATE_DIAGS 0x000F -#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 -#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 -#define PXENV_UNDI_GET_NIC_TYPE 0x0012 -#define PXENV_UNDI_GET_IFACE_INFO 0x0013 -#define PXENV_UNDI_ISR 0x0014 -#define PXENV_STOP_UNDI 0x0015 -#define PXENV_UNDI_GET_STATE 0x0015 - -#define PXENV_UNLOAD_STACK 0x0070 -#define PXENV_GET_CACHED_INFO 0x0071 -#define PXENV_RESTART_DHCP 0x0072 -#define PXENV_RESTART_TFTP 0x0073 -#define PXENV_MODE_SWITCH 0x0074 -#define PXENV_START_BASE 0x0075 -#define PXENV_STOP_BASE 0x0076 - -/* gPXE extensions... */ -#define PXENV_FILE_OPEN 0x00e0 -#define PXENV_FILE_CLOSE 0x00e1 -#define PXENV_FILE_SELECT 0x00e2 -#define PXENV_FILE_READ 0x00e3 -#define PXENV_GET_FILE_SIZE 0x00e4 -#define PXENV_FILE_EXEC 0x00e5 -#define PXENV_FILE_API_CHECK 0x00e6 - -/* Exit codes */ -#define PXENV_EXIT_SUCCESS 0x0000 -#define PXENV_EXIT_FAILURE 0x0001 - -/* Status codes */ -#define PXENV_STATUS_SUCCESS 0x00 -#define PXENV_STATUS_FAILURE 0x01 -#define PXENV_STATUS_BAD_FUNC 0x02 -#define PXENV_STATUS_UNSUPPORTED 0x03 -#define PXENV_STATUS_KEEP_UNDI 0x04 -#define PXENV_STATUS_KEEP_ALL 0x05 -#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 -#define PXENV_STATUS_ARP_TIMEOUT 0x11 -#define PXENV_STATUS_UDP_CLOSED 0x18 -#define PXENV_STATUS_UDP_OPEN 0x19 -#define PXENV_STATUS_TFTP_CLOSED 0x1a -#define PXENV_STATUS_TFTP_OPEN 0x1b -#define PXENV_STATUS_MCOPY_PROBLEM 0x20 -#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 -#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 -#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 -#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 -#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 -#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 -#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 -#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 -#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 -#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 - -#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 -#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 -#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 -#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 -#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 -#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a -#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b -#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c -#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d -#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e -#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f -#define PXENV_STATUS_DHCP_TIMEOUT 0x51 -#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 -#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 -#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 -#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 -#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b -#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c -#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 -#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 -#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 -#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 -#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 -#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 -#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 -#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 -#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 -#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 -#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 -#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 -#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 -#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 -#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 -#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 -#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 -#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 -#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 -#define PXENV_STATUS_LOADER_UNDI_START 0xca -#define PXENV_STATUS_LOADER_BC_START 0xcb - - - +#include /* - * some other defines + * Some basic defines... */ #define PKTBUF_SIZE (65536 / MAX_OPEN) @@ -168,11 +32,6 @@ #define DNS_MAX_SERVERS 4 #define is_digit(c) (((c) >= '0') && ((c) <= '9')) -#define htons(x) ( ( ((x) & 0xff) << 8) + ( ((x) &0xff00) >> 8) ) -#define ntohs(x) htons(x) -#define htonl(x) ( ( ((x) & 0xff) << 24) + ( ((x) & 0xff00) << 8 ) + \ - ( ((x) & 0xff0000) >> 8 ) + ( ((x) & 0xff000000) >> 24) ) -#define ntohl(x) htonl(x) /* * TFTP operation codes @@ -200,10 +59,58 @@ #define BOOTP_OPTION_MAGIC htonl(0x63825363) #define MAC_MAX 32 - /* * structures */ + +struct pxenv_t { + uint8_t signature[6]; /* PXENV+ */ + uint16_t version; + uint8_t length; + uint8_t checksum; + segoff16_t rmentry; + uint32_t pmoffset; + uint16_t pmselector; + uint16_t stackseg; + uint16_t stacksize; + uint16_t bc_codeseg; + uint16_t bc_codesize; + uint16_t bc_dataseg; + uint16_t bc_datasize; + uint16_t undidataseg; + uint16_t undidatasize; + uint16_t undicodeseg; + uint16_t undicodesize; + segoff16_t pxeptr; +} __packed; + +struct pxe_t { + uint8_t signature[4]; /* !PXE */ + uint8_t structlength; + uint8_t structcksum; + uint8_t structrev; + uint8_t _pad1; + segoff16_t undiromid; + segoff16_t baseromid; + segoff16_t entrypointsp; + segoff16_t entrypointesp; + segoff16_t statuscallout; + uint8_t _pad2; + uint8_t segdesccnt; + uint16_t firstselector; + pxe_segdesc_t seg[7]; +} __packed; + +enum pxe_segments { + PXE_Seg_Stack = 0, + PXE_Seg_UNDIData = 1, + PXE_Seg_UNDICode = 2, + PXE_Seg_UNDICodeWrite = 3, + PXE_Seg_BC_Data = 4, + PXE_Seg_BC_Code = 5, + PXE_Seg_BC_CodeWrite = 6 +}; + struct bootp_t { uint8_t opcode; /* BOOTP/DHCP "opcode" */ uint8_t hardware; /* ARP hreadware type */ @@ -302,8 +209,6 @@ struct gpxe_file_read { uint16_t buffer[2]; } __attribute__ ((packed)); - - /* * functions */ @@ -311,7 +216,4 @@ int ip_ok(uint32_t); void parse_dhcp(int); void parse_dhcp_options(void *, int, int); - - - #endif /* pxe.h */ diff --git a/core/pxe.c b/core/pxe.c index f4afc087..916bf435 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -336,7 +336,6 @@ static int pxe_get_cached_info(int type) */ static int is_url(char *url) { - while (*url) { if(! strncmp(url, "://", 3)) return 1; @@ -1251,42 +1250,43 @@ static void ip_init(void) * return 1 for success, 0 for failure. * */ -static int is_pxe(char *buf) +static int is_pxe(const void *buf) { - int i = buf[4]; + const struct pxe_t *pxe = buf; + const uint8_t *p = buf; + int i = pxe->structlength; uint8_t sum = 0; - if (memcmp(buf, "!PXE", 4) || i < 0x58) + if (i < sizeof(struct pxe_t) || + memcmp(pxe->signature, "!PXE", 4)) return 0; while (i--) - sum += *buf++; + sum += *p++; - if (sum == 0) - return 1; - else - return 0; + return sum == 0; } /** * Just like is_pxe, it checks PXENV+ structure * */ -static int is_pxenv(char *buf) +static int is_pxenv(const void *buf) { - int i = buf[8]; + const struct pxenv_t *pxenv = buf; + const uint8_t *p = buf; + int i = pxenv->length; uint8_t sum = 0; - if (memcmp(buf, "PXENV+", 6) || i < 0x28) + /* The pxeptr field isn't present in old versions */ + if (i < offsetof(struct pxenv_t, pxeptr) || + memcmp(pxenv->signature, "PXENV+", 6)) return 0; while (i--) - sum += *buf++; + sum += *p++; - if (sum == 0) - return 1; - else - return 0; + return sum == 0; } @@ -1309,29 +1309,29 @@ static int is_pxenv(char *buf) ; ********************************************************************/ -static inline int memory_scan(uint16_t seg, int (*func)(char *)) +static const void *memory_scan(uintptr_t start, int (*func)(const void *)) { - while (seg < 0xA000) { - if (func(MK_PTR(seg, 0))) - return 1; /* found it */ - seg++; + const char *ptr; + + /* Scan each 16 bytes of conventional memory before the VGA region */ + for (ptr = (const char *)start; ptr < (const char *)0xA0000; ptr += 16) { + if (func(ptr)) + return ptr; /* found it! */ + ptr += 16; } - return 0; + return NULL; } -static int memory_scan_for_pxe_struct(void) +static const struct pxe_t *memory_scan_for_pxe_struct(void) { extern uint16_t BIOS_fbm; /* Starting segment */ - uint16_t seg = BIOS_fbm << (10 - 4); - return memory_scan(seg, is_pxe); + return memory_scan(BIOS_fbm << 10, is_pxe); } -static int memory_scan_for_pxenv_struct(void) +static const struct pxenv_t *memory_scan_for_pxenv_struct(void) { - uint16_t seg = 0x1000; - - return memory_scan(seg, is_pxenv); + return memory_scan(0x10000, is_pxenv); } /* @@ -1349,11 +1349,16 @@ static int memory_scan_for_pxenv_struct(void) */ static void pxe_init(void) { + extern void pxe_int1a(void); char plan = 'A'; uint16_t seg, off; uint16_t code_seg, code_len; uint16_t data_seg, data_len; char *base = GET_PTR(InitStack); + com32sys_t regs; + const char *type; + const struct pxenv_t *pxenv; + const struct pxe_t *pxe; /* Assume API version 2.1 */ APIVer = 0x201; @@ -1361,43 +1366,39 @@ static void pxe_init(void) /* Plan A: !PXE structure as SS:[SP + 4] */ off = *(uint16_t *)(base + 48); seg = *(uint16_t *)(base + 50); - if (is_pxe(MK_PTR(seg, off))) + pxe = MK_PTR(seg, off); + if (is_pxe(pxe)) goto have_pxe; /* Plan B: PXENV+ structure at [ES:BX] */ plan++; off = *(uint16_t *)(base + 24); /* Original BX */ seg = *(uint16_t *)(base + 4); /* Original ES */ - if (is_pxenv(MK_PTR(seg, off))) + pxenv = MK_PTR(seg, off); + if (is_pxenv(pxenv)) goto have_pxenv; /* * Plan C: PXENV+ structure via INT 1Ah AX=5650h - * - * for now, we just skip it since it must be run in Real mode */ - extern void plan_c(void); plan++; -#if 0 - goto plan_D; - call16(plan_c, regs, regs); - if (((regs->eflags.l & EFLAGS_CF) == 0) && (regs->eax.w[0] == 0x564e)) { - seg = regs->es; - off = regs->ebx.w[0]; - if (is_pxenv(MK_PTR(seg, off))) + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x5650; + call16(pxe_int1a, ®s, ®s); + if (!(regs.eflags.l & EFLAGS_CF) && (regs.eax.w[0] == 0x564e)) { + pxenv = MK_PTR(regs.es, regs.ebx.w[0]); + if (is_pxenv(pxenv)) goto have_pxenv; } - plan_D: -#endif /* Plan D: !PXE memory scan */ plan++; - if (memory_scan_for_pxe_struct()) + if ((pxe = memory_scan_for_pxe_struct())) goto have_pxe; /* Plan E: PXENV+ memory scan */ plan++; - if (memory_scan_for_pxenv_struct()) + if ((pxenv = memory_scan_for_pxenv_struct())) goto have_pxenv; /* Found nothing at all !! */ @@ -1405,59 +1406,51 @@ static void pxe_init(void) call16(kaboom, NULL, NULL); have_pxenv: - base = MK_PTR(seg, off); - APIVer = *(uint16_t *)(base + 6); + APIVer = pxenv->version; printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer); /* if the API version number is 0x0201 or higher, use the !PXE structure */ if (APIVer >= 0x201) { - if (*(char *)(base + 8) < 0x2c) { /* Length of PXENV+ structure in bytes */ - if (memory_scan_for_pxe_struct()) - goto have_pxe; - } - - off = *(uint16_t *)(base + 0x28); - seg = *(uint16_t *)(base + 0x2a); - if (is_pxe(MK_PTR(seg, off))) - goto have_pxe; - /* - * Nope, !PXE structuremissing despite API 2.1+, or at least - * the pointer is missing. Do a last-ditch attempt to find it - */ - if (memory_scan_for_pxe_struct()) - goto have_pxe; + if (pxenv->length >= sizeof(struct pxenv_t)) { + pxe = GET_PTR(pxenv->pxeptr); + if (is_pxe(pxe)) + goto have_pxe; + /* + * Nope, !PXE structure missing despite API 2.1+, or at least + * the pointer is missing. Do a last-ditch attempt to find it + */ + if ((pxe = memory_scan_for_pxe_struct())) + goto have_pxe; + } } /* Otherwise, no dice, use PXENV+ structure */ - data_len = *(uint16_t *)(base + 0x22); /* UNDI data len */ - data_seg = *(uint16_t *)(base + 0x20); /* UNDI data seg */ - code_len = *(uint16_t *)(base + 0x26); /* UNDI code len */ - code_seg = *(uint16_t *)(base + 0x24); /* UNDI code seg */ - PXEEntry = *(far_ptr_t *)(base + 0x0a); /* PXENV+ entry point */ - printf("PXENV+ entry point found (we hope) at "); + data_len = pxenv->undidatasize; + data_seg = pxenv->undidataseg; + code_len = pxenv->undicodesize; + code_seg = pxenv->undicodeseg; + PXEEntry = pxenv->rmentry; + type = "PXENV+"; goto have_entrypoint; have_pxe: - base = MK_PTR(seg, off); - - data_len = *(uint16_t *)(base + 0x2e); /* UNDI data len */ - data_seg = *(uint16_t *)(base + 0x28); /* UNDI data seg */ - code_len = *(uint16_t *)(base + 0x36); /* UNDI code len */ - code_seg = *(uint16_t *)(base + 0x30); /* UNDI code seg */ - PXEEntry = *(far_ptr_t *)(base + 0x10); /* !PXE entry point */ - printf("!PXE entry point found (we hope) at "); + data_len = pxe->seg[PXE_Seg_UNDIData].size; + data_seg = pxe->seg[PXE_Seg_UNDIData].sel; + code_len = pxe->seg[PXE_Seg_UNDICode].size; + code_seg = pxe->seg[PXE_Seg_UNDICode].sel; + PXEEntry = pxe->entrypointsp; + type = "!PXE"; have_entrypoint: - printf("%04X:%04X via plan %c\n", PXEEntry.seg, PXEEntry.offs, plan); + printf("%s entry point found (we hope) at %04X:%04X via plan %c\n", + type, PXEEntry.seg, PXEEntry.offs, plan); printf("UNDI code segment at %04X len %04X\n", code_seg, code_len); - code_seg = code_seg + ((code_len + 15) >> 4); - printf("UNDI data segment at %04X len %04X\n", data_seg, data_len); + + code_seg = code_seg + ((code_len + 15) >> 4); data_seg = data_seg + ((data_len + 15) >> 4); - - + RealBaseMem = MAX(code_seg,data_seg) >> 6; /* Convert to kilobytes */ - //regs->es = regs->ds; /* Restore the es segment */ } /* diff --git a/core/pxelinux.asm b/core/pxelinux.asm index b8077fd9..06e52061 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -290,28 +290,7 @@ _start1: extern pxe_fs_ops mov eax,pxe_fs_ops pm_call fs_init - jmp next -; -; Plan C, because it must be in real mode, we set it here -; - global plan_c -plan_c: - - ; Plan C: PXENV+ structure via INT 1Ah AX=5650h - mov ax, 5650h -%if USE_PXE_PROVIDED_STACK == 0 - lss sp,[InitStack] -%endif - int 1Ah ; May trash regs -%if USE_PXE_PROVIDED_STACK == 0 - lss esp,[BaseStack] -%endif - sti ; Work around Etherboot bug - ret - - -next: ; ; Common initialization code ; @@ -483,6 +462,24 @@ PXEEntry equ pxenv.jump+1 PXEStatus resb 2 + section .text16 +; +; Invoke INT 1Ah on the PXE stack. This is used by the "Plan C" method +; for finding the PXE entry point. +; + global pxe_int1a +pxe_int1a: +%if USE_PXE_PROVIDED_STACK == 0 + mov [cs:PXEStack],sp + mov [cs:PXEStack+2],ss + lss sp,[cs:InitStack] +%endif + int 1Ah ; May trash registers +%if USE_PXE_PROVIDED_STACK == 0 + lss sp,[cs:PXEStack] +%endif + ret + ; ; TimeoutTable: list of timeouts (in 18.2 Hz timer ticks) ; -- cgit v1.2.1 From 0757cb3d6b64e810212024ca51bedbf16120fc6e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 Aug 2009 13:16:13 -0700 Subject: netinet/in.h: adjust hton/ntoh macros to be true constants Tweak the hton/ntoh macros so that they are true constants if the input is a constant expression; this makes them usable in the preprocessor. Signed-off-by: H. Peter Anvin --- com32/include/netinet/in.h | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h index 582632c9..97458bf9 100644 --- a/com32/include/netinet/in.h +++ b/com32/include/netinet/in.h @@ -5,36 +5,45 @@ #include +#define __htons_macro(v) (((v) << 8) | ((v) >> 8)) + static inline uint16_t __htons(uint16_t v) { - return ((v) << 8) | ((v) >> 8); + return __htons_macro(v); } -#define htons(x) __htons(x) -#define ntohs(x) __htons(x) +#define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x)) +#define ntohs(x) htons(x) + +#define __htonl_macro(v) ((((v) & 0x000000ff) << 24) | \ + (((v) & 0x0000ff00) << 8) | \ + (((v) & 0x00ff0000) >> 8) | \ + (((v) & 0xff000000) >> 24)) static inline uint32_t __htonl(uint32_t v) { if (__builtin_constant_p(v)) { - return (((v) & 0x000000ff) << 24) | - (((v) & 0x0000ff00) << 8) | - (((v) & 0x00ff0000) >> 8) | (((v) & 0xff000000) >> 24); + return __htonl_macro(v); } else { -asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0":"+q"(v)); + asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0":"+q"(v)); return v; } } -#define htonl(x) __htonl(x) -#define ntohl(x) __htonl(x) +#define htonl(x) (__builtin_constant_p(x) ? __htonl_macro(x) : __htonl(x)) +#define ntohl(x) htonl(x) + +#define __htonq_macro(v) \ + (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ + (__htonl_macro((uint32_t)((v) >> 32)))) static inline uint64_t __htonq(uint64_t v) { return ((uint64_t) __htonl(v) << 32) | __htonl(v >> 32); } -#define htonq(x) __htonq(x) -#define ntohq(x) __htonq(x) +#define htonq(x) (__builtin_constant_p(x) ? __htonq_macro(x) : __htonq(x)) +#define ntohq(x) htonq(x) typedef uint32_t in_addr_t; typedef uint16_t in_port_t; -- cgit v1.2.1 From 6a1f8b6a4d1b61b43a14b17b4f88319a03b97250 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 Aug 2009 13:17:27 -0700 Subject: pxe: more tweaks to the open (searchdir) routine More tweaks to the open (searchdir) routine, in particular in the OACK packet parsing. From testing it appears substantially more robust now. Signed-off-by: H. Peter Anvin --- core/pxe.c | 245 ++++++++++++++++++++++++++++--------------------------------- 1 file changed, 114 insertions(+), 131 deletions(-) diff --git a/core/pxe.c b/core/pxe.c index 916bf435..033e9ba5 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #define MAX_OPEN_LG2 5 @@ -10,8 +11,6 @@ #define FILENAME_MAX_LG2 7 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX(a,b) (a > b ? a : b) - #define GPXE 1 #define USE_PXE_PROVIDED_STACK 0 @@ -33,14 +32,16 @@ static const uint8_t TimeoutTable[] = { 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 }; -static char *mode = "octet"; -static char *tsize_str = "tsize"; -static int tsize_len = 6; /* We should include the final null here */ - -static char *blksize_str = "blksize"; -static int blksize_len = 8; - -static char *asciidec = "1408"; +struct tftp_options { + const char *str_ptr; /* string pointer */ + size_t offset; /* offset into socket structre */ +}; +static const struct tftp_options tftp_options[] = +{ + { "tsize", offsetof(struct open_file_t, tftp_filesize) }, + { "blksize", offsetof(struct open_file_t, tftp_blksize) }, +}; +static const int tftp_nopts = sizeof tftp_options / sizeof tftp_options[0]; /* * Initialize the Files structure @@ -576,12 +577,10 @@ static void fill_buffer(struct open_file_t *file) pkt.lport = file->tftp_localport; err = pxe_call(PXENV_UDP_READ, &pkt); if (err) { - if (BIOS_timer == old_time) { - printf("."); + if (BIOS_timer == old_time) continue; - } - printf("+"); + BIOS_timer = old_time; timeout--; /* decrease one timer tick */ if (!timeout) { timeout = *timeout_ptr++; @@ -702,44 +701,13 @@ static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, */ static int fill_tail(char *dst) { - char *p = dst; - strcpy(p, mode); - p += strlen(mode) + 1; - - strcpy(p, tsize_str); - p += strlen(tsize_str) + 1; - - strcpy(p, "0"); - p += 2; + static const char tail[] = "octet\0""tsize\0""0\0""blksize\0""1408"; - strcpy(p, blksize_str); - p += strlen(blksize_str) + 1; - - strcpy(p, asciidec); - p += strlen(asciidec) + 1; - - return p - dst; + memcpy(dst, tail, sizeof tail); + return sizeof tail; } -struct tftp_options { - char *str_ptr; /* string pointer */ - int str_len; /* string lenght */ - int offset; /* offset into socket structre */ -}; -static struct tftp_options tftp_options[2]; - -static inline void init_options(void) -{ - tftp_options[0].str_ptr = tsize_str; - tftp_options[0].str_len = tsize_len; - tftp_options[0].offset = (int)&((struct open_file_t *)0)->tftp_filesize; - - tftp_options[1].str_ptr = blksize_str; - tftp_options[1].str_len = blksize_len; - tftp_options[1].offset = (int)&((struct open_file_t *)0)->tftp_blksize; -} - /* * * @@ -759,19 +727,18 @@ static inline void init_options(void) */ static void pxe_searchdir(char *filename, struct file *file) { + extern char tftp_proto_err[]; char *buf = packet_buf; char *p = filename; char *options; - char *src, *dst; char *data; struct open_file_t *open_file; static __lowmem struct pxe_udp_write_pkt uw_pkt; static __lowmem struct pxe_udp_read_pkt ur_pkt; static __lowmem struct gpxe_file_open fo; static __lowmem struct gpxe_get_file_size gs; - struct tftp_options *tftp_opt = tftp_options; + const struct tftp_options *tftp_opt; int i = 0; - int tftp_opts = sizeof tftp_options / sizeof tftp_options[0]; int err; int buffersize; const uint8_t *timeout_ptr; @@ -781,13 +748,14 @@ static void pxe_searchdir(char *filename, struct file *file) uint16_t opcode; uint16_t blk_num; uint32_t ip; - uint32_t filesize = 0; - uint32_t *data_ptr; + uint32_t opdata, *opdata_ptr; - init_options(); open_file = allocate_socket(); - if (!open_file) - goto done; + if (!open_file) { + file->file_len = 0; + file->open_file = NULL; + return; + } timeout_ptr = TimeoutTable; /* Reset timeout */ @@ -825,11 +793,10 @@ static void pxe_searchdir(char *filename, struct file *file) #if 0 err = pxe_call(PXENV_GET_FILE_SIZE, &gs); if (!err) - filesize = gs.filesize; + open_file->tftp_filesize = gs.filesize; else #endif - filesize = -1; - open_file->tftp_filesize = -1; + open_file->tftp_filesize = -1; goto done; } #endif /* GPXE */ @@ -844,10 +811,13 @@ static void pxe_searchdir(char *filename, struct file *file) uw_pkt.buffersize = buf - packet_buf; err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); if (err || uw_pkt.status != 0) - goto failure; /* In fact, the 'failure' target will not do a failure thing; - it will move on to the next timeout, then tries again until - _real_ time out */ - + goto failure; /* + * In fact, the 'failure' target will not do + * a failure thing; it will move on to the + * next timeout, then tries again until + * _real_ time out + */ + /* * Danger, Will Robinson! We need to support tiemout * and retry lest we just lost a packet ... @@ -881,7 +851,7 @@ static void pxe_searchdir(char *filename, struct file *file) timeout_ptr = TimeoutTable; open_file->tftp_remoteport = ur_pkt.rport; - /* filesize <- -1 == unknow */ + /* filesize <- -1 == unknown */ open_file->tftp_filesize = -1; /* Default blksize unless blksize option negotiated */ open_file->tftp_blksize = TFTP_BLOCKSIZE; @@ -893,11 +863,12 @@ static void pxe_searchdir(char *filename, struct file *file) * Get the opcode type, and parse it */ opcode = *(uint16_t *)packet_buf; - if (opcode == TFTP_ERROR) { - filesize = 0; - open_file = NULL; - goto done; /* ERROR reply; don't try again */ - } else if (opcode == TFTP_DATA) { + switch (opcode) { + case TFTP_ERROR: + open_file->tftp_filesize = 0; + break; /* ERROR reply; don't try again */ + + case TFTP_DATA: /* * If the server doesn't support any options, we'll get a * DATA reply instead of OACK. Stash the data in the file @@ -932,94 +903,106 @@ static void pxe_searchdir(char *filename, struct file *file) open_file->tftp_bytesleft = buffersize; open_file->tftp_dataptr = open_file->tftp_pktbuf; - memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize); - goto done; - - } else if (opcode == TFTP_OACK) { + memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize); + break; + + case TFTP_OACK: /* * Now we need to parse the OACK packet to get the transfer * and packet sizes. */ - if (!buffersize) { - filesize = -1; - goto done; /* No options acked */ - } - - /* - * If we find an option which starts with a NUL byte, - * (a null option), we're either seeing garbage that some - * TFTP servers add to the end of the packet, or we have - * no clue how to parse the rest of the packet (what is - * an option name and what is a value?) In either case, - * discard the rest. - */ + options = packet_buf + 2; - if (*options == 0) - goto done; - p = options; + p = options; - do { - dst = src = p; - while (buffersize--) { - if (*src == 0) - break; /* found a final null */ - *dst++ = *src++ | 0x20; - if (!buffersize) - goto done; /* found no final null */ + while (buffersize) { + char *opt = p; + + /* + * If we find an option which starts with a NUL byte, + * (a null option), we're either seeing garbage that some + * TFTP servers add to the end of the packet, or we have + * no clue how to parse the rest of the packet (what is + * an option name and what is a value?) In either case, + * discard the rest. + */ + if (!*opt) + goto done; + + while (buffersize) { + if (!*p) + break; /* Found a final null */ + *p++ |= 0x20; + buffersize--; } - + if (!buffersize) + break; /* Unterminated option */ + + /* Consume the terminal null */ + p++; + buffersize--; + + if (!buffersize) + break; /* No option data */ + /* - * Parse option pointed to by options; guaranteed to be null-terminated + * Parse option pointed to by options; guaranteed to be + * null-terminated */ tftp_opt = tftp_options; - for (i = 0; i < tftp_opts; i++) { - if (!strncmp(p, tftp_opt->str_ptr,tftp_opt->str_len)) + for (i = 0; i < tftp_nopts; i++) { + if (!strcmp(opt, tftp_opt->str_ptr)) break; tftp_opt++; } - if (i == tftp_opts) - goto err_reply; /* Non-negotitated option returned, no idea what it means ...*/ - - p += tftp_opt->str_len; + if (i == tftp_nopts) + goto err_reply; /* Non-negotitated option returned, + no idea what it means ...*/ /* get the address of the filed that we want to write on */ - data_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset); - *data_ptr = 0; + opdata_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset); + opdata = 0; /* do convert a number-string to decimal number, just like atoi */ while (buffersize--) { - if (*p == 0) + uint8_t d = *p++; + if (d == '\0') break; /* found a final null */ - if (*p > '9') + d -= '0'; + if (d > 9) goto err_reply; /* Not a decimal digit */ - *data_ptr = *data_ptr * 10 + *p++ - '0'; + opdata = opdata*10 + d; } - p++; - }while (buffersize); - - } else { - extern char tftp_proto_err[]; - err_reply: - - uw_pkt.rport = open_file->tftp_remoteport; - uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); - uw_pkt.buffer[1] = 0; - uw_pkt.buffersize = 24; - pxe_call(PXENV_UDP_WRITE, &uw_pkt); - printf("TFTP server sent an incomprehesible reply\n"); - call16(kaboom, NULL, NULL); + *opdata_ptr = opdata; + } + break; + + default: + printf("TFTP unknown opcode %d\n", ntohs(opcode)); + goto err_reply; } - filesize = open_file->tftp_filesize; - - done: - if (!filesize) +done: + if (!open_file->tftp_filesize) { free_socket(open_file); - file->file_len = filesize; + file->file_len = 0; + file->open_file = NULL; + return; + } file->open_file = (void *)open_file; + file->file_len = open_file->tftp_filesize; return; - failure: +err_reply: + uw_pkt.rport = open_file->tftp_remoteport; + uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); + uw_pkt.buffer[1] = 0; + uw_pkt.buffersize = 24; + pxe_call(PXENV_UDP_WRITE, &uw_pkt); + printf("TFTP server sent an incomprehesible reply\n"); + call16(kaboom, NULL, NULL); + +failure: timeout_ptr++; if (*timeout_ptr) goto sendreq; /* Try again */ @@ -1450,7 +1433,7 @@ static void pxe_init(void) code_seg = code_seg + ((code_len + 15) >> 4); data_seg = data_seg + ((data_len + 15) >> 4); - RealBaseMem = MAX(code_seg,data_seg) >> 6; /* Convert to kilobytes */ + RealBaseMem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */ } /* -- cgit v1.2.1 From f2fa4525e58ba414220c9f62587b7e7aff35347f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 Aug 2009 17:25:43 -0700 Subject: core: VFS cleanups: add a persistent generic struct file Major cleanups to the VFS layer: - add a persistent generic "struct file" - pass "struct file *" to getfssec - add a close_file method - use VFS-assigned indicies instead of pointers as file handles. This allows the file structures to be allocated from high memory. Signed-off-by: H. Peter Anvin --- core/comboot.inc | 4 +- core/diskfs.inc | 3 -- core/ext2.c | 71 +++++++++++++++++------------ core/extern.inc | 2 +- core/fat.c | 56 ++++++++++++----------- core/fs.c | 133 +++++++++++++++++++++++++++++++++++++++++------------- core/getc.inc | 17 +------ core/include/fs.h | 27 ++++++++--- core/iso9660.c | 22 +++++---- core/isolinux.asm | 2 - core/pxe.c | 32 +++++++------ core/pxelinux.asm | 32 ------------- 12 files changed, 232 insertions(+), 169 deletions(-) diff --git a/core/comboot.inc b/core/comboot.inc index 007c3836..fb0f57f7 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -63,7 +63,7 @@ ; Looks like a COMBOOT image but too large comboot_too_large: - call close_file + pm_call close_file mov si,err_comlarge call writestr jmp enter_command @@ -547,7 +547,7 @@ comapi_read: ; comapi_close: mov si,P_SI - call close_file + pm_call close_file clc ret diff --git a/core/diskfs.inc b/core/diskfs.inc index 87e1bfe7..474657a6 100644 --- a/core/diskfs.inc +++ b/core/diskfs.inc @@ -28,9 +28,6 @@ retry_count equ 16 ; How patient are we with the disk? %assign HIGHMEM_SLOP 0 ; Avoid this much memory near the top LDLINUX_MAGIC equ 0x3eb202fe ; A random number to identify ourselves with -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) -MAX_OPEN equ (1 << MAX_OPEN_LG2) - SECTOR_SHIFT equ 9 SECTOR_SIZE equ (1 << SECTOR_SHIFT) diff --git a/core/ext2.c b/core/ext2.c index b57f1e70..91eff8ff 100644 --- a/core/ext2.c +++ b/core/ext2.c @@ -8,9 +8,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -/* The size of open_file_t in extlinux is double of in others */ -#define MAX_OPEN_LG2 (6 - 1) -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define MAX_SYMLINKS 64 #define SYMLINK_SECTORS 2 @@ -26,7 +23,7 @@ struct open_file_t { uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; @@ -84,19 +81,22 @@ static struct open_file_t *allocate_file(void) /** - * close_file: + * ext2_close_file: * * Deallocates a file structure point by FILE * * @param: file, the file structure we want deallocate * */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *of) { - if (file) - file->file_bytesleft = 0; + of->file_bytesleft = 0; } +static void ext2_close_file(struct file *file) +{ + close_pvt(file->open_file); +} /** * mangle_name: @@ -495,13 +495,14 @@ static void getlinsec_ext(struct fs_info *fs, char *buf, * @return: ECX(of regs), number of bytes read * */ -static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) +static uint32_t ext2_getfssec(struct file *gfile, char *buf, + int sectors, bool *have_more) { int sector_left, next_sector, sector_idx; int frag_start, con_sec_cnt; int bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; if (sectors > sector_left) @@ -528,7 +529,7 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, sector_idx ++; next_sector ++; - }while(next_sector == linsector(fs, sector_idx)); + } while (next_sector == linsector(fs, sector_idx)); #if 0 printf("You are reading data stored at sector --0x%x--0x%x\n", @@ -537,13 +538,14 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, getlinsec_ext(fs, buf, frag_start, con_sec_cnt); buf += con_sec_cnt << 9; file->file_sector += con_sec_cnt; /* next sector index */ - }while(sectors); + } while(sectors); if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; - *have_more = 0; - } else - *have_more = 1; + *have_more = 0; + } else { + *have_more = 1; + } file->file_bytesleft -= bytes_read; return bytes_read; @@ -557,21 +559,28 @@ static uint32_t ext2_getfssec(struct fs_info *fs, char *buf, * find a dir entry, if find return it or return NULL * */ -static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_file_t *file,char *filename) +static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, + struct open_file_t *file, + char *filename) { - int have_more; + bool have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; struct ext2_dir_entry *de; + struct file xfile; + + /* Fake out a VFS file structure */ + xfile.fs = fs; + xfile.open_file = file; /* read a clust at a time */ - ext2_getfssec(fs, trackbuf, file, SecPerClust, &have_more); + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; while (1) { if ((char *)de >= (char *)EndBlock) { if (!have_more) return NULL; - ext2_getfssec(fs, trackbuf, file,SecPerClust,&have_more); + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); de = (struct ext2_dir_entry *)trackbuf; } @@ -595,25 +604,29 @@ static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, struct open_fil } -static char* do_symlink(struct fs_info *fs, struct open_file_t *file, - uint32_t file_len, char *filename) +static char *do_symlink(struct fs_info *fs, struct open_file_t *file, + uint32_t file_len, char *filename) { - int flag, have_more; + int flag; + bool have_more; char *SymlinkTmpBuf = trackbuf; char *lnk_end; - char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + struct file xfile; + xfile.fs = fs; + xfile.open_file = file; flag = this_inode.i_file_acl ? SecPerClust : 0; if (this_inode.i_blocks == flag) { /* fast symlink */ - close_file(file); /* we've got all we need */ + close_pvt(file); /* we've got all we need */ memcpy(SymlinkTmpBuf, this_inode.i_block, file_len); lnk_end = SymlinkTmpBuf + file_len; } else { /* slow symlink */ - ext2_getfssec(fs, SymlinkTmpBuf,file,SYMLINK_SECTORS,&have_more); + ext2_getfssec(&xfile, SymlinkTmpBuf, SYMLINK_SECTORS, &have_more); lnk_end = SymlinkTmpBuf + file_len; } @@ -695,7 +708,7 @@ static void ext2_searchdir(char *filename, struct file *file) inr = de->d_inode; filename += de->d_name_len; - close_file(open_file); + close_pvt(open_file); goto open; } @@ -721,7 +734,7 @@ static void ext2_searchdir(char *filename, struct file *file) /* Otherwise, something bad ... */ err: - close_file(open_file); + close_pvt(open_file); err_noclose: file_len = 0; open_file = NULL; @@ -794,9 +807,11 @@ static int ext2_fs_init(struct fs_info *fs) const struct fs_ops ext2_fs_ops = { .fs_name = "ext2", + .fs_flags = 0, .fs_init = ext2_fs_init, .searchdir = ext2_searchdir, .getfssec = ext2_getfssec, + .close_file = ext2_close_file, .mangle_name = ext2_mangle_name, .unmangle_name = ext2_unmangle_name, .load_config = ext2_load_config diff --git a/core/extern.inc b/core/extern.inc index eb238be0..d944bb1f 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -14,7 +14,7 @@ ; fs.c extern fs_init, searchdir, getfssec, mangle_name, load_config - extern unmangle_name + extern unmangle_name, close_file %if IS_SYSLINUX ; fat.c diff --git a/core/fat.c b/core/fat.c index c1847308..83dc9081 100644 --- a/core/fat.c +++ b/core/fat.c @@ -9,8 +9,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_OPEN_LG2 6 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define ROOT_DIR_WORD 0x002f /* file structure. This holds the information for each currently open file */ @@ -20,7 +18,7 @@ struct open_file_t { uint32_t file_left; /* number of sectors left */ }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; extern uint8_t SecPerClust; @@ -105,12 +103,15 @@ static struct open_file_t *alloc_fill_dir(sector_t sector) /* Deallocates a file structure */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *of) { - if ( file ) - file->file_sector = 0; + of->file_sector = 0; } +static void vfat_close_file(struct file *file) +{ + close_pvt(file->open_file); +} /* Deallocates a directory structure */ @@ -321,11 +322,12 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, * @return: number of bytes read * */ -static uint32_t vfat_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) +static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, + bool *have_more) { uint32_t bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; if ( sectors > file->file_left ) sectors = file->file_left; @@ -669,8 +671,7 @@ static void vfat_searchdir(char *filename, struct file *file) char *p; struct open_file_t *open_file = NULL; - if (file->fs != this_fs) - this_fs = file->fs; + this_fs = file->fs; dir_sector = CurrentDir; if ( *filename == '/' ) { @@ -699,9 +700,10 @@ static void vfat_searchdir(char *filename, struct file *file) mangle_dos_name(MangleBuf, filename); /* close it before open a new dir file */ - close_file(open_file); + if (open_file) + close_pvt(open_file); open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); - if (! open_file) + if (!open_file) goto fail; dir_sector = open_file->file_sector; @@ -721,8 +723,8 @@ static void vfat_searchdir(char *filename, struct file *file) open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; } - file->file_len = file_len; - file->open_file = (void *)open_file; + file->file_len = file_len; + file->open_file = open_file; } @@ -869,13 +871,13 @@ void vfat_readdir(com32sys_t *regs)/* static void vfat_load_config(com32sys_t *regs) { - char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; - char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; - char syslinux_cfg3[] = "/syslinux.cfg"; - char config_name[] = "syslinux.cfg"; + static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; + static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; + static const char syslinux_cfg3[] = "/syslinux.cfg"; + static const char config_name[] = "syslinux.cfg"; - - char *syslinux_cfg[]= {syslinux_cfg1, syslinux_cfg2, syslinux_cfg3}; + const char * const syslinux_cfg[] = + { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 }; com32sys_t oregs; int i = 0; @@ -907,12 +909,10 @@ static void vfat_load_config(com32sys_t *regs) CurrentDir = PrevDir; } -static inline void bsr(uint8_t *res, int num) +static inline __constfunc uint32_t bsr(uint32_t num) { - int i = 0; - while (num >>= 1) - i ++; - *res = i; + asm("bsrl %1,%0" : "=r" (num) : "rm" (num)); + return num; } /* init. the fs meta data, return the block size in bits */ @@ -934,7 +934,7 @@ static int vfat_fs_init(struct fs_info *fs) RootDirSize = (fat.bxRootDirEnts+SECTOR_SIZE/32-1) >> (SECTOR_SHIFT-5); DataArea = RootDirArea + RootDirSize; - bsr(&ClustShift, fat.bxSecPerClust); + ClustShift = bsr(fat.bxSecPerClust); ClustByteShift = ClustShift + SECTOR_SHIFT; ClustMask = fat.bxSecPerClust - 1; ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; @@ -953,9 +953,11 @@ static int vfat_fs_init(struct fs_info *fs) const struct fs_ops vfat_fs_ops = { .fs_name = "vfat", + .fs_flags = 0, .fs_init = vfat_fs_init, .searchdir = vfat_searchdir, .getfssec = vfat_getfssec, + .close_file = vfat_close_file, .mangle_name = vfat_mangle_name, .unmangle_name = vfat_unmangle_name, .load_config = vfat_load_config diff --git a/core/fs.c b/core/fs.c index 0bfa1557..c4bf0387 100644 --- a/core/fs.c +++ b/core/fs.c @@ -4,11 +4,55 @@ #include "fs.h" #include "cache.h" - -/* The this fs pointer */ +/* The currently mounted filesystem */ struct fs_info *this_fs = NULL; struct fs_info fs; +/* Actual file structures (we don't have malloc yet...) */ +static struct file Files[MAX_OPEN]; + +/* + * Get an empty file structure + */ +static struct file *alloc_file(void) +{ + int i; + struct file *file = Files; + + for (i = 0; i < MAX_OPEN; i++) { + if (!file->open_file) + return file; + } + + return NULL; +} + +/* + * Close and free a file structure + */ +static inline void free_file(struct file *file) +{ + memset(file, 0, sizeof *file); +} + +static void _close_file(struct file *file) +{ + if (file->open_file) + file->fs->fs_ops->close_file(file); + free_file(file); +} + +/* + * Convert between a 16-bit file handle and a file structure + */ +static inline uint16_t file_to_handle(struct file *file) +{ + return file ? (file - Files)+1 : 0; +} +static inline struct file *handle_to_file(uint16_t handle) +{ + return handle ? &Files[handle-1] : NULL; +} void load_config(com32sys_t *regs) { @@ -17,8 +61,8 @@ void load_config(com32sys_t *regs) void mangle_name(com32sys_t *regs) { - char *src = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = (char *)MK_PTR(regs->es, regs->edi.w[0]); + char *src = MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = MK_PTR(regs->es, regs->edi.w[0]); this_fs->fs_ops->mangle_name(dst, src); } @@ -39,21 +83,28 @@ void unmangle_name(com32sys_t *regs) void getfssec(com32sys_t *regs) { int sectors; - int have_more; + bool have_more; uint32_t bytes_read; char *buf; - struct file file; + struct file *file; + uint16_t handle; sectors = regs->ecx.w[0]; - buf = (char *)MK_PTR(regs->es, regs->ebx.w[0]); - file.open_file = MK_PTR(regs->ds, regs->esi.w[0]); - file.fs = this_fs; - bytes_read = this_fs->fs_ops->getfssec(file.fs, buf, file.open_file, sectors, &have_more); + handle = regs->esi.w[0]; + file = handle_to_file(handle); + + buf = MK_PTR(regs->es, regs->ebx.w[0]); + bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more); - /* if we reach the EOF, set the si to be NULL */ - if (!have_more) + /* + * If we reach EOF, the filesystem driver will have already closed + * the underlying file... this really should be cleaner. + */ + if (!have_more) { + _close_file(file); regs->esi.w[0] = 0; + } regs->ecx.l = bytes_read; } @@ -62,24 +113,42 @@ void getfssec(com32sys_t *regs) void searchdir(com32sys_t *regs) { char *filename = (char *)MK_PTR(regs->ds, regs->edi.w[0]);; - struct file file; + struct file *file; -#if 1 +#if 0 printf("filename: %s\n", filename); #endif - memset(&file, 0, sizeof file); - file.fs = this_fs; - - this_fs->fs_ops->searchdir(filename, &file); - regs->esi.w[0] = OFFS_WRT(file.open_file, 0); - regs->eax.l = file.file_len; - if (file.open_file) - regs->eflags.l &= ~EFLAGS_ZF; - else - regs->eflags.l |= EFLAGS_ZF; + file = alloc_file(); + + if (file) { + file->fs = this_fs; + file->fs->fs_ops->searchdir(filename, file); + + if (file->open_file) { + regs->esi.w[0] = file_to_handle(file); + regs->eax.l = file->file_len; + regs->eflags.l &= ~EFLAGS_ZF; + return; + } + } + + /* failure... */ + regs->esi.w[0] = 0; + regs->eax.l = 0; + regs->eflags.l |= EFLAGS_ZF; } +void close_file(com32sys_t *regs) +{ + uint16_t handle = regs->esi.w[0]; + struct file *file; + + if (handle) { + file = handle_to_file(handle); + _close_file(file); + } +} /* * it will do: @@ -92,16 +161,18 @@ void searchdir(com32sys_t *regs) void fs_init(com32sys_t *regs) { int blk_shift; - struct fs_ops *ops = (struct fs_ops*)regs->eax.l; - + const struct fs_ops *ops = (const struct fs_ops *)regs->eax.l; + /* set up the fs stucture */ - fs.fs_name = ops->fs_name; fs.fs_ops = ops; - if (!strcmp(fs.fs_name, "pxe")) - fs.fs_dev = NULL; + + /* this is a total hack... */ + if (ops->fs_flags & FS_NODEV) + fs.fs_dev = NULL; /* Non-device filesystem */ else - fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, \ - regs->esi.w[0], regs->edi.w[0]); + fs.fs_dev = device_init(regs->edx.b[0], regs->edx.b[1], regs->ecx.l, + regs->esi.w[0], regs->edi.w[0]); + this_fs = &fs; /* invoke the fs-specific init code */ diff --git a/core/getc.inc b/core/getc.inc index 0aa140b9..48b9f774 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -83,24 +83,11 @@ openfd: .ret: ret .stack_full: - call close_file + pm_call close_file xor ax,ax ; ZF <- 1 pop bx ret -; -; close_file: -; Deallocates a file structure (pointer in SI) -; Assumes CS == DS. -; -close_file: - and si,si - jz .closed - mov dword [si],0 ; First dword == file_bytesleft - xor si,si -.closed: ret - - getc: push bx push si @@ -191,7 +178,7 @@ close: push si mov bx,[CurrentGetC] mov si,[bx+gc_file] - call close_file + pm_call close_file add bx,getc_file_size mov [CurrentGetC],bx pop si diff --git a/core/include/fs.h b/core/include/fs.h index ca4e281a..21e1349d 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -7,26 +7,41 @@ #include "core.h" #include "disk.h" +/* + * Maximum number of open files. This is *currently* constrained by the + * fact that PXE needs to be able to fit all its packet buffers into a + * 64K segment; this should be fixed by moving the packet buffers to high + * memory. + */ +#define MAX_OPEN_LG2 5 +#define MAX_OPEN (1 << MAX_OPEN_LG2) + struct fs_info { - char *fs_name; - struct fs_ops *fs_ops; + const struct fs_ops *fs_ops; struct device *fs_dev; }; +struct open_file_t; /* Filesystem private structure */ + struct file { - void* open_file; /* points to the fs-specific open_file_t */ - struct fs_info *fs; + struct open_file_t *open_file; /* Filesystem private data */ + struct fs_info *fs; uint32_t file_len; }; +enum fs_flags { + FS_NODEV = 1, +}; struct fs_ops { /* in fact, we use fs_ops structure to find the right fs */ - char *fs_name; + const char *fs_name; + enum fs_flags fs_flags; int (*fs_init)(struct fs_info *); void (*searchdir)(char *, struct file *); - uint32_t (*getfssec)(struct fs_info *, char *, void * , int, int *); + uint32_t (*getfssec)(struct file *, char *, int, bool *); + void (*close_file)(struct file *); void (*mangle_name)(char *, char *); int (*unmangle_name)(char *, char *); void (*load_config)(com32sys_t *); diff --git a/core/iso9660.c b/core/iso9660.c index c7e4041b..583513cd 100644 --- a/core/iso9660.c +++ b/core/iso9660.c @@ -10,8 +10,6 @@ #define FILENAME_MAX_LG2 8 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_OPEN_LG2 6 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define ISO_SECTOR_SHIFT 11 #define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) #define ROOT_DIR_WORD 0x002f @@ -24,7 +22,7 @@ struct open_file_t { uint32_t file_left; }; -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; struct dir_t { uint32_t dir_lba; /* Directory start (LBA) */ @@ -73,10 +71,14 @@ static struct open_file_t *allocate_file(void) * Deallocates a file structure * */ -static void close_file(struct open_file_t *file) +static inline void close_pvt(struct open_file_t *file) { - if (file) - file->file_sector = 0; + file->file_sector = 0; +} + +static void iso_close_file(struct file *file) +{ + close_pvt(file->open_file); } /** @@ -373,7 +375,7 @@ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, *res = dir; /* we can close it now */ - close_file(file); + close_pvt(file); /* Mark we got a directory */ return 1; @@ -452,7 +454,7 @@ static void iso_searchdir(char *filename, struct file *file) goto found; } err: - close_file(open_file); + close_pvt(open_file); file_len = 0; open_file = NULL; @@ -535,7 +537,7 @@ static int iso_fs_init(struct fs_info *fs) CurrentDir.dir_len = open_file->file_bytesleft; CurrentDir.dir_clust = open_file->file_left; CurrentDir.dir_lba = open_file->file_sector; - close_file(open_file); + close_pvt(open_file); #ifdef DEBUG printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); @@ -548,9 +550,11 @@ static int iso_fs_init(struct fs_info *fs) const struct fs_ops iso_fs_ops = { .fs_name = "iso", + .fs_flags = 0, .fs_init = iso_fs_init, .searchdir = iso_searchdir, .getfssec = iso_getfssec, + .close_file = iso_close_file, .mangle_name = iso_mangle_name, .unmangle_name = iso_unmangle_name, .load_config = iso_load_config diff --git a/core/isolinux.asm b/core/isolinux.asm index 91541bc6..2816dd8f 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -32,8 +32,6 @@ NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 0 ; Position in which to look retry_count equ 6 ; How patient are we with the BIOS? %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -MAX_OPEN_LG2 equ 6 ; log2(Max number of open files) -MAX_OPEN equ (1 << MAX_OPEN_LG2) SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement) SECTOR_SIZE equ (1 << SECTOR_SHIFT) diff --git a/core/pxe.c b/core/pxe.c index 033e9ba5..0b5102a2 100644 --- a/core/pxe.c +++ b/core/pxe.c @@ -6,15 +6,13 @@ #include #include -#define MAX_OPEN_LG2 5 -#define MAX_OPEN (1 << MAX_OPEN_LG2) #define FILENAME_MAX_LG2 7 #define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define GPXE 1 #define USE_PXE_PROVIDED_STACK 0 -static struct open_file_t __bss16 Files[MAX_OPEN]; +static struct open_file_t Files[MAX_OPEN]; static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; static char *err_pxefailed = "PXE API call failed, error "; @@ -99,10 +97,20 @@ static struct open_file_t *allocate_socket(void) */ static void free_socket(struct open_file_t *file) { - /* tftp_pktbuf is not cleared */ + /* tftp_nextport and tftp_pktbuf are not cleared */ memset(file, 0, offsetof(struct open_file_t, tftp_nextport)); } +static void pxe_close_file(struct file *file) +{ + /* + * XXX: we really should see if the connection is open as send + * a courtesy ERROR packet so the server knows the connection is + * dead. + */ + free_socket(file->open_file); +} + /** * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal * @@ -650,17 +658,14 @@ static void fill_buffer(struct open_file_t *file) * @return: the bytes read * */ -static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, - void *open_file, int blocks, int *have_more) +static uint32_t pxe_getfssec(struct file *gfile, char *buf, + int blocks, bool *have_more) { - struct open_file_t *file = (struct open_file_t *)open_file; + struct open_file_t *file = gfile->open_file; int count = blocks; int chunk; int bytes_read = 0; - sti(); - fs = NULL; /* drop the compile warning message */ - count <<= TFTP_BLOCKSIZE_LG2; while (count) { fill_buffer(file); /* If we have no 'fresh' buffer, get it */ @@ -684,10 +689,9 @@ static uint32_t pxe_getfssec(struct fs_info *fs, char *buf, *have_more = 1; } else if (file->tftp_goteof) { /* - * The socket is closed and the buffer dranined - * close socket structure and re-init for next user + * The socket is closed and the buffer drained; the caller will + * call close_file and therefore free the socket. */ - free_socket(file); *have_more = 0; } @@ -1544,9 +1548,11 @@ static int pxe_fs_init(struct fs_info *fs) const struct fs_ops pxe_fs_ops = { .fs_name = "pxe", + .fs_flags = FS_NODEV, .fs_init = pxe_fs_init, .searchdir = pxe_searchdir, .getfssec = pxe_getfssec, + .close_file = pxe_close_file, .mangle_name = pxe_mangle_name, .unmangle_name = pxe_unmangle_name, .load_config = pxe_load_config diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 06e52061..2e8b3190 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -35,17 +35,7 @@ NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 4 ; Position in which to look REBOOT_TIME equ 5*60 ; If failure, time until full reset %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -MAX_OPEN_LG2 equ 5 ; log2(Max number of open sockets) -MAX_OPEN equ (1 << MAX_OPEN_LG2) -PKTBUF_SIZE equ (65536/MAX_OPEN) ; Per-socket packet buffer size TFTP_PORT equ htons(69) ; Default TFTP port -; Desired TFTP block size -; For Ethernet MTU is normally 1500. Unfortunately there seems to -; be a fair number of networks with "substandard" MTUs which break. -; The code assumes TFTP_LARGEBLK <= 2K. -TFTP_MTU equ 1440 -TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr -; Standard TFTP block size TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block) TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2) @@ -764,29 +754,7 @@ BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack KeepPXE db 0 ; Should PXE be kept around? -; -; TFTP commands -; -tftp_tail db 'octet', 0 ; Octet mode -tsize_str db 'tsize' ,0 ; Request size -tsize_len equ ($-tsize_str) - db '0', 0 -blksize_str db 'blksize', 0 ; Request large blocks -blksize_len equ ($-blksize_str) - asciidec TFTP_LARGEBLK - db 0 -tftp_tail_len equ ($-tftp_tail) - alignz 2 -; -; Options negotiation parsing table (string pointer, string len, offset -; into socket structure) -; -tftp_opt_table: - dw tsize_str, tsize_len, tftp_filesize - dw blksize_str, blksize_len, tftp_blksize -tftp_opts equ ($-tftp_opt_table)/6 - ; ; Error packet to return on TFTP protocol error ; Most of our errors are OACK parsing errors, so use that error code -- cgit v1.2.1 From 73ed95079a6d317db472935a8965f36a63f10140 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 20:23:47 -0700 Subject: core: more filesystem-specific files into subdirectories Preemptively move filesystem-specific files into core/fs/ so we can start trying to pretend to be organized. Signed-off-by: H. Peter Anvin --- core/Makefile | 6 +- core/dhcp_option.c | 261 ------- core/ext2.c | 818 ---------------------- core/ext2_fs.inc | 183 ----- core/fat.c | 964 -------------------------- core/fs/ext2/ext2.c | 818 ++++++++++++++++++++++ core/fs/ext2/ext2_fs.h | 252 +++++++ core/fs/fat/fat.c | 964 ++++++++++++++++++++++++++ core/fs/fat/fat_fs.h | 114 +++ core/fs/iso9660/iso9660.c | 561 +++++++++++++++ core/fs/iso9660/iso9660_fs.h | 21 + core/fs/pxe/dhcp_option.c | 261 +++++++ core/fs/pxe/pxe.c | 1559 ++++++++++++++++++++++++++++++++++++++++++ core/fs/pxe/pxe.h | 219 ++++++ core/include/ext2_fs.h | 252 ------- core/include/fat_fs.h | 114 --- core/include/iso9660_fs.h | 21 - core/include/pxe.h | 219 ------ core/iso9660.c | 561 --------------- core/pxe.c | 1559 ------------------------------------------ 20 files changed, 4772 insertions(+), 4955 deletions(-) delete mode 100644 core/dhcp_option.c delete mode 100644 core/ext2.c delete mode 100644 core/ext2_fs.inc delete mode 100644 core/fat.c create mode 100644 core/fs/ext2/ext2.c create mode 100644 core/fs/ext2/ext2_fs.h create mode 100644 core/fs/fat/fat.c create mode 100644 core/fs/fat/fat_fs.h create mode 100644 core/fs/iso9660/iso9660.c create mode 100644 core/fs/iso9660/iso9660_fs.h create mode 100644 core/fs/pxe/dhcp_option.c create mode 100644 core/fs/pxe/pxe.c create mode 100644 core/fs/pxe/pxe.h delete mode 100644 core/include/ext2_fs.h delete mode 100644 core/include/fat_fs.h delete mode 100644 core/include/iso9660_fs.h delete mode 100644 core/include/pxe.h delete mode 100644 core/iso9660.c delete mode 100644 core/pxe.c diff --git a/core/Makefile b/core/Makefile index 7b03ef6a..d35390f4 100644 --- a/core/Makefile +++ b/core/Makefile @@ -40,8 +40,8 @@ BTARGET = kwdhash.gen \ # All primary source files for the main syslinux files NASMSRC := $(wildcard *.asm) NASMHDR := $(wildcard *.inc) -CSRC := $(wildcard *.c) -SSRC := $(wildcard *.S lzo/*.S) +CSRC := $(wildcard *.c */*.c */*/*.c) +SSRC := $(wildcard *.S */*.S */*/*.S) CHDR := $(wildcard *.h) OTHERSRC := keywords ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(SSRC) $(CHDR) $(OTHERSRC) @@ -130,7 +130,7 @@ tidy dist: rm -f codepage.cp *.o *.elf *.a stupid.* patch.offset .depend .*.d rm -f *.elf.tmp *.sym rm -f *.lsr *.lst *.map *.sec *.raw - rm -f */*.o */*.lst */.*.d + rm -f */*.o */*/*.o */*.lst */*/*.lst */.*.d */*/.*.d rm -f $(OBSOLETE) clean: tidy diff --git a/core/dhcp_option.c b/core/dhcp_option.c deleted file mode 100644 index d9d913fb..00000000 --- a/core/dhcp_option.c +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include -#include - -void parse_dhcp_options(void *, int, int); - -static void subnet_mask(void *data, int opt_len) -{ - if (opt_len != 4) - return; - Netmask = *(uint32_t *)data; -} - -static void router(void *data, int opt_len) -{ - if (opt_len != 4) - return; - Gateway = *(uint32_t *)data; -} - -static void dns_servers(void *data, int opt_len) -{ - int num = opt_len >> 2; - int i; - - if (num > DNS_MAX_SERVERS) - num = DNS_MAX_SERVERS; - - for (i = 0; i < num; i++) { - DNSServers[i] = *(uint32_t *)data; - data += 4; - } - - /* NOT SURE FOR NOW */ - LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0); -} - -static void local_domain(void *data, int opt_len) -{ - com32sys_t regs; - char *p = (char *)data + opt_len; - char end = *p; - - memset(®s, 0, sizeof regs); - *p = '\0'; /* Zero-terminate option */ - regs.esi.w[0] = OFFS_WRT(data, 0); - regs.edi.w[0] = OFFS_WRT(LocalDomain, 0); - call16(dns_mangle, ®s, NULL); - *p = end; /* Resotre ending byte */ -} - -static void vendor_encaps(void *data, int opt_len) -{ - /* Only recongnize PXELINUX options */ - parse_dhcp_options(data, opt_len, 208); -} - -static void option_overload(void *data, int opt_len) -{ - if (opt_len != 1) - return; - OverLoad = *(uint8_t *)data; -} - - -static void server(void *data, int opt_len) -{ - uint32_t ip; - - if (opt_len != 4) - return; - - if (ServerIP) - return; - - ip = *(uint32_t *)data; - if (ip_ok(ip)) - ServerIP = ip; -} - -static void client_identifier(void *data, int opt_len) -{ - if (opt_len > MAC_MAX || opt_len < 2 || - MACLen != (opt_len >> 8) || - *(uint8_t *)data != MACType) - return; - - opt_len --; - MACLen = opt_len & 0xff; - memcpy(MAC, data+1, opt_len); - MAC[opt_len] = 0; -} - -static void bootfile_name(void *data, int opt_len) -{ - strncpy(BootFile, data, opt_len); - BootFile[opt_len] = 0; -} - -static void uuid_client_identifier(void *data, int opt_len) -{ - int type = *(uint8_t *)data; - if (opt_len != 17 || - (type | HaveUUID)) - return; - - HaveUUID = 1; - UUIDType = type; - memcpy(UUID, data+1, 16); - UUID[16] = 0; -} - -static void pxelinux_configfile(void *data, int opt_len) -{ - DHCPMagic |= 2; - strncpy(ConfigName, data, opt_len); - ConfigName[opt_len] = 0; -} - -static void pxelinux_pathprefix(void *data,int opt_len) -{ - DHCPMagic |= 4; - strncpy(PathPrefix, data, opt_len); - PathPrefix[opt_len] = 0; -} - -static void pxelinux_reboottime(void *data, int opt_len) -{ - if ((opt_len && 0xff) != 4) - return ; - - RebootTime = ntohl(*(uint32_t *)data); - DHCPMagic |= 8; /* Got reboot time */ -} - - -struct dhcp_options { - int opt_num; - void (*fun) (void *, int); -}; - -static struct dhcp_options dhcp_opts[] = { - {1, subnet_mask}, - {3, router}, - {6, dns_servers}, - {15, local_domain}, - {43, vendor_encaps}, - {52, option_overload}, - {54, server}, - {61, client_identifier}, - {67, bootfile_name}, - {97, uuid_client_identifier}, - {209, pxelinux_configfile}, - {210, pxelinux_pathprefix}, - {211, pxelinux_reboottime} -}; - -/* - * Parse a sequence of DHCP options, pointed to by _option_; - * -- some DHCP servers leave option fields unterminated - * in violation of the spec. - * - * filter contains the minimum value for the option to recognize - * -- this is used to restrict parsing to PXELINUX-specific options only. - */ -void parse_dhcp_options(void *option, int size, int filter) -{ - uint8_t opt_num; - uint8_t opt_len; - uint8_t opt_filter = filter == 208 ? 208 : 0; - int opt_entries = sizeof(dhcp_opts) / sizeof(dhcp_opts[0]); - int i = 0; - char *p = option; - struct dhcp_options *opt; - - if (opt_filter) - printf("***NOTE!:*** we hit a pxelinux-specific options\n"); - - while (size --) { - opt_num = *p++; - - if (!size) - break; - if (opt_num == 0) - continue; - if (opt_num == 0xff) - break; - - /* Anything else will have a lenght filed */ - opt_len = *p++; /* c <- option lenght */ - size = size - opt_len - 1; - if (size < 0) - break; - if (opt_num < opt_filter) { /* Is the option value valid */ - option += opt_len; /* Try next */ - continue; - } - - opt = dhcp_opts; - for (i = 0; i < opt_entries; i++) { - if (opt_num == opt->opt_num) { - opt->fun(p, opt_len); - break; - } - opt ++; - } - - /* parse next */ - p += opt_len; - } -} - -/* - * - ; - ; parse_dhcp - ; - ; Parse a DHCP packet. This includes dealing with "overloaded" - ; option fields (see RFC 2132, section 9.3) - ; - ; This should fill in the following global variables, if the - ; information is present: - ; - ; MyIP - client IP address - ; ServerIP - boot server IP address - ; Netmask - network mask - ; Gateway - default gateway router IP - ; BootFile - boot file name - ; DNSServers - DNS server IPs - ; LocalDomain - Local domain name - ; MACLen, MAC - Client identifier, if MACLen == 0 - ; - ; This assumes the DHCP packet is in "trackbuf". - ; -*/ -void parse_dhcp(int pkt_len) -{ - struct bootp_t *dhcp = (struct bootp_t *)trackbuf; - int opt_len; - - OverLoad = 0; - if (ip_ok(dhcp->yip)) - MyIP = dhcp->yip; - - if (ip_ok(dhcp->sip)) - ServerIP = dhcp->sip; - - opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options; - if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) - parse_dhcp_options(&dhcp->options, opt_len, 0); - - if (OverLoad & 1) - parse_dhcp_options(&dhcp->bootfile, 128, 0); - else if (dhcp->bootfile[0]) - strcpy(BootFile, dhcp->bootfile); - - if (OverLoad & 2) - parse_dhcp_options(dhcp->sname, 64, 0); -} diff --git a/core/ext2.c b/core/ext2.c deleted file mode 100644 index 91eff8ff..00000000 --- a/core/ext2.c +++ /dev/null @@ -1,818 +0,0 @@ -#include -#include -#include "cache.h" -#include "core.h" -#include "disk.h" -#include "ext2_fs.h" -#include "fs.h" - -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define MAX_SYMLINKS 64 -#define SYMLINK_SECTORS 2 - -/* - * File structure, This holds the information for each currently open file - */ -struct open_file_t { - uint32_t file_bytesleft; /* Number of bytes left (0 = free) */ - uint32_t file_sector; /* Next linear sector to read */ - sector_t file_in_sec; /* Sector where inode lives */ - uint16_t file_in_off; - uint16_t file_mode; - uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ -}; - -static struct open_file_t Files[MAX_OPEN]; - -static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; - -static struct ext2_inode this_inode; -static struct ext2_super_block sb; - -static uint16_t ClustByteShift, ClustShift; -static uint32_t SecPerClust, ClustSize, ClustMask; -static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; -static int DescPerBlock, InodePerBlock; - - -/** - * strecpy: - * - * just like the function strcpy(), except it returns non-zero if overflow. - * - * well, in Syslinux, strcpy() will advance both the dst and src string pointer. - * - */ -static int strecpy(char *dst, char *src, char *end) -{ - while (*src != '\0') - *dst++ = *src++; - *dst = '\0'; - - if (dst > end) - return 1; - else - return 0; -} - - -/** - * allocate_file: - * - * Allocate a file structure - * - * @return: if successful return the file pointer, or return NULL - * - */ -static struct open_file_t *allocate_file(void) -{ - struct open_file_t *file = Files; - int i; - - for (i = 0; i < MAX_OPEN; i++) { - if (file->file_bytesleft == 0) /* found it */ - return file; - file++; - } - - return NULL; /* not found */ -} - - -/** - * ext2_close_file: - * - * Deallocates a file structure point by FILE - * - * @param: file, the file structure we want deallocate - * - */ -static inline void close_pvt(struct open_file_t *of) -{ - of->file_bytesleft = 0; -} - -static void ext2_close_file(struct file *file) -{ - close_pvt(file->open_file); -} - -/** - * mangle_name: - * - * Mangle a filename pointed to by DS:SI(of regs) into a - * buffer pointed to by ES:DI(of regs); ends on encountering - * any whitespace. - * - */ -static void ext2_mangle_name(char *dst, char *src) -{ - char *p = dst; - int i = FILENAME_MAX -1; - - while(*src > ' ') { - if (*src == '/') { - if (*(src+1) == '/') { - src ++; - i --; - continue; - } - } - i --; - *dst++ = *src++; - } - - while (1) { - if (dst == p) - break; - if (*(dst-1) != '/') - break; - - dst --; - i ++; - } - - i ++; - for (; i > 0; i --) - *dst++ = '\0'; -} - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int ext2_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - - -/** - * get_group_desc: - * - * get the group's descriptor of group_num - * - * @param: group_num, the group number; - * - * @return: the pointer of the group's descriptor - * - */ -static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) -{ - block_t block_num; - uint32_t offset; - struct ext2_group_desc *desc; - struct cache_struct *cs; - - block_num = group_num / DescPerBlock; - offset = group_num % DescPerBlock; - - block_num += sb.s_first_data_block + 1; - cs = get_cache_block(fs->fs_dev, block_num); - - desc = (struct ext2_group_desc *)cs->data + offset; - - return desc; -} - - -/** - * read_inode: - * - * read the right inode structure to _dst_. - * - * @param: inode_offset, the inode offset within a group; - * @prarm: dst, wher we will store the inode structure; - * @param: desc, the pointer to the group's descriptor - * @param: block, a pointer used for retruning the blk number for file structure - * @param: offset, same as block - * - */ -static void read_inode(struct fs_info *fs, uint32_t inode_offset, - struct ext2_inode *dst, struct ext2_group_desc *desc, - block_t *block, uint32_t *offset) -{ - struct cache_struct *cs; - struct ext2_inode *inode; - - *block = inode_offset / InodePerBlock + desc->bg_inode_table; - *offset = inode_offset % InodePerBlock; - - cs = get_cache_block(fs->fs_dev, *block); - - /* well, in EXT4, the inode structure usually be 256 */ - inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size))); - memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE); - - /* for file structure */ - *offset = (inode_offset * sb.s_inode_size) % ClustSize; -} - - -/** - * open_inode: - * - * open a file indicated by an inode number in INR - * - * @param : inr, the inode number - * @return: a open_file_t structure pointer - * file length in bytes - * the first 128 bytes of the inode, stores in ThisInode - * - */ -static struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) -{ - struct open_file_t *file; - struct ext2_group_desc *desc; - - uint32_t inode_group, inode_offset; - block_t block_num; - uint32_t block_off; - - file = allocate_file(); - if (!file) - return NULL; - - file->file_sector = 0; - - inr --; - inode_group = inr / sb.s_inodes_per_group; - - /* get the group desc */ - desc = get_group_desc(fs, inode_group); - - inode_offset = inr % sb.s_inodes_per_group; - read_inode(fs, inode_offset, &this_inode, desc, &block_num, &block_off); - - /* Finally, we need to convet it to sector for now */ - file->file_in_sec = (block_num<>SECTOR_SHIFT); - file->file_in_off = block_off & (SECTOR_SIZE - 1); - file->file_mode = this_inode.i_mode; - *file_len = file->file_bytesleft = this_inode.i_size; - - if (*file_len == 0) - return NULL; - - return file; -} - - - -static struct ext4_extent_header * -ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) -{ - struct ext4_extent_idx *index; - struct cache_struct *cs; - block_t blk; - int i; - - while (1) { - if (eh->eh_magic != EXT4_EXT_MAGIC) - return NULL; - - /* got it */ - if (eh->eh_depth == 0) - return eh; - - index = EXT4_FIRST_INDEX(eh); - for (i = 0; i < eh->eh_entries; i++) { - if (block < index[i].ei_block) - break; - } - if (--i < 0) - return NULL; - - blk = index[i].ei_leaf_hi; - blk = (blk << 32) + index[i].ei_leaf_lo; - - /* read the blk to memeory */ - cs = get_cache_block(fs->fs_dev, blk); - eh = (struct ext4_extent_header *)(cs->data); - } -} - -/* handle the ext4 extents to get the phsical block number */ -static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) -{ - struct ext4_extent_header *leaf; - struct ext4_extent *ext; - int i; - block_t start; - - leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); - if (! leaf) { - printf("ERROR, extent leaf not found\n"); - return 0; - } - - ext = EXT4_FIRST_EXTENT(leaf); - for (i = 0; i < leaf->eh_entries; i++) { - if (block < ext[i].ee_block) - break; - } - if (--i < 0) { - printf("ERROR, not find the right block\n"); - return 0; - } - - - /* got it */ - block -= ext[i].ee_block; - if (block >= ext[i].ee_len) - return 0; - - start = ext[i].ee_start_hi; - start = (start << 32) + ext[i].ee_start_lo; - - return start + block; -} - - -/** - * linsector_direct: - * - * @param: block, the block index - * @param: inode, the inode structure - * - * @return: the physic block number - */ -static block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode) -{ - struct cache_struct *cs; - - /* direct blocks */ - if (block < EXT2_NDIR_BLOCKS) - return inode->i_block[block]; - - - /* indirect blocks */ - block -= EXT2_NDIR_BLOCKS; - if (block < PtrsPerBlock1) { - block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; - cs = get_cache_block(fs->fs_dev, ind_block); - - return ((uint32_t *)cs->data)[block]; - } - - /* double indirect blocks */ - block -= PtrsPerBlock1; - if (block < PtrsPerBlock2) { - block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; - cs = get_cache_block(fs->fs_dev, dou_block); - - dou_block = ((uint32_t *)cs->data)[block / PtrsPerBlock1]; - cs = get_cache_block(fs->fs_dev, dou_block); - - return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; - } - - /* triple indirect block */ - block -= PtrsPerBlock2; - if (block < PtrsPerBlock3) { - block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; - cs = get_cache_block(fs->fs_dev, tri_block); - - tri_block = ((uint32_t *)cs->data)[block / PtrsPerBlock2]; - cs = get_cache_block(fs->fs_dev, tri_block); - - tri_block = ((uint32_t *)cs->data)[block % PtrsPerBlock2]; - cs = get_cache_block(fs->fs_dev, tri_block); - - return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; - } - - /* File too big, can not handle */ - printf("ERROR, file too big\n"); - return 0; -} - - -/** - * linsector: - * - * Convert a linear sector index in a file to linear sector number - * - * well, alought this function converts a linear sector number to - * physic sector number, it uses block cache in the implemention. - * - * @param: lin_sector, the lineral sector index - * - * @return: physic sector number - */ -static sector_t linsector(struct fs_info *fs, uint32_t lin_sector) -{ - uint32_t block = lin_sector >> ClustShift; - block_t ret; - struct ext2_inode *inode; - - /* well, this is what I think the variable this_inode used for */ - inode = &this_inode; - - if (inode->i_flags & EXT4_EXTENTS_FLAG) - ret = linsector_extent(fs, block, inode); - else - ret = linsector_direct(fs, block, inode); - - if (!ret) { - printf("ERROR: something error happend at linsector..\n"); - return 0; - } - - /* finally convert it to sector */ - return ((ret << ClustShift) + (lin_sector & ClustMask)); -} - - -/* - * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure. - * - * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller. - */ -static inline int ext2_match_entry (const char * const name, - struct ext2_dir_entry * de) -{ - if (!de->d_inode) - return 0; - return !strncmp(name, de->d_name, de->d_name_len); -} - - -/* - * p is at least 6 bytes before the end of page - */ -static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) -{ - return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); -} - -/** - * getlinsec_ext: - * - * same as getlinsec, except load any sector from the zero - * block as all zeros; use to load any data derived from - * n ext2 block pointer, i.e. anything *except the superblock - * - */ -static void getlinsec_ext(struct fs_info *fs, char *buf, - sector_t sector, int sector_cnt) -{ - int ext_cnt = 0; - struct disk *disk = fs->fs_dev->disk; - - if (sector < SecPerClust) { - ext_cnt = SecPerClust - sector; - memset(buf, 0, ext_cnt << SECTOR_SHIFT); - buf += ext_cnt << SECTOR_SHIFT; - } - - sector += ext_cnt; - sector_cnt -= ext_cnt; - disk->rdwr_sectors(disk, buf, sector, sector_cnt, 0); -} - -/** - * getfssec: - * - * Get multiple sectors from a file - * - * Alought we have made the buffer data based on block size, - * we use sector for implemention; because reading multiple - * sectors (then can be multiple blocks) is what the function - * do. So, let it be based on sectors. - * - * This function can be called from C function, and either from - * ASM function. - * - * @param: ES:BX(of regs), the buffer to store data - * @param: DS:SI(of regs), the pointer to open_file_t - * @param: CX(of regs), number of sectors to read - * - * @return: ECX(of regs), number of bytes read - * - */ -static uint32_t ext2_getfssec(struct file *gfile, char *buf, - int sectors, bool *have_more) -{ - int sector_left, next_sector, sector_idx; - int frag_start, con_sec_cnt; - int bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = gfile->open_file; - struct fs_info *fs = gfile->fs; - - sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; - if (sectors > sector_left) - sectors = sector_left; - - while (sectors) { - /* - * get the frament - */ - sector_idx = file->file_sector; - next_sector = frag_start = linsector(fs, sector_idx); - con_sec_cnt = 0; - - /* get the consective sectors count */ - do { - con_sec_cnt ++; - sectors --; - if (sectors <= 0) - break; - - /* if sectors >= the sectors left in the 64K block, break and read */ - if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1)) - break; - - sector_idx ++; - next_sector ++; - } while (next_sector == linsector(fs, sector_idx)); - -#if 0 - printf("You are reading data stored at sector --0x%x--0x%x\n", - frag_start, frag_start + con_sec_cnt -1); -#endif - getlinsec_ext(fs, buf, frag_start, con_sec_cnt); - buf += con_sec_cnt << 9; - file->file_sector += con_sec_cnt; /* next sector index */ - } while(sectors); - - if (bytes_read >= file->file_bytesleft) { - bytes_read = file->file_bytesleft; - *have_more = 0; - } else { - *have_more = 1; - } - file->file_bytesleft -= bytes_read; - - return bytes_read; -} - - - -/** - * find_dir_entry: - * - * find a dir entry, if find return it or return NULL - * - */ -static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, - struct open_file_t *file, - char *filename) -{ - bool have_more; - char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; - struct ext2_dir_entry *de; - struct file xfile; - - /* Fake out a VFS file structure */ - xfile.fs = fs; - xfile.open_file = file; - - /* read a clust at a time */ - ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); - de = (struct ext2_dir_entry *)trackbuf; - - while (1) { - if ((char *)de >= (char *)EndBlock) { - if (!have_more) - return NULL; - ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); - de = (struct ext2_dir_entry *)trackbuf; - } - - /* Zero inode == void entry */ - if (de->d_inode == 0) { - de = ext2_next_entry(de); - continue; - } - - if (ext2_match_entry (filename, de)) { - filename += de->d_name_len; - if ((*filename == 0) || (*filename == '/')) - return de; /* got it */ - - /* not match, restore the filename then try next */ - filename -= de->d_name_len; - } - - de = ext2_next_entry(de); - } -} - - -static char *do_symlink(struct fs_info *fs, struct open_file_t *file, - uint32_t file_len, char *filename) -{ - int flag; - bool have_more; - - char *SymlinkTmpBuf = trackbuf; - char *lnk_end; - char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; - struct file xfile; - xfile.fs = fs; - xfile.open_file = file; - - flag = this_inode.i_file_acl ? SecPerClust : 0; - if (this_inode.i_blocks == flag) { - /* fast symlink */ - close_pvt(file); /* we've got all we need */ - memcpy(SymlinkTmpBuf, this_inode.i_block, file_len); - lnk_end = SymlinkTmpBuf + file_len; - - } else { - /* slow symlink */ - ext2_getfssec(&xfile, SymlinkTmpBuf, SYMLINK_SECTORS, &have_more); - lnk_end = SymlinkTmpBuf + file_len; - } - - if (*filename != 0) - *lnk_end++ = '/'; - - if (strecpy(lnk_end, filename, SymlinkTmpBufEnd)) - return NULL; /* buffer overflow */ - - /* - * now copy it to the "real" buffer; we need to have - * two buffers so we avoid overwriting the tail on - * the next copy. - */ - strcpy(SymlinkBuf, SymlinkTmpBuf); - - /* return the new path */ - return SymlinkBuf; -} - - - - -/** - * searchdir: - * - * Search the root directory for a pre-mangle filename in FILENAME. - * - * @param: filename, the filename we want to search. - * - * @out : a file pointer, stores in DS:SI (NOTE, DS == 0) - * @out : file lenght in bytes, stores in eax - * - */ -static void ext2_searchdir(char *filename, struct file *file) -{ - extern int CurrentDir; - - struct open_file_t *open_file; - struct ext2_dir_entry *de; - uint8_t file_mode; - uint8_t SymlinkCtr = MAX_SYMLINKS; - uint32_t inr = CurrentDir; - uint32_t ThisDir = CurrentDir; - uint32_t file_len; - - begin_path: - while (*filename == '/') { /* Absolute filename */ - inr = EXT2_ROOT_INO; - filename ++; - } - open: - if ((open_file = open_inode(file->fs, inr, &file_len)) == NULL) - goto err_noclose; - - file_mode = open_file->file_mode >> S_IFSHIFT; - - /* It's a file */ - if (file_mode == T_IFREG) { - if (*filename == '\0') - goto done; - else - goto err; - } - - - /* It's a directory */ - if (file_mode == T_IFDIR) { - ThisDir = inr; - - if (*filename == 0) - goto err; - while (*filename == '/') - filename ++; - - de = find_dir_entry(file->fs, open_file, filename); - if (!de) - goto err; - - inr = de->d_inode; - filename += de->d_name_len; - close_pvt(open_file); - goto open; - } - - - /* - * It's a symlink. We have to determine if it's a fast symlink - * (data stored in the inode) or not (data stored as a regular - * file.) Either which way, we start from the directory - * which we just visited if relative, or from the root directory - * if absolute, and append any remaining part of the path. - */ - if (file_mode == T_IFLNK) { - if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) - goto err; /* too many links or symlink too long */ - - filename = do_symlink(file->fs, open_file, file_len, filename); - if (!filename) - goto err_noclose;/* buffer overflow */ - - inr = ThisDir; - goto begin_path; /* we got a new path, so search it again */ - } - - /* Otherwise, something bad ... */ - err: - close_pvt(open_file); - err_noclose: - file_len = 0; - open_file = NULL; - done: - - file->file_len = file_len; - file->open_file = (void*)open_file; - -#if 0 - if (open_file) { - printf("file bytesleft: %d\n", open_file->file_bytesleft); - printf("file sector : %d\n", open_file->file_sector); - printf("file in sector: %d\n", open_file->file_in_sec); - printf("file offsector: %d\n", open_file->file_in_off); - } -#endif - -} - -static void ext2_load_config(com32sys_t *regs) -{ - char *config_name = "extlinux.conf"; - com32sys_t out_regs; - - strcpy(ConfigName, config_name); - *(uint32_t *)CurrentDirName = 0x00002f2e; - - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); - - regs->eax.w[0] = out_regs.eax.w[0]; - -#if 0 - printf("the zero flag is %s\n", regs->eax.w[0] ? \ - "CLEAR, means we found the config file" : - "SET, menas we didn't find the config file"); -#endif -} - - -/** - * init. the fs meta data, return the block size bits. - */ -static int ext2_fs_init(struct fs_info *fs) -{ - struct disk *disk = fs->fs_dev->disk; -#if 0 - printf("super block@: %p\n", &sb); -#endif - /* read the super block */ - disk->rdwr_sectors(disk, &sb, 2, 2, 0); - - ClustByteShift = sb.s_log_block_size + 10; - ClustSize = 1 << ClustByteShift; - ClustShift = ClustByteShift - SECTOR_SHIFT; - - DescPerBlock = ClustSize >> ext2_group_desc_lg2size; - InodePerBlock = ClustSize / sb.s_inode_size; - - SecPerClust = ClustSize >> SECTOR_SHIFT; - ClustMask = SecPerClust - 1; - - PtrsPerBlock1 = 1 << (ClustByteShift - 2); - PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2); - PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3); - - return ClustByteShift; -} - -const struct fs_ops ext2_fs_ops = { - .fs_name = "ext2", - .fs_flags = 0, - .fs_init = ext2_fs_init, - .searchdir = ext2_searchdir, - .getfssec = ext2_getfssec, - .close_file = ext2_close_file, - .mangle_name = ext2_mangle_name, - .unmangle_name = ext2_unmangle_name, - .load_config = ext2_load_config -}; diff --git a/core/ext2_fs.inc b/core/ext2_fs.inc deleted file mode 100644 index e84efb14..00000000 --- a/core/ext2_fs.inc +++ /dev/null @@ -1,183 +0,0 @@ -; ----------------------------------------------------------------------- -; -; Copyright 1998-2008 H. Peter Anvin - All Rights Reserved -; -; 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, Inc., 675 Mass Ave, Cambridge MA 02139, -; USA; either version 2 of the License, or (at your option) any later -; version; incorporated herein by reference. -; -; ----------------------------------------------------------------------- - -; -; ext2_fs.inc -; -; NASM include file for ext2fs data structures -; - -%define EXT2_SUPER_MAGIC 0xEF53 - -%define EXT2_GOOD_OLD_REV 0 ; The good old (original) format -%define EXT2_DYNAMIC_REV 1 ; V2 format w/ dynamic inode sizes -%define EXT2_GOOD_OLD_INODE_SIZE 128 - -; Special inode numbers -%define EXT2_BAD_INO 1 ; Bad blocks inode -%define EXT2_ROOT_INO 2 ; Root inode -%define EXT2_BOOT_LOADER_INO 5 ; Boot loader inode -%define EXT2_UNDEL_DIR_INO 6 ; Undelete directory inode -%define EXT3_RESIZE_INO 7 ; Reserved group descriptors inode -%define EXT3_JOURNAL_INO 8 ; Journal inode - -; We're readonly, so we only care about incompat features. -%define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 -%define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -%define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 -%define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 -%define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -%define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - -%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) - -; -; File types and file modes -; -%define S_IFDIR 0040000o ; Directory -%define S_IFCHR 0020000o ; Character device -%define S_IFBLK 0060000o ; Block device -%define S_IFREG 0100000o ; Regular file -%define S_IFIFO 0010000o ; FIFO -%define S_IFLNK 0120000o ; Symbolic link -%define S_IFSOCK 0140000o ; Socket - -%define S_IFSHIFT 12 - -%define T_IFDIR (S_IFDIR >> S_IFSHIFT) -%define T_IFCHR (S_IFCHR >> S_IFSHIFT) -%define T_IFBLK (S_IFBLK >> S_IFSHIFT) -%define T_IFREG (S_IFREG >> S_IFSHIFT) -%define T_IFIFO (S_IFIFO >> S_IFSHIFT) -%define T_IFLNK (S_IFLNK >> S_IFSHIFT) -%define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) - -; -; Structure definition for the ext2 superblock -; - struc ext2_super_block -s_inodes_count resd 1 ; Inodes count -s_blocks_count resd 1 ; Blocks count -s_r_blocks_count resd 1 ; Reserved blocks count -s_free_blocks_count resd 1 ; Free blocks count -s_free_inodes_count resd 1 ; Free inodes count -s_first_data_block resd 1 ; First Data Block -s_log_block_size resd 1 ; Block size -s_log_frag_size resd 1 ; Fragment size -s_blocks_per_group resd 1 ; # Blocks per group -s_frags_per_group resd 1 ; # Fragments per group -s_inodes_per_group resd 1 ; # Inodes per group -s_mtime resd 1 ; Mount time -s_wtime resd 1 ; Write time -s_mnt_count resw 1 ; Mount count -s_max_mnt_count resw 1 ; Maximal mount count -s_magic resw 1 ; Magic signature -s_state resw 1 ; File system state -s_errors resw 1 ; Behaviour when detecting errors -s_minor_rev_level resw 1 ; minor revision level -s_lastcheck resd 1 ; time of last check -s_checkinterval resd 1 ; max. time between checks -s_creator_os resd 1 ; OS -s_rev_level resd 1 ; Revision level -s_def_resuid resw 1 ; Default uid for reserved blocks -s_def_resgid resw 1 ; Default gid for reserved blocks -s_first_ino resd 1 ; First non-reserved inode -s_inode_size resw 1 ; size of inode structure -s_block_group_nr resw 1 ; block group # of this superblock -s_feature_compat resd 1 ; compatible feature set -s_feature_incompat resd 1 ; incompatible feature set -s_feature_ro_compat resd 1 ; readonly-compatible feature set -s_uuid resb 16 ; 128-bit uuid for volume -s_volume_name resb 16 ; volume name -s_last_mounted resb 64 ; directory where last mounted -s_algorithm_usage_bitmap resd 1 ; For compression -s_prealloc_blocks resb 1 ; Nr of blocks to try to preallocate -s_prealloc_dir_blocks resb 1 ; Nr to preallocate for dirs -s_padding1 resw 1 -s_reserved resd 204 ; Padding to the end of the block - endstruc - -%ifndef DEPEND -%if ext2_super_block_size != 1024 -%error "ext2_super_block definition bogus" -%endif -%endif - -; -; Structure definition for the ext2 inode -; - struc ext2_inode -i_mode resw 1 ; File mode -i_uid resw 1 ; Owner Uid -i_size resd 1 ; Size in bytes -i_atime resd 1 ; Access time -i_ctime resd 1 ; Creation time -i_mtime resd 1 ; Modification time -i_dtime resd 1 ; Deletion Time -i_gid resw 1 ; Group Id -i_links_count resw 1 ; Links count -i_blocks resd 1 ; Blocks count -i_flags resd 1 ; File flags -l_i_reserved1 resd 1 -i_block resd EXT2_N_BLOCKS ; Pointer to blocks -i_version resd 1 ; File version (for NFS) -i_file_acl resd 1 ; File ACL -i_dir_acl resd 1 ; Directory ACL -i_faddr resd 1 ; Fragment address -l_i_frag resb 1 ; Fragment number -l_i_fsize resb 1 ; Fragment size -i_pad1 resw 1 -l_i_reserved2 resd 2 - endstruc - -%ifndef DEPEND -%if ext2_inode_size != 128 -%error "ext2_inode definition bogus" -%endif -%endif - -; -; Structure definition for ext2 block group descriptor -; - struc ext2_group_desc -bg_block_bitmap resd 1 ; Block bitmap block -bg_inode_bitmap resd 1 ; Inode bitmap block -bg_inode_table resd 1 ; Inode table block -bg_free_blocks_count resw 1 ; Free blocks count -bg_free_inodes_count resw 1 ; Free inodes count -bg_used_dirs_count resw 1 ; Used inodes count -bg_pad resw 1 -bg_reserved resd 3 - endstruc - -%ifndef DEPEND -%if ext2_group_desc_size != 32 -%error "ext2_group_desc definition bogus" -%endif -%endif - -%define ext2_group_desc_lg2size 5 - -; -; Structure definition for ext2 directory entry -; - struc ext2_dir_entry -d_inode resd 1 ; Inode number -d_rec_len resw 1 ; Directory entry length -d_name_len resb 1 ; Name length -d_file_type resb 1 ; File type -d_name equ $ - endstruc diff --git a/core/fat.c b/core/fat.c deleted file mode 100644 index 83dc9081..00000000 --- a/core/fat.c +++ /dev/null @@ -1,964 +0,0 @@ -#include -#include -#include "cache.h" -#include "core.h" -#include "disk.h" -#include "fat_fs.h" -#include "fs.h" - - -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define ROOT_DIR_WORD 0x002f - -/* file structure. This holds the information for each currently open file */ -struct open_file_t { - sector_t file_sector; /* sector pointer ( 0 = structure free ) */ - uint32_t file_bytesleft; /* number of bytes left */ - uint32_t file_left; /* number of sectors left */ -}; - -static struct open_file_t Files[MAX_OPEN]; - -extern uint8_t SecPerClust; - - -/* the fat bpb data */ -static struct fat_bpb fat; -static int FATType = 0; - -/* generic information about FAT fs */ -static sector_t FAT; /* Location of (first) FAT */ -static sector_t RootDirArea; /* Location of root directory area */ -static sector_t RootDir; /* Location of root directory proper */ -static sector_t DataArea; /* Location of data area */ -static uint32_t TotalSectors; /* Total number of sectors */ -static uint32_t ClustSize; /* Bytes/cluster */ -static uint32_t ClustMask; /* Sector/cluster - 1 */ -static uint8_t ClustShift; /* Shift count for sectors/cluster */ -static uint8_t ClustByteShift; /* Shift count for bytes/cluster */ - -static int CurrentDir; -static int PrevDir; - -/* used for long name entry */ -static char MangleBuf[12]; -static char entry_name[14]; - -/* try with the biggest long name */ -static char long_name[0x40 * 13]; -static char *NameStart; -static int NameLen; - -/* do this for readdir, because it called from asm and don't know the fs structure */ -static struct fs_info *this_fs = NULL; - - -/** - * allocate_file: - * - * Allocate a file structure - * - * @return: if successful return the file pointer, or return NULL - * - */ -static struct open_file_t *allocate_file(void) -{ - struct open_file_t *file; - int i = 0; - - file = Files; - - for (; i < MAX_OPEN; i ++ ) { - if ( file->file_sector == 0 ) /* found it */ - return file; - file ++; - } - - return NULL; /* not found */ -} - - -/** - * alloc_fill_dir: - * - * Allocate then fill a file structure for a directory starting in - * sector SECTOR. if successful, return the pointer of filled file - * structure, or return NULL. - * - */ -static struct open_file_t *alloc_fill_dir(sector_t sector) -{ - struct open_file_t *file; - - file = allocate_file(); - if ( !file ) - return NULL; - - file->file_sector = sector; /* current sector */ - file->file_bytesleft = 0; /* current offset */ - file->file_left = sector; /* beginning sector */ - return file; -} - - -/* Deallocates a file structure */ -static inline void close_pvt(struct open_file_t *of) -{ - of->file_sector = 0; -} - -static void vfat_close_file(struct file *file) -{ - close_pvt(file->open_file); -} - - -/* Deallocates a directory structure */ -/*********** -void close_dir(struct fat_dir_entry *dir) -{ - if ( dir ) - *(uint32_t*)dir = 0; -} -***********/ - - -/** - * getfatsector: - * - * check for a particular sector in the FAT cache. - * - */ -static struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) -{ - return get_cache_block(fs->fs_dev, FAT + sector); -} - - -/** - * nextcluster: - * - * Advance a cluster pointer in clust_num to the next cluster - * pointer at in the FAT tables. CF = 0 on return if end of file. - * - * @param: clust_num; - * - * @return: the next cluster number - * - */ -static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) -{ - uint32_t next_cluster; - sector_t fat_sector; - uint32_t offset; - int lo, hi; - struct cache_struct *cs; - - switch(FATType) { - case FAT12: - fat_sector = (clust_num + clust_num / 2) >> SECTOR_SHIFT; - cs = getfatsector(fs, fat_sector); - offset = (clust_num * 3 / 2) & ( SECTOR_SIZE -1 ); - if ( offset == 0x1ff ) { - /* - * we got the end of the one fat sector, - * but we don't got we have(just one byte, we need two), - * so store the low part, then read the next fat - * sector, read the high part, then combine it. - */ - lo = *(uint8_t *)(cs->data + offset); - cs = getfatsector(fs, fat_sector + 1); - hi = *(uint8_t *)cs->data; - next_cluster = (hi << 8) + lo; - } else - next_cluster = *(uint16_t *)(cs->data + offset); - - if ( clust_num & 0x0001 ) - next_cluster >>= 4; /* cluster number is ODD */ - else - next_cluster &= 0x0fff; /* cluster number is EVEN */ - if ( next_cluster > 0x0ff0 ) - goto fail; - break; - - case FAT16: - fat_sector = clust_num >> (SECTOR_SHIFT - 1); - offset = clust_num & ( (1 << (SECTOR_SHIFT-1)) -1); - cs = getfatsector(fs, fat_sector); - next_cluster = ((uint16_t *)cs->data)[offset]; - if ( next_cluster > 0xfff0 ) - goto fail; - break; - - case FAT32: - fat_sector = clust_num >> (SECTOR_SHIFT - 2); - offset = clust_num & ( (1 << (SECTOR_SHIFT-2)) -1); - cs = getfatsector(fs, fat_sector); - next_cluster = ((uint32_t *)cs->data)[offset] & 0x0fffffff; - if ( next_cluster > 0x0ffffff0 ) - goto fail; - break; - } - - return next_cluster; - - fail: - /* got an unexcepted cluster number, so return ZERO */ - return 0; -} - - - -/** - * nextsector: - * - * given a sector on input, return the next sector of the - * same filesystem object, which may be the root directory or a - * cluster chain. Returns EOF. - * - */ -static sector_t nextsector(struct fs_info *fs, sector_t sector) -{ - sector_t data_sector; - uint32_t cluster; - - if ( sector < DataArea ) { - sector ++; - /* if we reached the end of root area */ - if ( sector == DataArea ) - sector = 0; /* return 0 */ - return sector; - } - - data_sector = sector - DataArea; - if ( (data_sector+1) & ClustMask ) /* in a cluster */ - return (++sector); - - /* got a new cluster */ - cluster = nextcluster(fs, (data_sector >> ClustShift) + 2); - if ( !cluster ) - return 0; - - /* return the start of the new cluster */ - sector = ( (cluster - 2) << ClustShift ) + DataArea; - return sector; -} - - - - - -/** - * __getfssec: - * - * get multiple sectors from a file - * - * This routine makes sure the subransfers do not cross a 64K boundary - * and will correct the situation if it does, UNLESS *sectos* cross - * 64K boundaries. - * - * @param: buf - * @param: file structure - * @param: sectors - * - */ -static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, uint32_t sectors) -{ - sector_t curr_sector = file->file_sector; - sector_t frag_start , next_sector; - uint32_t con_sec_cnt; - struct disk *disk = fs->fs_dev->disk; - - while (sectors) { - /* get fragment */ - con_sec_cnt = 0; - frag_start = curr_sector; - - do { - /* get consective sector count */ - con_sec_cnt ++; - sectors --; - if ( sectors == 0 ) - break; - - next_sector = nextsector(fs, curr_sector); - if ( !next_sector ) - break; - }while( next_sector == (++curr_sector) ); - -#if 0 - printf("You are reading data stored at sector --0x%x--0x%x\n", - frag_start, frag_start + con_sec_cnt -1); -#endif - - /* do read */ - disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0); - buf += con_sec_cnt << 9;/* adjust buffer pointer */ - - if ( !sectors ) - break; - //curr_sector --; /* this is the last sector actually read */ - curr_sector = next_sector; - } - - /* update the file_sector filed for the next read */ - file->file_sector = nextsector(fs, curr_sector); -} - - - -/** - * getfssec: - * - * get multiple sectors from a file - * - * - * @param: buf - * @param: file - * @param: sectors - * @param: have_more - * - * @return: number of bytes read - * - */ -static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, - bool *have_more) -{ - uint32_t bytes_read = sectors << SECTOR_SHIFT; - struct open_file_t *file = gfile->open_file; - struct fs_info *fs = gfile->fs; - - if ( sectors > file->file_left ) - sectors = file->file_left; - - __getfssec(fs, buf, file, sectors); - - if ( bytes_read >= file->file_bytesleft ) { - bytes_read = file->file_bytesleft; - *have_more = 0; - } else - *have_more = 1; - file->file_bytesleft -= bytes_read; - file->file_left -= sectors; - - return bytes_read; -} - -/** - * mangle_name: - * - * Mangle a filename pointed to by src into a buffer pointed to by dst; - * ends on encountering any whitespace. - * - */ -static void vfat_mangle_name(char *dst, char *src) -{ - char *p = dst; - int i = FILENAME_MAX -1; - - while(*src > ' ') { - if ( *src == '\\' ) - *src = '/'; - - if (*src == '/') { - if (*(src+1) == '/') { - src ++; - i --; - continue; - } - } - i --; - *dst++ = *src++; - } - - while (1) { - if (dst == p) - break; - if ((*(dst-1) != '/') && (*(dst-1) != '.')) - break; - - dst --; - i ++; - } - - i ++; - for (; i > 0; i --) - *dst++ = '\0'; -} - - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int vfat_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - -/** - * mangle_dos_name: - * - * Mangle a dos filename component pointed to by FILENAME - * into MangleBuf; ends on encountering any whitespace or - * slash. - * - * WARNING: saves pointers into the buffer for longname matchs! - * - * @param: filename - * @param: MangleBuf - * - */ -/** - * for now, it can't handle this case: - * xyxzxyxjfdkfjdjf.txt as it will just output the first 11 chars - * but not care the dot char at the later, so I think we need do - * this, but it seems that the SYSLINUX doesn't do it, so I will - * make it stay as what it was orignal. - * - */ -static void mangle_dos_name(char *MangleBuf, char *filename) -{ - - char *dst = MangleBuf; - char *src = filename; - int i = 0; - unsigned char c; - - NameStart = filename; - - for (; i < 11; i ++) - MangleBuf[i] = ' '; - - for (i = 0; i < 11; i++) { - c = *src ++; - - if ( (c <= ' ') || (c == '/') ) - break; - - if ( c == '.' ) { - dst = &MangleBuf[8]; - i = 7; - continue; - } - - if (c >= 'a' && c <= 'z') - c -= 32; - if ( (c == 0xe5) && (i == 11) ) - c = 0x05; - - *dst++ = c; - } - MangleBuf[12] = '\0'; - - while( (*src != '/') && (*src > ' ') ) - src ++; - - NameLen = src - filename; -} - - - -static void unicode_to_ascii(char *entry_name, uint16_t *unicode_buf) -{ - int i = 0; - - for (; i < 13; i++) { - if ( unicode_buf[i] == 0xffff ) { - entry_name[i] = '\0'; - return; - } - entry_name[i] = (char)unicode_buf[i]; - } -} - -/** - * long_entry_name: - * - * get the long entry name - * - */ -static void long_entry_name(struct fat_long_name_entry *dir) -{ - uint16_t unicode_buf[13]; - - memcpy(unicode_buf, dir->name1, 5 * 2); - memcpy(unicode_buf + 5, dir->name2, 6 * 2); - memcpy(unicode_buf + 11,dir->name3, 2 * 2); - - unicode_to_ascii(entry_name, unicode_buf); - -} - - -static uint8_t get_checksum(char *dir_name) -{ - int i; - uint8_t sum=0; - - for (i=11; i; i--) - sum = ((sum & 1) << 7) + (sum >> 1) + *dir_name++; - return sum; -} - -/* compute the first sector number of one dir where the data stores */ -static inline sector_t first_sector(struct fat_dir_entry *dir) -{ - uint32_t first_clust, sector; - - first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low; - sector = ((first_clust - 2) << ClustShift) + DataArea; - - return sector; -} - - -/** - * search_dos_dir: - * - * search a specific directory for a pre-mangled filename in - * MangleBuf, in the directory starting in sector SECTOR - * - * NOTE: This file considers finding a zero-length file an - * error. This is so we don't have to deal with that special - * case elsewhere in the program (most loops have the test - * at the end). - * - * @param: MangleBuf - * @param: dir_sector, directory sector - * - * @out: file pointer - * @out: file length (MAY BE ZERO!) - * @out: file attribute - * @out: dh, clobbered. - * - */ -static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, - uint32_t dir_sector, uint32_t *file_len, uint8_t *attr) -{ - struct open_file_t* file; - struct cache_struct* cs; - struct fat_dir_entry *dir; - struct fat_long_name_entry *long_dir; - - uint8_t VFATInit, VFATNext, VFATCsum; - uint8_t id; - uint32_t slots; - uint32_t entries; - int checksum; - - file = allocate_file(); - if ( !file ) - return NULL; - - /* - * Compute the value of a possible VFAT longname - * "last" entry (which, of coures, comes first ...) - */ - slots = (NameLen + 12) / 13; - slots |= 0x40; - VFATInit = slots; - VFATNext = slots; - - do { - cs = get_cache_block(fs->fs_dev, dir_sector); - dir = (struct fat_dir_entry *)cs->data; - entries = SECTOR_SIZE / 32; - - /* scan all the entries in a sector */ - do { - if ( dir->name[0] == 0 ) - return NULL; /* Hit directory high water mark */ - - if ( dir->attr == 0x0f ) { - /* it's a long name entry */ - long_dir = (struct fat_long_name_entry *)dir; - id = long_dir->id; - if ( id !=VFATNext ) - goto not_match; - - if ( id & 0x40 ) { - /*get the initial checksum value*/ - VFATCsum = long_dir->checksum; - } else { - if ( long_dir->checksum != VFATCsum ) - goto not_match; - } - - id &= 0x3f; - VFATNext = --id; - - /* got the long entry name */ - long_entry_name(long_dir); - memcpy(long_name + id * 13, entry_name, 13); - - /* - * if we got the last entry? - * if so, check it, or go on with the next entry - */ - if ( id == 0 ) { - if ( strcmp(long_name, NameStart) ) - goto not_match; - } - - goto next_entry; - - } else { - /* it's a short entry */ - if ( dir->attr & 0x08 ) /* ingore volume labels */ - goto not_match; - - - /* If we have a long name match, then VFATNext must be 0 */ - if ( !VFATNext ) { - /* - * we already have a VFAT long name match, however, - * the match is only valid if the checksum matchs. - */ - checksum = get_checksum(dir->name); - if ( checksum == VFATCsum ) - goto found; /* got a match on long name */ - - } else { - if ( strncmp(MangleBuf, dir->name, 11) == 0 ) - goto found; - } - } - - not_match:/* find it again */ - VFATNext = VFATInit; - - next_entry: - dir ++; - - }while ( --entries ); - - dir_sector = nextsector(fs, dir_sector); - - }while ( dir_sector ); /* scan another secotr */ - - found: - *file_len = file->file_bytesleft = dir->file_size; - file->file_sector = first_sector(dir); - *attr = dir->attr; - - return file; -} - - - -/** - * searchdir: - * - * open a file - * - * @param: filename, the file we wanna open - * @param: file_len, to return the file length - * - * @return: return the file structure on successful, or NULL. - * - */ -static void vfat_searchdir(char *filename, struct file *file) -{ - sector_t dir_sector; - uint32_t file_len = 0; - uint8_t attr = 0; - char *p; - struct open_file_t *open_file = NULL; - - this_fs = file->fs; - - dir_sector = CurrentDir; - if ( *filename == '/' ) { - dir_sector = RootDir; - if (*(filename + 1) == 0) /* root dir is what we need */ - goto found_dir; - } - - while ( *filename ) { - if (*filename == '/') - filename++; /* skip '/' */ - p = filename; - if (*p == 0) - break; - PrevDir = dir_sector; - - /* try to find the end */ - while ( (*p > ' ') && (*p != '/') ) - p ++; - - if (filename == p) { - /* found a dir */ - dir_sector = PrevDir; - goto found_dir; - } - - mangle_dos_name(MangleBuf, filename); - /* close it before open a new dir file */ - if (open_file) - close_pvt(open_file); - open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); - if (!open_file) - goto fail; - - dir_sector = open_file->file_sector; - filename = p; - } - - if (attr & 0x10) { - dir_sector = PrevDir; - found_dir: - open_file = alloc_fill_dir(dir_sector); - } else if ( (attr & 0x18) || (file_len == 0) ) { - fail: - file_len = 0; - open_file = NULL; - } else { - open_file->file_bytesleft = file_len; - open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; - } - - file->file_len = file_len; - file->open_file = open_file; -} - - - - -/** - * readdir: - * - * read one file from a directory - * - * returns the file's name in the filename string buffer - * - * @param: filename - * @param: file - * - */ -void vfat_readdir(com32sys_t *regs)/* - struct fs_info *fs, struct open_file_t* dir_file, - char* filename, uint32_t *file_len, uint8_t *attr) - */ -{ - uint32_t sector, sec_off; - /* make it to be 1 to check if we have met a long name entry before */ - uint8_t id = 1; - uint8_t init_id, next_id; - uint8_t entries_left; - int i; - - char *filename = MK_PTR(regs->es, regs->edi.w[0]); - struct open_file_t *dir_file = MK_PTR(regs->ds, regs->esi.w[0]); - - struct cache_struct *cs; - struct fat_dir_entry *dir; - struct fat_long_name_entry *long_dir; - struct open_file_t file; - - sector = dir_file->file_sector; - sec_off = dir_file->file_bytesleft; - if (!sector) - goto fail; - - entries_left = (SECTOR_SIZE - sec_off) >> 5; - cs = get_cache_block(this_fs->fs_dev, sector); - dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ - - while ( 1 ) { - if ( dir->name[0] == 0 ) - goto fail; - - if ( dir->attr == FAT_ATTR_LONG_NAME ) { - /* it's a long name */ - long_dir = (struct fat_long_name_entry *)dir; - - if ( long_dir->id & 0x40 ) { - init_id = id = long_dir->id & 0x3f; - id--; - } else { - next_id = (long_dir->id & 0x3f) - 1; - id--; - if ( id != next_id ) - goto next_entry; - } - - long_entry_name(long_dir); - memcpy(filename + id * 13, entry_name, 13); - - - /* - * we need go on with the next entry - * and we will fall through to next entry - */ - - } else { - /* it's a short entry */ - - if ( !id ) /* we got a long name match */ - break; - - if ( dir->attr & FAT_ATTR_VOLUME_ID ) - goto next_entry; - - for( i = 0; i < 8; i ++) { - if ( dir->name[i] == ' ' ) - break; - *filename++ = dir->name[i]; - } - - *filename++ = '.'; - - for ( i = 8; i < 11; i ++) { - if ( dir->name[i] == ' ' ) - break; - *filename ++ = dir->name[i]; - } - - /* check if we have got an extention */ - if (*(filename - 1) == '.') - *(filename - 1) = '\0'; - else - *filename = '\0'; - - break; - } - - next_entry: - dir ++; - entries_left --; - - if ( !entries_left ) { - sector = nextsector(this_fs, sector); - if ( !sector ) - goto fail; - cs = get_cache_block(this_fs->fs_dev, sector); - dir = (struct fat_dir_entry *)cs->data; - } - } - - /* finally , we get what we want */ - entries_left --; - if ( !entries_left ) { - sector = nextsector(this_fs, sector); - if ( !sector ) - goto fail; - dir_file->file_bytesleft = 0; - } else - dir_file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); - dir_file->file_sector = sector; - - file.file_sector = sector; - file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT) ) & 0xffff; - - regs->eax.l = dir->file_size; - regs->ebx.l = first_sector(dir); - regs->edx.b[0] = dir->attr; - - return; - - fail: - //close_dir(dir); - regs->eax.l = 0; - regs->esi.w[0] = 0; - regs->eflags.l |= EFLAGS_CF; -} - -static void vfat_load_config(com32sys_t *regs) -{ - static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; - static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; - static const char syslinux_cfg3[] = "/syslinux.cfg"; - static const char config_name[] = "syslinux.cfg"; - - const char * const syslinux_cfg[] = - { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 }; - com32sys_t oregs; - int i = 0; - - *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; - CurrentDir = RootDir; - - /* - * we use the ConfigName to pass the config path because - * it is under the address 0xffff - */ - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - for (; i < 3; i++) { - strcpy(ConfigName, syslinux_cfg[i]); - memset(&oregs, 0, sizeof oregs); - call16(core_open, regs, &oregs); - - /* if zf flag set, then failed; try another */ - if (! (oregs.eflags.l & EFLAGS_ZF)) - break; - } - if ( i == 3 ) { - printf("no config file found\n"); - return; /* no config file */ - } - - strcpy(ConfigName, config_name); - strcpy(CurrentDirName, syslinux_cfg[i]); - CurrentDirName[strlen(syslinux_cfg[i])-strlen(config_name)] = '\0'; - CurrentDir = PrevDir; -} - -static inline __constfunc uint32_t bsr(uint32_t num) -{ - asm("bsrl %1,%0" : "=r" (num) : "rm" (num)); - return num; -} - -/* init. the fs meta data, return the block size in bits */ -static int vfat_fs_init(struct fs_info *fs) -{ - int sectors_per_fat; - uint32_t clust_num; - int RootDirSize; - struct disk *disk = fs->fs_dev->disk; - - /* get the fat bpb information */ - disk->rdwr_sectors(disk, &fat, 0, 1, 0); - - TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; - FAT = fat.bxResSectors; - - sectors_per_fat = fat.bxFATsecs ? : fat.u.fat32.bxFATsecs_32; - RootDir = RootDirArea = FAT + sectors_per_fat * fat.bxFATs; - RootDirSize = (fat.bxRootDirEnts+SECTOR_SIZE/32-1) >> (SECTOR_SHIFT-5); - DataArea = RootDirArea + RootDirSize; - - ClustShift = bsr(fat.bxSecPerClust); - ClustByteShift = ClustShift + SECTOR_SHIFT; - ClustMask = fat.bxSecPerClust - 1; - ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; - - clust_num = (TotalSectors - DataArea) >> ClustShift; - if ( clust_num < 4085 ) - FATType = FAT12; - else if ( clust_num < 65525 ) - FATType = FAT16; - else - FATType = FAT32; - - /* for SYSLINUX, the cache is based on sector size */ - return SECTOR_SHIFT; -} - -const struct fs_ops vfat_fs_ops = { - .fs_name = "vfat", - .fs_flags = 0, - .fs_init = vfat_fs_init, - .searchdir = vfat_searchdir, - .getfssec = vfat_getfssec, - .close_file = vfat_close_file, - .mangle_name = vfat_mangle_name, - .unmangle_name = vfat_unmangle_name, - .load_config = vfat_load_config -}; diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c new file mode 100644 index 00000000..91eff8ff --- /dev/null +++ b/core/fs/ext2/ext2.c @@ -0,0 +1,818 @@ +#include +#include +#include "cache.h" +#include "core.h" +#include "disk.h" +#include "ext2_fs.h" +#include "fs.h" + +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) +#define MAX_SYMLINKS 64 +#define SYMLINK_SECTORS 2 + +/* + * File structure, This holds the information for each currently open file + */ +struct open_file_t { + uint32_t file_bytesleft; /* Number of bytes left (0 = free) */ + uint32_t file_sector; /* Next linear sector to read */ + sector_t file_in_sec; /* Sector where inode lives */ + uint16_t file_in_off; + uint16_t file_mode; + uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ +}; + +static struct open_file_t Files[MAX_OPEN]; + +static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; + +static struct ext2_inode this_inode; +static struct ext2_super_block sb; + +static uint16_t ClustByteShift, ClustShift; +static uint32_t SecPerClust, ClustSize, ClustMask; +static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; +static int DescPerBlock, InodePerBlock; + + +/** + * strecpy: + * + * just like the function strcpy(), except it returns non-zero if overflow. + * + * well, in Syslinux, strcpy() will advance both the dst and src string pointer. + * + */ +static int strecpy(char *dst, char *src, char *end) +{ + while (*src != '\0') + *dst++ = *src++; + *dst = '\0'; + + if (dst > end) + return 1; + else + return 0; +} + + +/** + * allocate_file: + * + * Allocate a file structure + * + * @return: if successful return the file pointer, or return NULL + * + */ +static struct open_file_t *allocate_file(void) +{ + struct open_file_t *file = Files; + int i; + + for (i = 0; i < MAX_OPEN; i++) { + if (file->file_bytesleft == 0) /* found it */ + return file; + file++; + } + + return NULL; /* not found */ +} + + +/** + * ext2_close_file: + * + * Deallocates a file structure point by FILE + * + * @param: file, the file structure we want deallocate + * + */ +static inline void close_pvt(struct open_file_t *of) +{ + of->file_bytesleft = 0; +} + +static void ext2_close_file(struct file *file) +{ + close_pvt(file->open_file); +} + +/** + * mangle_name: + * + * Mangle a filename pointed to by DS:SI(of regs) into a + * buffer pointed to by ES:DI(of regs); ends on encountering + * any whitespace. + * + */ +static void ext2_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX -1; + + while(*src > ' ') { + if (*src == '/') { + if (*(src+1) == '/') { + src ++; + i --; + continue; + } + } + i --; + *dst++ = *src++; + } + + while (1) { + if (dst == p) + break; + if (*(dst-1) != '/') + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i --) + *dst++ = '\0'; +} + +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int ext2_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + + +/** + * get_group_desc: + * + * get the group's descriptor of group_num + * + * @param: group_num, the group number; + * + * @return: the pointer of the group's descriptor + * + */ +static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) +{ + block_t block_num; + uint32_t offset; + struct ext2_group_desc *desc; + struct cache_struct *cs; + + block_num = group_num / DescPerBlock; + offset = group_num % DescPerBlock; + + block_num += sb.s_first_data_block + 1; + cs = get_cache_block(fs->fs_dev, block_num); + + desc = (struct ext2_group_desc *)cs->data + offset; + + return desc; +} + + +/** + * read_inode: + * + * read the right inode structure to _dst_. + * + * @param: inode_offset, the inode offset within a group; + * @prarm: dst, wher we will store the inode structure; + * @param: desc, the pointer to the group's descriptor + * @param: block, a pointer used for retruning the blk number for file structure + * @param: offset, same as block + * + */ +static void read_inode(struct fs_info *fs, uint32_t inode_offset, + struct ext2_inode *dst, struct ext2_group_desc *desc, + block_t *block, uint32_t *offset) +{ + struct cache_struct *cs; + struct ext2_inode *inode; + + *block = inode_offset / InodePerBlock + desc->bg_inode_table; + *offset = inode_offset % InodePerBlock; + + cs = get_cache_block(fs->fs_dev, *block); + + /* well, in EXT4, the inode structure usually be 256 */ + inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size))); + memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE); + + /* for file structure */ + *offset = (inode_offset * sb.s_inode_size) % ClustSize; +} + + +/** + * open_inode: + * + * open a file indicated by an inode number in INR + * + * @param : inr, the inode number + * @return: a open_file_t structure pointer + * file length in bytes + * the first 128 bytes of the inode, stores in ThisInode + * + */ +static struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) +{ + struct open_file_t *file; + struct ext2_group_desc *desc; + + uint32_t inode_group, inode_offset; + block_t block_num; + uint32_t block_off; + + file = allocate_file(); + if (!file) + return NULL; + + file->file_sector = 0; + + inr --; + inode_group = inr / sb.s_inodes_per_group; + + /* get the group desc */ + desc = get_group_desc(fs, inode_group); + + inode_offset = inr % sb.s_inodes_per_group; + read_inode(fs, inode_offset, &this_inode, desc, &block_num, &block_off); + + /* Finally, we need to convet it to sector for now */ + file->file_in_sec = (block_num<>SECTOR_SHIFT); + file->file_in_off = block_off & (SECTOR_SIZE - 1); + file->file_mode = this_inode.i_mode; + *file_len = file->file_bytesleft = this_inode.i_size; + + if (*file_len == 0) + return NULL; + + return file; +} + + + +static struct ext4_extent_header * +ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) +{ + struct ext4_extent_idx *index; + struct cache_struct *cs; + block_t blk; + int i; + + while (1) { + if (eh->eh_magic != EXT4_EXT_MAGIC) + return NULL; + + /* got it */ + if (eh->eh_depth == 0) + return eh; + + index = EXT4_FIRST_INDEX(eh); + for (i = 0; i < eh->eh_entries; i++) { + if (block < index[i].ei_block) + break; + } + if (--i < 0) + return NULL; + + blk = index[i].ei_leaf_hi; + blk = (blk << 32) + index[i].ei_leaf_lo; + + /* read the blk to memeory */ + cs = get_cache_block(fs->fs_dev, blk); + eh = (struct ext4_extent_header *)(cs->data); + } +} + +/* handle the ext4 extents to get the phsical block number */ +static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) +{ + struct ext4_extent_header *leaf; + struct ext4_extent *ext; + int i; + block_t start; + + leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); + if (! leaf) { + printf("ERROR, extent leaf not found\n"); + return 0; + } + + ext = EXT4_FIRST_EXTENT(leaf); + for (i = 0; i < leaf->eh_entries; i++) { + if (block < ext[i].ee_block) + break; + } + if (--i < 0) { + printf("ERROR, not find the right block\n"); + return 0; + } + + + /* got it */ + block -= ext[i].ee_block; + if (block >= ext[i].ee_len) + return 0; + + start = ext[i].ee_start_hi; + start = (start << 32) + ext[i].ee_start_lo; + + return start + block; +} + + +/** + * linsector_direct: + * + * @param: block, the block index + * @param: inode, the inode structure + * + * @return: the physic block number + */ +static block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode) +{ + struct cache_struct *cs; + + /* direct blocks */ + if (block < EXT2_NDIR_BLOCKS) + return inode->i_block[block]; + + + /* indirect blocks */ + block -= EXT2_NDIR_BLOCKS; + if (block < PtrsPerBlock1) { + block_t ind_block = inode->i_block[EXT2_IND_BLOCK]; + cs = get_cache_block(fs->fs_dev, ind_block); + + return ((uint32_t *)cs->data)[block]; + } + + /* double indirect blocks */ + block -= PtrsPerBlock1; + if (block < PtrsPerBlock2) { + block_t dou_block = inode->i_block[EXT2_DIND_BLOCK]; + cs = get_cache_block(fs->fs_dev, dou_block); + + dou_block = ((uint32_t *)cs->data)[block / PtrsPerBlock1]; + cs = get_cache_block(fs->fs_dev, dou_block); + + return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; + } + + /* triple indirect block */ + block -= PtrsPerBlock2; + if (block < PtrsPerBlock3) { + block_t tri_block = inode->i_block[EXT2_TIND_BLOCK]; + cs = get_cache_block(fs->fs_dev, tri_block); + + tri_block = ((uint32_t *)cs->data)[block / PtrsPerBlock2]; + cs = get_cache_block(fs->fs_dev, tri_block); + + tri_block = ((uint32_t *)cs->data)[block % PtrsPerBlock2]; + cs = get_cache_block(fs->fs_dev, tri_block); + + return ((uint32_t*)cs->data)[block % PtrsPerBlock1]; + } + + /* File too big, can not handle */ + printf("ERROR, file too big\n"); + return 0; +} + + +/** + * linsector: + * + * Convert a linear sector index in a file to linear sector number + * + * well, alought this function converts a linear sector number to + * physic sector number, it uses block cache in the implemention. + * + * @param: lin_sector, the lineral sector index + * + * @return: physic sector number + */ +static sector_t linsector(struct fs_info *fs, uint32_t lin_sector) +{ + uint32_t block = lin_sector >> ClustShift; + block_t ret; + struct ext2_inode *inode; + + /* well, this is what I think the variable this_inode used for */ + inode = &this_inode; + + if (inode->i_flags & EXT4_EXTENTS_FLAG) + ret = linsector_extent(fs, block, inode); + else + ret = linsector_direct(fs, block, inode); + + if (!ret) { + printf("ERROR: something error happend at linsector..\n"); + return 0; + } + + /* finally convert it to sector */ + return ((ret << ClustShift) + (lin_sector & ClustMask)); +} + + +/* + * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure. + * + * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller. + */ +static inline int ext2_match_entry (const char * const name, + struct ext2_dir_entry * de) +{ + if (!de->d_inode) + return 0; + return !strncmp(name, de->d_name, de->d_name_len); +} + + +/* + * p is at least 6 bytes before the end of page + */ +static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) +{ + return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); +} + +/** + * getlinsec_ext: + * + * same as getlinsec, except load any sector from the zero + * block as all zeros; use to load any data derived from + * n ext2 block pointer, i.e. anything *except the superblock + * + */ +static void getlinsec_ext(struct fs_info *fs, char *buf, + sector_t sector, int sector_cnt) +{ + int ext_cnt = 0; + struct disk *disk = fs->fs_dev->disk; + + if (sector < SecPerClust) { + ext_cnt = SecPerClust - sector; + memset(buf, 0, ext_cnt << SECTOR_SHIFT); + buf += ext_cnt << SECTOR_SHIFT; + } + + sector += ext_cnt; + sector_cnt -= ext_cnt; + disk->rdwr_sectors(disk, buf, sector, sector_cnt, 0); +} + +/** + * getfssec: + * + * Get multiple sectors from a file + * + * Alought we have made the buffer data based on block size, + * we use sector for implemention; because reading multiple + * sectors (then can be multiple blocks) is what the function + * do. So, let it be based on sectors. + * + * This function can be called from C function, and either from + * ASM function. + * + * @param: ES:BX(of regs), the buffer to store data + * @param: DS:SI(of regs), the pointer to open_file_t + * @param: CX(of regs), number of sectors to read + * + * @return: ECX(of regs), number of bytes read + * + */ +static uint32_t ext2_getfssec(struct file *gfile, char *buf, + int sectors, bool *have_more) +{ + int sector_left, next_sector, sector_idx; + int frag_start, con_sec_cnt; + int bytes_read = sectors << SECTOR_SHIFT; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; + + sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT; + if (sectors > sector_left) + sectors = sector_left; + + while (sectors) { + /* + * get the frament + */ + sector_idx = file->file_sector; + next_sector = frag_start = linsector(fs, sector_idx); + con_sec_cnt = 0; + + /* get the consective sectors count */ + do { + con_sec_cnt ++; + sectors --; + if (sectors <= 0) + break; + + /* if sectors >= the sectors left in the 64K block, break and read */ + if (sectors >= (((~(uint32_t)buf&0xffff)|((uint32_t)buf&0xffff0000)) + 1)) + break; + + sector_idx ++; + next_sector ++; + } while (next_sector == linsector(fs, sector_idx)); + +#if 0 + printf("You are reading data stored at sector --0x%x--0x%x\n", + frag_start, frag_start + con_sec_cnt -1); +#endif + getlinsec_ext(fs, buf, frag_start, con_sec_cnt); + buf += con_sec_cnt << 9; + file->file_sector += con_sec_cnt; /* next sector index */ + } while(sectors); + + if (bytes_read >= file->file_bytesleft) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else { + *have_more = 1; + } + file->file_bytesleft -= bytes_read; + + return bytes_read; +} + + + +/** + * find_dir_entry: + * + * find a dir entry, if find return it or return NULL + * + */ +static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, + struct open_file_t *file, + char *filename) +{ + bool have_more; + char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; + struct ext2_dir_entry *de; + struct file xfile; + + /* Fake out a VFS file structure */ + xfile.fs = fs; + xfile.open_file = file; + + /* read a clust at a time */ + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); + de = (struct ext2_dir_entry *)trackbuf; + + while (1) { + if ((char *)de >= (char *)EndBlock) { + if (!have_more) + return NULL; + ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more); + de = (struct ext2_dir_entry *)trackbuf; + } + + /* Zero inode == void entry */ + if (de->d_inode == 0) { + de = ext2_next_entry(de); + continue; + } + + if (ext2_match_entry (filename, de)) { + filename += de->d_name_len; + if ((*filename == 0) || (*filename == '/')) + return de; /* got it */ + + /* not match, restore the filename then try next */ + filename -= de->d_name_len; + } + + de = ext2_next_entry(de); + } +} + + +static char *do_symlink(struct fs_info *fs, struct open_file_t *file, + uint32_t file_len, char *filename) +{ + int flag; + bool have_more; + + char *SymlinkTmpBuf = trackbuf; + char *lnk_end; + char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64; + struct file xfile; + xfile.fs = fs; + xfile.open_file = file; + + flag = this_inode.i_file_acl ? SecPerClust : 0; + if (this_inode.i_blocks == flag) { + /* fast symlink */ + close_pvt(file); /* we've got all we need */ + memcpy(SymlinkTmpBuf, this_inode.i_block, file_len); + lnk_end = SymlinkTmpBuf + file_len; + + } else { + /* slow symlink */ + ext2_getfssec(&xfile, SymlinkTmpBuf, SYMLINK_SECTORS, &have_more); + lnk_end = SymlinkTmpBuf + file_len; + } + + if (*filename != 0) + *lnk_end++ = '/'; + + if (strecpy(lnk_end, filename, SymlinkTmpBufEnd)) + return NULL; /* buffer overflow */ + + /* + * now copy it to the "real" buffer; we need to have + * two buffers so we avoid overwriting the tail on + * the next copy. + */ + strcpy(SymlinkBuf, SymlinkTmpBuf); + + /* return the new path */ + return SymlinkBuf; +} + + + + +/** + * searchdir: + * + * Search the root directory for a pre-mangle filename in FILENAME. + * + * @param: filename, the filename we want to search. + * + * @out : a file pointer, stores in DS:SI (NOTE, DS == 0) + * @out : file lenght in bytes, stores in eax + * + */ +static void ext2_searchdir(char *filename, struct file *file) +{ + extern int CurrentDir; + + struct open_file_t *open_file; + struct ext2_dir_entry *de; + uint8_t file_mode; + uint8_t SymlinkCtr = MAX_SYMLINKS; + uint32_t inr = CurrentDir; + uint32_t ThisDir = CurrentDir; + uint32_t file_len; + + begin_path: + while (*filename == '/') { /* Absolute filename */ + inr = EXT2_ROOT_INO; + filename ++; + } + open: + if ((open_file = open_inode(file->fs, inr, &file_len)) == NULL) + goto err_noclose; + + file_mode = open_file->file_mode >> S_IFSHIFT; + + /* It's a file */ + if (file_mode == T_IFREG) { + if (*filename == '\0') + goto done; + else + goto err; + } + + + /* It's a directory */ + if (file_mode == T_IFDIR) { + ThisDir = inr; + + if (*filename == 0) + goto err; + while (*filename == '/') + filename ++; + + de = find_dir_entry(file->fs, open_file, filename); + if (!de) + goto err; + + inr = de->d_inode; + filename += de->d_name_len; + close_pvt(open_file); + goto open; + } + + + /* + * It's a symlink. We have to determine if it's a fast symlink + * (data stored in the inode) or not (data stored as a regular + * file.) Either which way, we start from the directory + * which we just visited if relative, or from the root directory + * if absolute, and append any remaining part of the path. + */ + if (file_mode == T_IFLNK) { + if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE) + goto err; /* too many links or symlink too long */ + + filename = do_symlink(file->fs, open_file, file_len, filename); + if (!filename) + goto err_noclose;/* buffer overflow */ + + inr = ThisDir; + goto begin_path; /* we got a new path, so search it again */ + } + + /* Otherwise, something bad ... */ + err: + close_pvt(open_file); + err_noclose: + file_len = 0; + open_file = NULL; + done: + + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 0 + if (open_file) { + printf("file bytesleft: %d\n", open_file->file_bytesleft); + printf("file sector : %d\n", open_file->file_sector); + printf("file in sector: %d\n", open_file->file_in_sec); + printf("file offsector: %d\n", open_file->file_in_off); + } +#endif + +} + +static void ext2_load_config(com32sys_t *regs) +{ + char *config_name = "extlinux.conf"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + *(uint32_t *)CurrentDirName = 0x00002f2e; + + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); + + regs->eax.w[0] = out_regs.eax.w[0]; + +#if 0 + printf("the zero flag is %s\n", regs->eax.w[0] ? \ + "CLEAR, means we found the config file" : + "SET, menas we didn't find the config file"); +#endif +} + + +/** + * init. the fs meta data, return the block size bits. + */ +static int ext2_fs_init(struct fs_info *fs) +{ + struct disk *disk = fs->fs_dev->disk; +#if 0 + printf("super block@: %p\n", &sb); +#endif + /* read the super block */ + disk->rdwr_sectors(disk, &sb, 2, 2, 0); + + ClustByteShift = sb.s_log_block_size + 10; + ClustSize = 1 << ClustByteShift; + ClustShift = ClustByteShift - SECTOR_SHIFT; + + DescPerBlock = ClustSize >> ext2_group_desc_lg2size; + InodePerBlock = ClustSize / sb.s_inode_size; + + SecPerClust = ClustSize >> SECTOR_SHIFT; + ClustMask = SecPerClust - 1; + + PtrsPerBlock1 = 1 << (ClustByteShift - 2); + PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2); + PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3); + + return ClustByteShift; +} + +const struct fs_ops ext2_fs_ops = { + .fs_name = "ext2", + .fs_flags = 0, + .fs_init = ext2_fs_init, + .searchdir = ext2_searchdir, + .getfssec = ext2_getfssec, + .close_file = ext2_close_file, + .mangle_name = ext2_mangle_name, + .unmangle_name = ext2_unmangle_name, + .load_config = ext2_load_config +}; diff --git a/core/fs/ext2/ext2_fs.h b/core/fs/ext2/ext2_fs.h new file mode 100644 index 00000000..d579eade --- /dev/null +++ b/core/fs/ext2/ext2_fs.h @@ -0,0 +1,252 @@ +#ifndef __EXT2_FS_H +#define __EXT2_FS_H + +#include + +#define EXT2_SUPER_MAGIC 0xEF53 + +#define EXT2_GOOD_OLD_REV 0 // The good old (original) format +#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +// Special inode numbers +#define EXT2_BAD_INO 1 // Bad blocks inode +#define EXT2_ROOT_INO 2 // Root inode +#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode +#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode +#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode +#define EXT3_JOURNAL_INO 8 // Journal inode + +// We're readonly, so we only care about incompat features. +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff + +#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) + + +/* for EXT4 extent */ +#define EXT4_EXT_MAGIC 0xf30a +#define EXT4_EXTENTS_FLAG 0x00080000 + +/* + * File types and file modes + */ +#define S_IFDIR 0040000 // Directory +#define S_IFCHR 0020000 // Character device +#define S_IFBLK 0060000 // Block device +#define S_IFREG 0100000 // Regular file +#define S_IFIFO 0010000 // FIFO +#define S_IFLNK 0120000 // Symbolic link +#define S_IFSOCK 0140000 // Socket + +#define S_IFSHIFT 12 + +#define T_IFDIR (S_IFDIR >> S_IFSHIFT) +#define T_IFCHR (S_IFCHR >> S_IFSHIFT) +#define T_IFBLK (S_IFBLK >> S_IFSHIFT) +#define T_IFREG (S_IFREG >> S_IFSHIFT) +#define T_IFIFO (S_IFIFO >> S_IFSHIFT) +#define T_IFLNK (S_IFLNK >> S_IFSHIFT) +#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) + + +#define ext2_group_desc_lg2size 5 + + + +/* + * super block structure: + * include/linux/ext2_fs.h + */ +struct ext2_super_block { + uint32_t s_inodes_count; /* Inodes count */ + uint32_t s_blocks_count; /* Blocks count */ + uint32_t s_r_blocks_count; /* Reserved blocks count */ + uint32_t s_free_blocks_count; /* Free blocks count */ + uint32_t s_free_inodes_count; /* Free inodes count */ + uint32_t s_first_data_block; /* First Data Block */ + uint32_t s_log_block_size; /* Block size */ + uint32_t s_log_frag_size; /* Fragment size */ + uint32_t s_blocks_per_group; /* # Blocks per group */ + uint32_t s_frags_per_group; /* # Fragments per group */ + uint32_t s_inodes_per_group; /* # Inodes per group */ + uint32_t s_mtime; /* Mount time */ + uint32_t s_wtime; /* Write time */ + uint16_t s_mnt_count; /* Mount count */ + int16_t s_max_mnt_count; /* Maximal mount count */ + uint16_t s_magic; /* Magic signature */ + uint16_t s_state; /* File system state */ + uint16_t s_errors; /* Behaviour when detecting errors */ + uint16_t s_minor_rev_level; + uint32_t s_lastcheck; /* time of last check */ + uint32_t s_checkinterval; /* max. time between checks */ + uint32_t s_creator_os; /* OS */ + uint32_t s_rev_level; /* Revision level */ + uint16_t s_def_resuid; /* Default uid for reserved blocks */ + uint16_t s_def_resgid; /* Default gid for reserved blocks */ + + uint32_t s_first_ino; /* First non-reserved inode */ + uint16_t s_inode_size; /* size of inode structure */ + uint16_t s_block_group_nr; /* block group # of this superblock */ + uint32_t s_feature_compat; /* compatible feature set */ + uint32_t s_feature_incompat; /* incompatible feature set */ + uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ + uint8_t s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + uint32_t s_algorithm_usage_bitmap; /* For compression */ + uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + uint8_t s_prealloc_dir_blocks; + uint16_t s_padding1; + uint32_t s_reserved[204]; /* Padding to the end of the block */ +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_super_block_size != 1024 +#error ext2_super_block definition bogus +#endif +#endif +*******************************************************************************/ + +/* + * ext2 group desc structure: + */ +struct ext2_group_desc { + uint32_t bg_block_bitmap; /* Blocks bitmap block */ + uint32_t bg_inode_bitmap; /* Inodes bitmap block */ + uint32_t bg_inode_table; /* Inodes table block */ + uint16_t bg_free_blocks_count; /* Free blocks count */ + uint16_t bg_free_inodes_count; /* Free inodes count */ + uint16_t bg_used_dirs_count; /* Directories count */ + uint16_t bg_pad; + uint32_t bg_reserved[3]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_group_desc_size != 32 +#error ext2_group_desc definition bogus +#endif +#endif +*******************************************************************************/ + + +/* + * ext2 inode structure: + */ +struct ext2_inode { + uint16_t i_mode; /* File mode */ + uint16_t i_uid; /* Owner Uid */ + uint32_t i_size; /* 4: Size in bytes */ + uint32_t i_atime; /* Access time */ + uint32_t i_ctime; /* 12: Creation time */ + uint32_t i_mtime; /* Modification time */ + uint32_t i_dtime; /* 20: Deletion Time */ + uint16_t i_gid; /* Group Id */ + uint16_t i_links_count; /* 24: Links count */ + uint32_t i_blocks; /* Blocks count */ + uint32_t i_flags; /* 32: File flags */ + uint32_t l_i_reserved1; + uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ + uint32_t i_version; /* File version (for NFS) */ + uint32_t i_file_acl; /* File ACL */ + uint32_t i_dir_acl; /* Directory ACL */ + uint32_t i_faddr; /* Fragment address */ + uint8_t l_i_frag; /* Fragment number */ + uint8_t l_i_fsize; /* Fragment size */ + uint16_t i_pad1; + uint32_t l_i_reserved2[2]; +}; + +/******************************************************************************* +#ifndef DEPEND +#if ext2_inode_size != 128 +#error ext2_inode definition bogus +#endif +#endif +*******************************************************************************/ + + +#define EXT2_NAME_LEN 255 +struct ext2_dir_entry { + unsigned int d_inode; /* Inode number */ + unsigned short d_rec_len; /* Directory entry length */ + unsigned char d_name_len; /* Name length */ + unsigned char d_file_type; + char d_name[EXT2_NAME_LEN]; /* File name */ +}; + +/******************************************************************************* +#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) +*******************************************************************************/ + + + + + + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +struct ext4_extent { + uint32_t ee_block; /* first logical block extent covers */ + uint16_t ee_len; /* number of blocks covered by extent */ + uint16_t ee_start_hi; /* high 16 bits of physical block */ + uint32_t ee_start_lo; /* low 32 bits of physical block */ +}; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +struct ext4_extent_idx { + uint32_t ei_block; /* index covers logical blocks from 'block' */ + uint32_t ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + uint16_t ei_leaf_hi; /* high 16 bits of physical block */ + uint16_t ei_unused; +}; + +/* + * Each block (leaves and indexes), even inode-stored has header. + */ +struct ext4_extent_header { + uint16_t eh_magic; /* probably will support different formats */ + uint16_t eh_entries; /* number of valid entries */ + uint16_t eh_max; /* capacity of store in entries */ + uint16_t eh_depth; /* has tree real underlying blocks? */ + uint32_t eh_generation; /* generation of the tree */ +}; + + + +#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) +#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) + + + + + + + +/* function declartion */ +/******************************************************************************* +extern struct open_file_t * ext2_read(char *); +extern int ext2_read(struct open_file_t *, char *, int); +*******************************************************************************/ + + +#endif /* ext2_fs.h */ diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c new file mode 100644 index 00000000..83dc9081 --- /dev/null +++ b/core/fs/fat/fat.c @@ -0,0 +1,964 @@ +#include +#include +#include "cache.h" +#include "core.h" +#include "disk.h" +#include "fat_fs.h" +#include "fs.h" + + +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) +#define ROOT_DIR_WORD 0x002f + +/* file structure. This holds the information for each currently open file */ +struct open_file_t { + sector_t file_sector; /* sector pointer ( 0 = structure free ) */ + uint32_t file_bytesleft; /* number of bytes left */ + uint32_t file_left; /* number of sectors left */ +}; + +static struct open_file_t Files[MAX_OPEN]; + +extern uint8_t SecPerClust; + + +/* the fat bpb data */ +static struct fat_bpb fat; +static int FATType = 0; + +/* generic information about FAT fs */ +static sector_t FAT; /* Location of (first) FAT */ +static sector_t RootDirArea; /* Location of root directory area */ +static sector_t RootDir; /* Location of root directory proper */ +static sector_t DataArea; /* Location of data area */ +static uint32_t TotalSectors; /* Total number of sectors */ +static uint32_t ClustSize; /* Bytes/cluster */ +static uint32_t ClustMask; /* Sector/cluster - 1 */ +static uint8_t ClustShift; /* Shift count for sectors/cluster */ +static uint8_t ClustByteShift; /* Shift count for bytes/cluster */ + +static int CurrentDir; +static int PrevDir; + +/* used for long name entry */ +static char MangleBuf[12]; +static char entry_name[14]; + +/* try with the biggest long name */ +static char long_name[0x40 * 13]; +static char *NameStart; +static int NameLen; + +/* do this for readdir, because it called from asm and don't know the fs structure */ +static struct fs_info *this_fs = NULL; + + +/** + * allocate_file: + * + * Allocate a file structure + * + * @return: if successful return the file pointer, or return NULL + * + */ +static struct open_file_t *allocate_file(void) +{ + struct open_file_t *file; + int i = 0; + + file = Files; + + for (; i < MAX_OPEN; i ++ ) { + if ( file->file_sector == 0 ) /* found it */ + return file; + file ++; + } + + return NULL; /* not found */ +} + + +/** + * alloc_fill_dir: + * + * Allocate then fill a file structure for a directory starting in + * sector SECTOR. if successful, return the pointer of filled file + * structure, or return NULL. + * + */ +static struct open_file_t *alloc_fill_dir(sector_t sector) +{ + struct open_file_t *file; + + file = allocate_file(); + if ( !file ) + return NULL; + + file->file_sector = sector; /* current sector */ + file->file_bytesleft = 0; /* current offset */ + file->file_left = sector; /* beginning sector */ + return file; +} + + +/* Deallocates a file structure */ +static inline void close_pvt(struct open_file_t *of) +{ + of->file_sector = 0; +} + +static void vfat_close_file(struct file *file) +{ + close_pvt(file->open_file); +} + + +/* Deallocates a directory structure */ +/*********** +void close_dir(struct fat_dir_entry *dir) +{ + if ( dir ) + *(uint32_t*)dir = 0; +} +***********/ + + +/** + * getfatsector: + * + * check for a particular sector in the FAT cache. + * + */ +static struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) +{ + return get_cache_block(fs->fs_dev, FAT + sector); +} + + +/** + * nextcluster: + * + * Advance a cluster pointer in clust_num to the next cluster + * pointer at in the FAT tables. CF = 0 on return if end of file. + * + * @param: clust_num; + * + * @return: the next cluster number + * + */ +static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) +{ + uint32_t next_cluster; + sector_t fat_sector; + uint32_t offset; + int lo, hi; + struct cache_struct *cs; + + switch(FATType) { + case FAT12: + fat_sector = (clust_num + clust_num / 2) >> SECTOR_SHIFT; + cs = getfatsector(fs, fat_sector); + offset = (clust_num * 3 / 2) & ( SECTOR_SIZE -1 ); + if ( offset == 0x1ff ) { + /* + * we got the end of the one fat sector, + * but we don't got we have(just one byte, we need two), + * so store the low part, then read the next fat + * sector, read the high part, then combine it. + */ + lo = *(uint8_t *)(cs->data + offset); + cs = getfatsector(fs, fat_sector + 1); + hi = *(uint8_t *)cs->data; + next_cluster = (hi << 8) + lo; + } else + next_cluster = *(uint16_t *)(cs->data + offset); + + if ( clust_num & 0x0001 ) + next_cluster >>= 4; /* cluster number is ODD */ + else + next_cluster &= 0x0fff; /* cluster number is EVEN */ + if ( next_cluster > 0x0ff0 ) + goto fail; + break; + + case FAT16: + fat_sector = clust_num >> (SECTOR_SHIFT - 1); + offset = clust_num & ( (1 << (SECTOR_SHIFT-1)) -1); + cs = getfatsector(fs, fat_sector); + next_cluster = ((uint16_t *)cs->data)[offset]; + if ( next_cluster > 0xfff0 ) + goto fail; + break; + + case FAT32: + fat_sector = clust_num >> (SECTOR_SHIFT - 2); + offset = clust_num & ( (1 << (SECTOR_SHIFT-2)) -1); + cs = getfatsector(fs, fat_sector); + next_cluster = ((uint32_t *)cs->data)[offset] & 0x0fffffff; + if ( next_cluster > 0x0ffffff0 ) + goto fail; + break; + } + + return next_cluster; + + fail: + /* got an unexcepted cluster number, so return ZERO */ + return 0; +} + + + +/** + * nextsector: + * + * given a sector on input, return the next sector of the + * same filesystem object, which may be the root directory or a + * cluster chain. Returns EOF. + * + */ +static sector_t nextsector(struct fs_info *fs, sector_t sector) +{ + sector_t data_sector; + uint32_t cluster; + + if ( sector < DataArea ) { + sector ++; + /* if we reached the end of root area */ + if ( sector == DataArea ) + sector = 0; /* return 0 */ + return sector; + } + + data_sector = sector - DataArea; + if ( (data_sector+1) & ClustMask ) /* in a cluster */ + return (++sector); + + /* got a new cluster */ + cluster = nextcluster(fs, (data_sector >> ClustShift) + 2); + if ( !cluster ) + return 0; + + /* return the start of the new cluster */ + sector = ( (cluster - 2) << ClustShift ) + DataArea; + return sector; +} + + + + + +/** + * __getfssec: + * + * get multiple sectors from a file + * + * This routine makes sure the subransfers do not cross a 64K boundary + * and will correct the situation if it does, UNLESS *sectos* cross + * 64K boundaries. + * + * @param: buf + * @param: file structure + * @param: sectors + * + */ +static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, uint32_t sectors) +{ + sector_t curr_sector = file->file_sector; + sector_t frag_start , next_sector; + uint32_t con_sec_cnt; + struct disk *disk = fs->fs_dev->disk; + + while (sectors) { + /* get fragment */ + con_sec_cnt = 0; + frag_start = curr_sector; + + do { + /* get consective sector count */ + con_sec_cnt ++; + sectors --; + if ( sectors == 0 ) + break; + + next_sector = nextsector(fs, curr_sector); + if ( !next_sector ) + break; + }while( next_sector == (++curr_sector) ); + +#if 0 + printf("You are reading data stored at sector --0x%x--0x%x\n", + frag_start, frag_start + con_sec_cnt -1); +#endif + + /* do read */ + disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0); + buf += con_sec_cnt << 9;/* adjust buffer pointer */ + + if ( !sectors ) + break; + //curr_sector --; /* this is the last sector actually read */ + curr_sector = next_sector; + } + + /* update the file_sector filed for the next read */ + file->file_sector = nextsector(fs, curr_sector); +} + + + +/** + * getfssec: + * + * get multiple sectors from a file + * + * + * @param: buf + * @param: file + * @param: sectors + * @param: have_more + * + * @return: number of bytes read + * + */ +static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, + bool *have_more) +{ + uint32_t bytes_read = sectors << SECTOR_SHIFT; + struct open_file_t *file = gfile->open_file; + struct fs_info *fs = gfile->fs; + + if ( sectors > file->file_left ) + sectors = file->file_left; + + __getfssec(fs, buf, file, sectors); + + if ( bytes_read >= file->file_bytesleft ) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else + *have_more = 1; + file->file_bytesleft -= bytes_read; + file->file_left -= sectors; + + return bytes_read; +} + +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed to by dst; + * ends on encountering any whitespace. + * + */ +static void vfat_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX -1; + + while(*src > ' ') { + if ( *src == '\\' ) + *src = '/'; + + if (*src == '/') { + if (*(src+1) == '/') { + src ++; + i --; + continue; + } + } + i --; + *dst++ = *src++; + } + + while (1) { + if (dst == p) + break; + if ((*(dst-1) != '/') && (*(dst-1) != '.')) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i --) + *dst++ = '\0'; +} + + +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int vfat_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + +/** + * mangle_dos_name: + * + * Mangle a dos filename component pointed to by FILENAME + * into MangleBuf; ends on encountering any whitespace or + * slash. + * + * WARNING: saves pointers into the buffer for longname matchs! + * + * @param: filename + * @param: MangleBuf + * + */ +/** + * for now, it can't handle this case: + * xyxzxyxjfdkfjdjf.txt as it will just output the first 11 chars + * but not care the dot char at the later, so I think we need do + * this, but it seems that the SYSLINUX doesn't do it, so I will + * make it stay as what it was orignal. + * + */ +static void mangle_dos_name(char *MangleBuf, char *filename) +{ + + char *dst = MangleBuf; + char *src = filename; + int i = 0; + unsigned char c; + + NameStart = filename; + + for (; i < 11; i ++) + MangleBuf[i] = ' '; + + for (i = 0; i < 11; i++) { + c = *src ++; + + if ( (c <= ' ') || (c == '/') ) + break; + + if ( c == '.' ) { + dst = &MangleBuf[8]; + i = 7; + continue; + } + + if (c >= 'a' && c <= 'z') + c -= 32; + if ( (c == 0xe5) && (i == 11) ) + c = 0x05; + + *dst++ = c; + } + MangleBuf[12] = '\0'; + + while( (*src != '/') && (*src > ' ') ) + src ++; + + NameLen = src - filename; +} + + + +static void unicode_to_ascii(char *entry_name, uint16_t *unicode_buf) +{ + int i = 0; + + for (; i < 13; i++) { + if ( unicode_buf[i] == 0xffff ) { + entry_name[i] = '\0'; + return; + } + entry_name[i] = (char)unicode_buf[i]; + } +} + +/** + * long_entry_name: + * + * get the long entry name + * + */ +static void long_entry_name(struct fat_long_name_entry *dir) +{ + uint16_t unicode_buf[13]; + + memcpy(unicode_buf, dir->name1, 5 * 2); + memcpy(unicode_buf + 5, dir->name2, 6 * 2); + memcpy(unicode_buf + 11,dir->name3, 2 * 2); + + unicode_to_ascii(entry_name, unicode_buf); + +} + + +static uint8_t get_checksum(char *dir_name) +{ + int i; + uint8_t sum=0; + + for (i=11; i; i--) + sum = ((sum & 1) << 7) + (sum >> 1) + *dir_name++; + return sum; +} + +/* compute the first sector number of one dir where the data stores */ +static inline sector_t first_sector(struct fat_dir_entry *dir) +{ + uint32_t first_clust, sector; + + first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low; + sector = ((first_clust - 2) << ClustShift) + DataArea; + + return sector; +} + + +/** + * search_dos_dir: + * + * search a specific directory for a pre-mangled filename in + * MangleBuf, in the directory starting in sector SECTOR + * + * NOTE: This file considers finding a zero-length file an + * error. This is so we don't have to deal with that special + * case elsewhere in the program (most loops have the test + * at the end). + * + * @param: MangleBuf + * @param: dir_sector, directory sector + * + * @out: file pointer + * @out: file length (MAY BE ZERO!) + * @out: file attribute + * @out: dh, clobbered. + * + */ +static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, + uint32_t dir_sector, uint32_t *file_len, uint8_t *attr) +{ + struct open_file_t* file; + struct cache_struct* cs; + struct fat_dir_entry *dir; + struct fat_long_name_entry *long_dir; + + uint8_t VFATInit, VFATNext, VFATCsum; + uint8_t id; + uint32_t slots; + uint32_t entries; + int checksum; + + file = allocate_file(); + if ( !file ) + return NULL; + + /* + * Compute the value of a possible VFAT longname + * "last" entry (which, of coures, comes first ...) + */ + slots = (NameLen + 12) / 13; + slots |= 0x40; + VFATInit = slots; + VFATNext = slots; + + do { + cs = get_cache_block(fs->fs_dev, dir_sector); + dir = (struct fat_dir_entry *)cs->data; + entries = SECTOR_SIZE / 32; + + /* scan all the entries in a sector */ + do { + if ( dir->name[0] == 0 ) + return NULL; /* Hit directory high water mark */ + + if ( dir->attr == 0x0f ) { + /* it's a long name entry */ + long_dir = (struct fat_long_name_entry *)dir; + id = long_dir->id; + if ( id !=VFATNext ) + goto not_match; + + if ( id & 0x40 ) { + /*get the initial checksum value*/ + VFATCsum = long_dir->checksum; + } else { + if ( long_dir->checksum != VFATCsum ) + goto not_match; + } + + id &= 0x3f; + VFATNext = --id; + + /* got the long entry name */ + long_entry_name(long_dir); + memcpy(long_name + id * 13, entry_name, 13); + + /* + * if we got the last entry? + * if so, check it, or go on with the next entry + */ + if ( id == 0 ) { + if ( strcmp(long_name, NameStart) ) + goto not_match; + } + + goto next_entry; + + } else { + /* it's a short entry */ + if ( dir->attr & 0x08 ) /* ingore volume labels */ + goto not_match; + + + /* If we have a long name match, then VFATNext must be 0 */ + if ( !VFATNext ) { + /* + * we already have a VFAT long name match, however, + * the match is only valid if the checksum matchs. + */ + checksum = get_checksum(dir->name); + if ( checksum == VFATCsum ) + goto found; /* got a match on long name */ + + } else { + if ( strncmp(MangleBuf, dir->name, 11) == 0 ) + goto found; + } + } + + not_match:/* find it again */ + VFATNext = VFATInit; + + next_entry: + dir ++; + + }while ( --entries ); + + dir_sector = nextsector(fs, dir_sector); + + }while ( dir_sector ); /* scan another secotr */ + + found: + *file_len = file->file_bytesleft = dir->file_size; + file->file_sector = first_sector(dir); + *attr = dir->attr; + + return file; +} + + + +/** + * searchdir: + * + * open a file + * + * @param: filename, the file we wanna open + * @param: file_len, to return the file length + * + * @return: return the file structure on successful, or NULL. + * + */ +static void vfat_searchdir(char *filename, struct file *file) +{ + sector_t dir_sector; + uint32_t file_len = 0; + uint8_t attr = 0; + char *p; + struct open_file_t *open_file = NULL; + + this_fs = file->fs; + + dir_sector = CurrentDir; + if ( *filename == '/' ) { + dir_sector = RootDir; + if (*(filename + 1) == 0) /* root dir is what we need */ + goto found_dir; + } + + while ( *filename ) { + if (*filename == '/') + filename++; /* skip '/' */ + p = filename; + if (*p == 0) + break; + PrevDir = dir_sector; + + /* try to find the end */ + while ( (*p > ' ') && (*p != '/') ) + p ++; + + if (filename == p) { + /* found a dir */ + dir_sector = PrevDir; + goto found_dir; + } + + mangle_dos_name(MangleBuf, filename); + /* close it before open a new dir file */ + if (open_file) + close_pvt(open_file); + open_file = search_dos_dir(file->fs, MangleBuf, dir_sector, &file_len, &attr); + if (!open_file) + goto fail; + + dir_sector = open_file->file_sector; + filename = p; + } + + if (attr & 0x10) { + dir_sector = PrevDir; + found_dir: + open_file = alloc_fill_dir(dir_sector); + } else if ( (attr & 0x18) || (file_len == 0) ) { + fail: + file_len = 0; + open_file = NULL; + } else { + open_file->file_bytesleft = file_len; + open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; + } + + file->file_len = file_len; + file->open_file = open_file; +} + + + + +/** + * readdir: + * + * read one file from a directory + * + * returns the file's name in the filename string buffer + * + * @param: filename + * @param: file + * + */ +void vfat_readdir(com32sys_t *regs)/* + struct fs_info *fs, struct open_file_t* dir_file, + char* filename, uint32_t *file_len, uint8_t *attr) + */ +{ + uint32_t sector, sec_off; + /* make it to be 1 to check if we have met a long name entry before */ + uint8_t id = 1; + uint8_t init_id, next_id; + uint8_t entries_left; + int i; + + char *filename = MK_PTR(regs->es, regs->edi.w[0]); + struct open_file_t *dir_file = MK_PTR(regs->ds, regs->esi.w[0]); + + struct cache_struct *cs; + struct fat_dir_entry *dir; + struct fat_long_name_entry *long_dir; + struct open_file_t file; + + sector = dir_file->file_sector; + sec_off = dir_file->file_bytesleft; + if (!sector) + goto fail; + + entries_left = (SECTOR_SIZE - sec_off) >> 5; + cs = get_cache_block(this_fs->fs_dev, sector); + dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ + + while ( 1 ) { + if ( dir->name[0] == 0 ) + goto fail; + + if ( dir->attr == FAT_ATTR_LONG_NAME ) { + /* it's a long name */ + long_dir = (struct fat_long_name_entry *)dir; + + if ( long_dir->id & 0x40 ) { + init_id = id = long_dir->id & 0x3f; + id--; + } else { + next_id = (long_dir->id & 0x3f) - 1; + id--; + if ( id != next_id ) + goto next_entry; + } + + long_entry_name(long_dir); + memcpy(filename + id * 13, entry_name, 13); + + + /* + * we need go on with the next entry + * and we will fall through to next entry + */ + + } else { + /* it's a short entry */ + + if ( !id ) /* we got a long name match */ + break; + + if ( dir->attr & FAT_ATTR_VOLUME_ID ) + goto next_entry; + + for( i = 0; i < 8; i ++) { + if ( dir->name[i] == ' ' ) + break; + *filename++ = dir->name[i]; + } + + *filename++ = '.'; + + for ( i = 8; i < 11; i ++) { + if ( dir->name[i] == ' ' ) + break; + *filename ++ = dir->name[i]; + } + + /* check if we have got an extention */ + if (*(filename - 1) == '.') + *(filename - 1) = '\0'; + else + *filename = '\0'; + + break; + } + + next_entry: + dir ++; + entries_left --; + + if ( !entries_left ) { + sector = nextsector(this_fs, sector); + if ( !sector ) + goto fail; + cs = get_cache_block(this_fs->fs_dev, sector); + dir = (struct fat_dir_entry *)cs->data; + } + } + + /* finally , we get what we want */ + entries_left --; + if ( !entries_left ) { + sector = nextsector(this_fs, sector); + if ( !sector ) + goto fail; + dir_file->file_bytesleft = 0; + } else + dir_file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); + dir_file->file_sector = sector; + + file.file_sector = sector; + file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT) ) & 0xffff; + + regs->eax.l = dir->file_size; + regs->ebx.l = first_sector(dir); + regs->edx.b[0] = dir->attr; + + return; + + fail: + //close_dir(dir); + regs->eax.l = 0; + regs->esi.w[0] = 0; + regs->eflags.l |= EFLAGS_CF; +} + +static void vfat_load_config(com32sys_t *regs) +{ + static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; + static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; + static const char syslinux_cfg3[] = "/syslinux.cfg"; + static const char config_name[] = "syslinux.cfg"; + + const char * const syslinux_cfg[] = + { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 }; + com32sys_t oregs; + int i = 0; + + *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; + CurrentDir = RootDir; + + /* + * we use the ConfigName to pass the config path because + * it is under the address 0xffff + */ + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + for (; i < 3; i++) { + strcpy(ConfigName, syslinux_cfg[i]); + memset(&oregs, 0, sizeof oregs); + call16(core_open, regs, &oregs); + + /* if zf flag set, then failed; try another */ + if (! (oregs.eflags.l & EFLAGS_ZF)) + break; + } + if ( i == 3 ) { + printf("no config file found\n"); + return; /* no config file */ + } + + strcpy(ConfigName, config_name); + strcpy(CurrentDirName, syslinux_cfg[i]); + CurrentDirName[strlen(syslinux_cfg[i])-strlen(config_name)] = '\0'; + CurrentDir = PrevDir; +} + +static inline __constfunc uint32_t bsr(uint32_t num) +{ + asm("bsrl %1,%0" : "=r" (num) : "rm" (num)); + return num; +} + +/* init. the fs meta data, return the block size in bits */ +static int vfat_fs_init(struct fs_info *fs) +{ + int sectors_per_fat; + uint32_t clust_num; + int RootDirSize; + struct disk *disk = fs->fs_dev->disk; + + /* get the fat bpb information */ + disk->rdwr_sectors(disk, &fat, 0, 1, 0); + + TotalSectors = fat.bxSectors ? : fat.bsHugeSectors; + FAT = fat.bxResSectors; + + sectors_per_fat = fat.bxFATsecs ? : fat.u.fat32.bxFATsecs_32; + RootDir = RootDirArea = FAT + sectors_per_fat * fat.bxFATs; + RootDirSize = (fat.bxRootDirEnts+SECTOR_SIZE/32-1) >> (SECTOR_SHIFT-5); + DataArea = RootDirArea + RootDirSize; + + ClustShift = bsr(fat.bxSecPerClust); + ClustByteShift = ClustShift + SECTOR_SHIFT; + ClustMask = fat.bxSecPerClust - 1; + ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; + + clust_num = (TotalSectors - DataArea) >> ClustShift; + if ( clust_num < 4085 ) + FATType = FAT12; + else if ( clust_num < 65525 ) + FATType = FAT16; + else + FATType = FAT32; + + /* for SYSLINUX, the cache is based on sector size */ + return SECTOR_SHIFT; +} + +const struct fs_ops vfat_fs_ops = { + .fs_name = "vfat", + .fs_flags = 0, + .fs_init = vfat_fs_init, + .searchdir = vfat_searchdir, + .getfssec = vfat_getfssec, + .close_file = vfat_close_file, + .mangle_name = vfat_mangle_name, + .unmangle_name = vfat_unmangle_name, + .load_config = vfat_load_config +}; diff --git a/core/fs/fat/fat_fs.h b/core/fs/fat/fat_fs.h new file mode 100644 index 00000000..71c1d9a7 --- /dev/null +++ b/core/fs/fat/fat_fs.h @@ -0,0 +1,114 @@ +#ifndef FAT_FS_H +#define FAT_FS_H + +#include + +#define FAT_DIR_ENTRY_SIZE 32 +#define DIRENT_SHIFT 5 + +#define FAT_ATTR_READ_ONLY 0x01 +#define FAT_ATTR_HIDDEN 0x02 +#define FAT_ATTR_SYSTEM 0x04 +#define FAT_ATTR_VOLUME_ID 0x08 +#define FAT_ATTR_DIRECTORY 0x10 +#define FAT_ATTR_ARCHIVE 0x20 + +#define FAT_MAXFILE 256 + +#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY \ + | FAT_ATTR_HIDDEN \ + | FAT_ATTR_SYSTEM \ + | FAT_ATTR_VOLUME_ID) + +#define FAT_ATTR_VALID (FAT_ATTR_READ_ONLY \ + | FAT_ATTR_HIDDEN \ + | FAT_ATTR_SYSTEM \ + | FAT_ATTR_DIRECTORY \ + | FAT_ATTR_ARCHIVE) + +enum fat_type{ FAT12, FAT16, FAT32 }; + +/* + * The fat file system structures + */ + +struct fat_bpb { + uint8_t jmp_boot[3]; + uint8_t oem_name[8]; + uint16_t sector_size; + uint8_t bxSecPerClust; + uint16_t bxResSectors; + uint8_t bxFATs; + uint16_t bxRootDirEnts; + uint16_t bxSectors; + uint8_t media; + uint16_t bxFATsecs; + uint16_t sectors_per_track; + uint16_t num_heads; + uint32_t num_hidden_sectors; + uint32_t bsHugeSectors; + + union { + struct { + uint8_t num_ph_drive; + uint8_t reserved; + uint8_t boot_sig; + uint32_t num_serial; + uint8_t label[11]; + uint8_t fstype[8]; + } __attribute__ ((packed)) fat12_16; + + struct { + uint32_t bxFATsecs_32; + uint16_t extended_flags; + uint16_t fs_version; + uint32_t root_cluster; + uint16_t fs_info; + uint16_t backup_boot_sector; + uint8_t reserved[12]; + uint8_t num_ph_drive; + uint8_t reserved1; + uint8_t boot_sig; + uint32_t num_serial; + uint8_t label[11]; + uint8_t fstype[8]; + } __attribute__ ((packed)) fat32; + + } __attribute__ ((packed)) u; + +} __attribute__ ((packed)); + + + +struct fat_dir_entry { + char name[11]; + uint8_t attr; + uint8_t nt_reserved; + uint8_t c_time_tenth; + uint16_t c_time; + uint16_t c_date; + uint16_t a_date; + uint16_t first_cluster_high; + uint16_t w_time; + uint16_t w_date; + uint16_t first_cluster_low; + uint32_t file_size; +} __attribute__ ((packed)); + + + +struct fat_long_name_entry { + uint8_t id; + uint16_t name1[5]; + uint8_t attr; + uint8_t reserved; + uint8_t checksum; + uint16_t name2[6]; + uint16_t first_cluster; + uint16_t name3[2]; +} __attribute__ ((packed)); + + + + +#endif /* fat_fs.h */ diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c new file mode 100644 index 00000000..583513cd --- /dev/null +++ b/core/fs/iso9660/iso9660.c @@ -0,0 +1,561 @@ +#include +#include +//#include "cache.h" +#include "core.h" +#include "disk.h" +#include "iso9660_fs.h" +#include "fs.h" + +#define DEBUG 1 + +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) +#define ISO_SECTOR_SHIFT 11 +#define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) +#define ROOT_DIR_WORD 0x002f +#define TRACKBUF_SIZE 8192 + + +struct open_file_t { + sector_t file_sector; + uint32_t file_bytesleft; + uint32_t file_left; +}; + +static struct open_file_t Files[MAX_OPEN]; + +struct dir_t { + uint32_t dir_lba; /* Directory start (LBA) */ + uint32_t dir_len; /* Length in bytes */ + uint32_t dir_clust; /* Length in clusters */ +}; +static struct dir_t RootDir; +static struct dir_t CurrentDir; + +static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; + +static char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ +static char *ISOFileNameEnd = &ISOFileName[64]; + +/* + * use to store the block shift, since we treat the hd-mode as 512 bytes + * sector size, 2048 bytes block size. we still treat the cdrom as 2048 + * bytes sector size and also the block size. + */ +static int block_shift; + +/** + * allocate_file: + * + * allocate a file structure + * + */ +static struct open_file_t *allocate_file(void) +{ + struct open_file_t *file = Files; + int i; + + for (i = 0; i < MAX_OPEN; i++) { + if ( file->file_sector == 0 ) /* found it */ + return file; + file++; + } + + return NULL; /* not found */ +} + + +/** + * close_file: + * + * Deallocates a file structure + * + */ +static inline void close_pvt(struct open_file_t *file) +{ + file->file_sector = 0; +} + +static void iso_close_file(struct file *file) +{ + close_pvt(file->open_file); +} + +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed + * to by dst; ends on encountering any whitespace. + * dst is preserved. + * + * This verifies that a filename is < FilENAME_MAX characters, + * doesn't contain whitespace, zero-pads the output buffer, + * and removes trailing dots and redumndant slashes, so "repe + * cmpsb" can do a compare, and the path-searching routine gets + * a bit of an easier job. + * + */ +static void iso_mangle_name(char *dst, char *src) +{ + char *p = dst; + int i = FILENAME_MAX - 1; + + while ( *src > ' ' ) { + if ( *src == '/' ) { + if ( *(src+1) == '/' ) { + i --; + src ++; + continue; + } + } + + *dst++ = *src ++; + i --; + } + + while ( 1 ) { + if ( dst == p ) + break; + + if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) + break; + + dst --; + i ++; + } + + i ++; + for (; i > 0; i -- ) + *dst++ = '\0'; +} + + +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int iso_unmangle_name(char *dst, char *src) +{ + strcpy(dst, src); + return strlen(src); +} + +/** + * compare the names si and di and report if they are + * equal from an ISO 9600 perspective. + * + * @param: de_name, the name from the file system. + * @param: len, the length of de_name, and will return the real name of the de_name + * ';' and other terminates excluded. + * @param: file_name, the name we want to check, is expected to end with a null + * + * @return: 1 on match, or 0. + * + */ +static int iso_compare_names(char *de_name, int *len, char *file_name) +{ + char *p = ISOFileName; + char c1, c2; + + int i = 0; + + while ( (i < *len) && *de_name && (*de_name != ';') && (p < ISOFileNameEnd - 1) ) { + *p++ = *de_name++; + i++; + } + + /* Remove terminal dots */ + while ( *(p-1) == '.' ) { + if ( *len <= 2 ) + break; + + if ( p <= ISOFileName ) + break; + p --; + i--; + } + + if ( i <= 0 ) + return 0; + + *p = '\0'; + + /* return the 'real' length of de_name */ + *len = i; + + p = ISOFileName; + + /* i is the 'real' name length of file_name */ + while ( i ) { + c1 = *p++; + c2 = *file_name++; + + if ( (c1 == 0) && (c2 == 0) ) + return 1; /* success */ + + else if ( (c1 == 0) || ( c2 == 0 ) ) + return 0; + + c1 |= 0x20; + c2 |= 0x20; /* convert to lower case */ + if ( c1 != c2 ) + return 0; + i --; + } + + return 1; +} + +static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, int count) +{ + /* changed those to _sector_ */ + block <<= block_shift; + count <<= block_shift; + return disk->rdwr_sectors(disk, buf, block, count, 0); +} + +/** + * iso_getfssec: + * + * Get multiple clusters from a file, given the file pointer. + * + * @param: buf + * @param: file, the address of the open file structure + * @param: sectors, how many we want to read at once + * @param: have_more, to indicate if we have reach the end of the file + * + */ +static uint32_t iso_getfssec(struct fs_info *fs, char *buf, + void *open_file, int sectors, int *have_more) +{ + uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; + struct open_file_t *file = (struct open_file_t *)open_file; + struct disk *disk = fs->fs_dev->disk; + + if ( sectors > file->file_left ) + sectors = file->file_left; + + cdrom_read_sectors(disk, buf, file->file_sector, sectors); + + file->file_sector += sectors; + file->file_left -= sectors; + + if ( bytes_read >= file->file_bytesleft ) { + bytes_read = file->file_bytesleft; + *have_more = 0; + } else + *have_more = 1; + file->file_bytesleft -= bytes_read; + + return bytes_read; +} + + + +/** + * do_search_dir: + * + * find a file or directory with name within the _dir_ directory. + * + * the return value will tell us what we find, it's a file or dir? + * on 1 be dir, 2 be file, 0 be error. + * + * res will return the result. + * + */ +static int do_search_dir(struct fs_info *fs, struct dir_t *dir, + char *name, uint32_t *file_len, void **res) +{ + struct open_file_t *file; + struct iso_dir_entry *de; + struct iso_dir_entry tmpde; + + uint32_t offset = 0; /* let's start it with the start */ + uint32_t file_pos = 0; + char *de_name; + int de_len; + int de_name_len; + int have_more; + + file = allocate_file(); + if ( !file ) + return 0; + + file->file_left = dir->dir_clust; + file->file_sector = dir->dir_lba; + + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + de = (struct iso_dir_entry *)trackbuf; + + while ( file_pos < dir->dir_len ) { + int found = 0; + + if ( (char *)de >= (char *)(trackbuf + TRACKBUF_SIZE) ) { + if ( !have_more ) + return 0; + + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + offset = 0; + } + + de = (struct iso_dir_entry *) (trackbuf + offset); + + de_len = de->length; + + if ( de_len == 0) { + offset = file_pos = (file_pos+ISO_SECTOR_SIZE) & ~(ISO_SECTOR_SIZE-1); + continue; + } + + + offset += de_len; + + /* Make sure we have a full directory entry */ + if ( offset >= TRACKBUF_SIZE ) { + int slop = TRACKBUF_SIZE - offset + de_len; + memcpy(&tmpde, de, slop); + offset &= TRACKBUF_SIZE - 1; + file->file_sector ++; + if ( offset ) { + if ( !have_more ) + return 0; + iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + memcpy((void*)&tmpde + slop, trackbuf, offset); + } + de = &tmpde; + } + + if ( de_len < 33 ) { + printf("Corrutped directory entry in sector %d\n", file->file_sector); + return 0; + } + + de_name_len = de->name_len; + de_name = (char *)((void *)de + 0x21); + + + if ( (de_name_len == 1) && (*de_name == 0) ) { + found = iso_compare_names(".", &de_name_len, name); + + } else if ( (de_name_len == 1) && (*de_name == 1) ) { + de_name_len = 2; + found = iso_compare_names("..", &de_name_len, name); + + } else + found = iso_compare_names(de_name, &de_name_len, name); + + if (found) + break; + + file_pos += de_len; + } + + if ( file_pos >= dir->dir_len ) + return 0; /* not found */ + + + if ( *(name+de_name_len) && (*(name+de_name_len) != '/' ) ) { + printf("Something wrong happened during searching file %s\n", name); + + *res = NULL; + return 0; + } + + if ( de->flags & 0x02 ) { + /* it's a directory */ + dir = &CurrentDir; + dir->dir_lba = *(uint32_t *)de->extent; + dir->dir_len = *(uint32_t *)de->size; + dir->dir_clust = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = dir->dir_len; + *res = dir; + + /* we can close it now */ + close_pvt(file); + + /* Mark we got a directory */ + return 1; + } else { + /* it's a file */ + file->file_sector = *(uint32_t *)de->extent; + file->file_bytesleft = *(uint32_t *)de->size; + file->file_left = (file->file_bytesleft + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + *file_len = file->file_bytesleft; + *res = file; + + /* Mark we got a file */ + return 2; + } +} + + +/** + * iso_searchdir: + * + * open a file + * + * searchdir_iso is a special entry point for ISOLINUX only. In addition + * to the above, searchdir_iso passes a file flag mask in AL. This is + * useful for searching for directories. + * + * well, it's not like the searchidr function in EXT fs or FAT fs; it also + * can read a diretory.(Just thought of mine, liu) + * + */ +static void iso_searchdir(char *filename, struct file *file) +{ + struct open_file_t *open_file = NULL; + struct dir_t *dir; + uint32_t file_len = 0; + int ret; + void *res; + + dir = &CurrentDir; + if ( *filename == '/' ) { + dir = &RootDir; + filename ++; + } + + while ( *filename ) { + ret = do_search_dir(file->fs, dir, filename, &file_len, &res); + if ( ret == 1 ) + dir = (struct dir_t *)res; + else if ( ret == 2 ) + break; + else + goto err; + + /* find the end */ + while ( *filename && (*filename != '/') ) + filename ++; + + /* skip the slash */ + while ( *filename && (*filename == '/') ) + filename++; + } + + /* well , we need recheck it , becuase it can be a directory */ + if ( ret == 2 ) { + open_file = (struct open_file_t *)res; + goto found; + } else { + open_file = allocate_file(); + if ( !open_file ) + goto err; + + open_file->file_sector = dir->dir_lba; + open_file->file_bytesleft = dir->dir_len; + open_file->file_left = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + goto found; + } + err: + close_pvt(open_file); + file_len = 0; + open_file = NULL; + + found: + file->file_len = file_len; + file->open_file = (void*)open_file; + +#if 0 + if (open_file) { + printf("file bytesleft: %d\n", open_file->file_bytesleft); + printf("file sector : %d\n", open_file->file_sector); + printf("file in sector: %d\n", open_file->file_in_sec); + printf("file offsector: %d\n", open_file->file_in_off); + } +#endif +} + +static void iso_load_config(com32sys_t *regs) +{ + char *config_name = "isolinux.cfg"; + com32sys_t out_regs; + + strcpy(ConfigName, config_name); + + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + memset(&out_regs, 0, sizeof out_regs); + call16(core_open, regs, &out_regs); +} + + +static int iso_fs_init(struct fs_info *fs) +{ + char *iso_dir; + char *boot_dir = "/boot/isolinux"; + char *isolinux_dir = "/isolinux"; + int len; + int bi_pvd = 16; + struct file file; + struct open_file_t *open_file; + struct disk *disk = fs->fs_dev->disk; + + block_shift = ISO_SECTOR_SHIFT - disk->sector_shift; + cdrom_read_sectors(disk, trackbuf, bi_pvd, 1); + CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); + +#ifdef DEBUG + printf("Root directory at LBA = 0x%x\n", RootDir.dir_lba); +#endif + + CurrentDir.dir_len = RootDir.dir_len = *(uint32_t*)(trackbuf + 156 + 10); + CurrentDir.dir_clust = RootDir.dir_clust = (RootDir.dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; + + /* + * Look for an isolinux directory, and if found, + * make it the current directory instead of the + * root directory. + * + * Also copy the name of the directory to CurrrentDirName + */ + *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; + + iso_dir = boot_dir; + file.fs = fs; + iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ + if ( !file.file_len ) { + iso_dir = isolinux_dir; + iso_searchdir(isolinux_dir, &file); /* search for /isolinux */ + if ( !file.file_len ) { + printf("No isolinux directory found!\n"); + return 0; + } + } + + strcpy(CurrentDirName, iso_dir); + len = strlen(CurrentDirName); + CurrentDirName[len] = '/'; + CurrentDirName[len+1] = '\0'; + + open_file = (struct open_file_t *)file.open_file; + CurrentDir.dir_len = open_file->file_bytesleft; + CurrentDir.dir_clust = open_file->file_left; + CurrentDir.dir_lba = open_file->file_sector; + close_pvt(open_file); + +#ifdef DEBUG + printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); +#endif + + /* we do not use cache for now, so we can just return 0 */ + return 0; +} + + +const struct fs_ops iso_fs_ops = { + .fs_name = "iso", + .fs_flags = 0, + .fs_init = iso_fs_init, + .searchdir = iso_searchdir, + .getfssec = iso_getfssec, + .close_file = iso_close_file, + .mangle_name = iso_mangle_name, + .unmangle_name = iso_unmangle_name, + .load_config = iso_load_config +}; diff --git a/core/fs/iso9660/iso9660_fs.h b/core/fs/iso9660/iso9660_fs.h new file mode 100644 index 00000000..ca123b16 --- /dev/null +++ b/core/fs/iso9660/iso9660_fs.h @@ -0,0 +1,21 @@ +#ifndef ISO9660_FS_H +#define ISO9660_FS_H + +#include + +struct iso_dir_entry { + uint8_t length; /* 00 */ + uint8_t ext_attr_length; /* 01 */ + uint8_t extent[8]; /* 02 */ + uint8_t size[8]; /* 0a */ + uint8_t date[7]; /* 12 */ + uint8_t flags; /* 19 */ + uint8_t file_unit_size; /* 1a */ + uint8_t interleave; /* 1b */ + uint8_t volume_sequence_number[4]; /* 1c */ + uint8_t name_len; /* 20 */ + //uint8_t name[]; /* 21 */ +}; + + +#endif /* iso9660_fs.h */ diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c new file mode 100644 index 00000000..5c81fbdd --- /dev/null +++ b/core/fs/pxe/dhcp_option.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include "pxe.h" + +void parse_dhcp_options(void *, int, int); + +static void subnet_mask(void *data, int opt_len) +{ + if (opt_len != 4) + return; + Netmask = *(uint32_t *)data; +} + +static void router(void *data, int opt_len) +{ + if (opt_len != 4) + return; + Gateway = *(uint32_t *)data; +} + +static void dns_servers(void *data, int opt_len) +{ + int num = opt_len >> 2; + int i; + + if (num > DNS_MAX_SERVERS) + num = DNS_MAX_SERVERS; + + for (i = 0; i < num; i++) { + DNSServers[i] = *(uint32_t *)data; + data += 4; + } + + /* NOT SURE FOR NOW */ + LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0); +} + +static void local_domain(void *data, int opt_len) +{ + com32sys_t regs; + char *p = (char *)data + opt_len; + char end = *p; + + memset(®s, 0, sizeof regs); + *p = '\0'; /* Zero-terminate option */ + regs.esi.w[0] = OFFS_WRT(data, 0); + regs.edi.w[0] = OFFS_WRT(LocalDomain, 0); + call16(dns_mangle, ®s, NULL); + *p = end; /* Resotre ending byte */ +} + +static void vendor_encaps(void *data, int opt_len) +{ + /* Only recongnize PXELINUX options */ + parse_dhcp_options(data, opt_len, 208); +} + +static void option_overload(void *data, int opt_len) +{ + if (opt_len != 1) + return; + OverLoad = *(uint8_t *)data; +} + + +static void server(void *data, int opt_len) +{ + uint32_t ip; + + if (opt_len != 4) + return; + + if (ServerIP) + return; + + ip = *(uint32_t *)data; + if (ip_ok(ip)) + ServerIP = ip; +} + +static void client_identifier(void *data, int opt_len) +{ + if (opt_len > MAC_MAX || opt_len < 2 || + MACLen != (opt_len >> 8) || + *(uint8_t *)data != MACType) + return; + + opt_len --; + MACLen = opt_len & 0xff; + memcpy(MAC, data+1, opt_len); + MAC[opt_len] = 0; +} + +static void bootfile_name(void *data, int opt_len) +{ + strncpy(BootFile, data, opt_len); + BootFile[opt_len] = 0; +} + +static void uuid_client_identifier(void *data, int opt_len) +{ + int type = *(uint8_t *)data; + if (opt_len != 17 || + (type | HaveUUID)) + return; + + HaveUUID = 1; + UUIDType = type; + memcpy(UUID, data+1, 16); + UUID[16] = 0; +} + +static void pxelinux_configfile(void *data, int opt_len) +{ + DHCPMagic |= 2; + strncpy(ConfigName, data, opt_len); + ConfigName[opt_len] = 0; +} + +static void pxelinux_pathprefix(void *data,int opt_len) +{ + DHCPMagic |= 4; + strncpy(PathPrefix, data, opt_len); + PathPrefix[opt_len] = 0; +} + +static void pxelinux_reboottime(void *data, int opt_len) +{ + if ((opt_len && 0xff) != 4) + return ; + + RebootTime = ntohl(*(uint32_t *)data); + DHCPMagic |= 8; /* Got reboot time */ +} + + +struct dhcp_options { + int opt_num; + void (*fun) (void *, int); +}; + +static struct dhcp_options dhcp_opts[] = { + {1, subnet_mask}, + {3, router}, + {6, dns_servers}, + {15, local_domain}, + {43, vendor_encaps}, + {52, option_overload}, + {54, server}, + {61, client_identifier}, + {67, bootfile_name}, + {97, uuid_client_identifier}, + {209, pxelinux_configfile}, + {210, pxelinux_pathprefix}, + {211, pxelinux_reboottime} +}; + +/* + * Parse a sequence of DHCP options, pointed to by _option_; + * -- some DHCP servers leave option fields unterminated + * in violation of the spec. + * + * filter contains the minimum value for the option to recognize + * -- this is used to restrict parsing to PXELINUX-specific options only. + */ +void parse_dhcp_options(void *option, int size, int filter) +{ + uint8_t opt_num; + uint8_t opt_len; + uint8_t opt_filter = filter == 208 ? 208 : 0; + int opt_entries = sizeof(dhcp_opts) / sizeof(dhcp_opts[0]); + int i = 0; + char *p = option; + struct dhcp_options *opt; + + if (opt_filter) + printf("***NOTE!:*** we hit a pxelinux-specific options\n"); + + while (size --) { + opt_num = *p++; + + if (!size) + break; + if (opt_num == 0) + continue; + if (opt_num == 0xff) + break; + + /* Anything else will have a lenght filed */ + opt_len = *p++; /* c <- option lenght */ + size = size - opt_len - 1; + if (size < 0) + break; + if (opt_num < opt_filter) { /* Is the option value valid */ + option += opt_len; /* Try next */ + continue; + } + + opt = dhcp_opts; + for (i = 0; i < opt_entries; i++) { + if (opt_num == opt->opt_num) { + opt->fun(p, opt_len); + break; + } + opt ++; + } + + /* parse next */ + p += opt_len; + } +} + +/* + * + ; + ; parse_dhcp + ; + ; Parse a DHCP packet. This includes dealing with "overloaded" + ; option fields (see RFC 2132, section 9.3) + ; + ; This should fill in the following global variables, if the + ; information is present: + ; + ; MyIP - client IP address + ; ServerIP - boot server IP address + ; Netmask - network mask + ; Gateway - default gateway router IP + ; BootFile - boot file name + ; DNSServers - DNS server IPs + ; LocalDomain - Local domain name + ; MACLen, MAC - Client identifier, if MACLen == 0 + ; + ; This assumes the DHCP packet is in "trackbuf". + ; +*/ +void parse_dhcp(int pkt_len) +{ + struct bootp_t *dhcp = (struct bootp_t *)trackbuf; + int opt_len; + + OverLoad = 0; + if (ip_ok(dhcp->yip)) + MyIP = dhcp->yip; + + if (ip_ok(dhcp->sip)) + ServerIP = dhcp->sip; + + opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options; + if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) + parse_dhcp_options(&dhcp->options, opt_len, 0); + + if (OverLoad & 1) + parse_dhcp_options(&dhcp->bootfile, 128, 0); + else if (dhcp->bootfile[0]) + strcpy(BootFile, dhcp->bootfile); + + if (OverLoad & 2) + parse_dhcp_options(dhcp->sname, 64, 0); +} diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c new file mode 100644 index 00000000..d4662f5c --- /dev/null +++ b/core/fs/pxe/pxe.c @@ -0,0 +1,1559 @@ +#include +#include +#include +#include +#include +#include +#include "pxe.h" + +#define FILENAME_MAX_LG2 7 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) + +#define GPXE 1 +#define USE_PXE_PROVIDED_STACK 0 + +static struct open_file_t Files[MAX_OPEN]; + +static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; +static char *err_pxefailed = "PXE API call failed, error "; +static char *err_udpinit = "Failed to initialize UDP stack\n"; + +static char *tftpprefix_msg = "TFTP prefix: "; +static char *get_packet_msg = "Getting cached packet "; + +static int has_gpxe; +static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; +int HaveUUID = 0; + +static const uint8_t TimeoutTable[] = { + 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, + 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 +}; + +struct tftp_options { + const char *str_ptr; /* string pointer */ + size_t offset; /* offset into socket structre */ +}; +static const struct tftp_options tftp_options[] = +{ + { "tsize", offsetof(struct open_file_t, tftp_filesize) }, + { "blksize", offsetof(struct open_file_t, tftp_blksize) }, +}; +static const int tftp_nopts = sizeof tftp_options / sizeof tftp_options[0]; + +/* + * Initialize the Files structure + */ +static void files_init(void) +{ + int i; + struct open_file_t *socket = Files; + uint16_t pktbuf = 0; + uint16_t nextport = 49152; + + for (i = 0; i < MAX_OPEN; i++) { + socket->tftp_pktbuf = pktbuf; + socket->tftp_nextport = nextport; + pktbuf += PKTBUF_SIZE; + nextport++; + socket++; + } +} + +/* + * Allocate a local UDP port structure. + * return the socket pointer if success, or null if failure + * + */ +static struct open_file_t *allocate_socket(void) +{ + int i; + struct open_file_t *socket = Files; + uint16_t nextport; + + for (i = 0; i < MAX_OPEN; i++) { + if (!socket->tftp_localport) + break; + socket++; + } + + if (i == MAX_OPEN) + return NULL; + + /* + * Allocate a socket number. Socket numbers are made guaranteed + * unique by including the socket slot number; add a counter value + * to keep the numbers from being likely to get immediately + * reused. The mask enforces wraparound to the range 49152-57343. + */ + nextport = socket->tftp_nextport; + socket->tftp_nextport = (nextport + (1 << MAX_OPEN_LG2)) & 0xdfff; + socket->tftp_localport = htons(nextport); /* Socket now in use */ + return socket; +} + +/* + * free socket, socket in SI; return SI = 0, ZF = 1 for convenience + */ +static void free_socket(struct open_file_t *file) +{ + /* tftp_nextport and tftp_pktbuf are not cleared */ + memset(file, 0, offsetof(struct open_file_t, tftp_nextport)); +} + +static void pxe_close_file(struct file *file) +{ + /* + * XXX: we really should see if the connection is open as send + * a courtesy ERROR packet so the server knows the connection is + * dead. + */ + free_socket(file->open_file); +} + +/** + * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal + * + * @param: dst, output buffer + * @param: src, input buffer + * @param: count, number of bytes + * + */ +static void lchexbytes(char *dst, const void *src, int count) +{ + uint8_t half; + uint8_t c; + const uint8_t *s = src; + + for(; count > 0; count--) { + c = *s++; + half = ((c >> 4) & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; + + half = (c & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; + } +} + +/** + * just like the lchexbytes, except to upper-case + * + */ +static void uchexbytes(char *dst, const void *src, int count) +{ + uint8_t half; + uint8_t c; + const uint8_t *s = src; + + for(; count > 0; count--) { + c = *s++; + half = ((c >> 4) & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; + + half = (c & 0x0f) + '0'; + *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; + } +} + + + + +/* + * + * Tests an IP address in EAX for validity; return with 0 for bad, 1 for good. + * We used to refuse class E, but class E addresses are likely to become + * assignable unicast addresses in the near future. + * + */ +int ip_ok(uint32_t ip) +{ + if (ip == -1) /* Refuse the all-one address */ + goto bad; + if ((ip & 0xff) == 0) /* Refuse network zero */ + goto bad; + if ((ip & 0xff) == 0xff) /* Refuse loopback */ + goto bad; + if ((ip & 0xf0) == 0xe0) /* Refuse class D */ + goto bad; + + return 1; + + bad: + return 0; +} + + +/********************************************************************* +; +; gendotquad +; +; Take an IP address (in network byte order) in EAX and +; output a dotted quad string to ES:DI. +; DI points to terminal null at end of string on exit. +; + *********************************************************************/ +/** + * @param: dst, to store the converted ip string + * @param: ip, the ip address that needed convert. + * + * @return: the ip string length + */ +int gendotquad(char *dst, uint32_t ip) +{ + int part; + int i = 0, j; + char temp[4]; + char *p = dst; + + for (; i < 4; i++) { + j = 0; + part = ip & 0xff; + do { + temp[j++] = (part % 10) + '0'; + }while(part /= 10); + for (; j > 0; j--) + *p++ = temp[j-1]; + *p++ = '.'; + + ip >>= 8; + } + /* drop the last dot '.' and zero-terminate string*/ + *(--p) = 0; + + return p - dst; +} + +/* + * parse the ip_str and return the ip address with *res. + * return the the string address after the ip string + * + */ +static char *parse_dotquad(char *ip_str, uint32_t *res) +{ + char *p = ip_str; + int i = 0; + uint8_t part = 0; + uint32_t ip = 0; + + for (; i < 4; i++) { + while (is_digit(*p)) { + part = part * 10 + *p - '0'; + p++; + } + if (i != 3 && *p != '.') + return NULL; + + ip = (ip << 8) | part; + part = 0; + p++; + } + p --; + + *res = ip; + return p; +} + +/* + * the ASM pxenv function wrapper, return 1 if error, or 0 + * + */ +static int pxe_call(int opcode, void *data) +{ + extern void pxenv(void); + com32sys_t in_regs, out_regs; + +#if 0 + printf("pxe_call op %04x data %p\n", opcode, data); +#endif + + memset(&in_regs, 0, sizeof in_regs); + + in_regs.ebx.w[0] = opcode; + in_regs.es = SEG(data); + in_regs.edi.w[0] = OFFS(data); + call16(pxenv, &in_regs, &out_regs); + + return out_regs.eflags.l & EFLAGS_CF; /* CF SET for fail */ +} + +/** + * + * Send ACK packet. This is a common operation and so is worth canning. + * + * @param: file, TFTP block pointer + * @param: ack_num, Packet # to ack (network byte order) + * + */ +static void ack_packet(struct open_file_t *file, uint16_t ack_num) +{ + int err; + static __lowmem struct pxe_udp_write_pkt uw_pkt; + + /* Packet number to ack */ + ack_packet_buf[1] = ack_num; + uw_pkt.lport = file->tftp_localport; + uw_pkt.rport = file->tftp_remoteport; + uw_pkt.sip = file->tftp_remoteip; + uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; + uw_pkt.buffer[0] = OFFS_WRT(ack_packet_buf, 0); + uw_pkt.buffer[1] = 0; /* seems SEG and OFFS stuff doesn't work here */ + uw_pkt.buffersize = 4; + + err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); +#if 0 + printf("sent %s\n", err ? "FAILED" : "OK"); +#endif +} + + +/** + * Get a DHCP packet from the PXE stack into the trackbuf + * + * @param: type, packet type + * @return: buffer size + * + */ +static int pxe_get_cached_info(int type) +{ + int err; + static __lowmem struct pxe_bootp_query_pkt bq_pkt; + printf(" %02x", type); + + bq_pkt.status = 0; + bq_pkt.packettype = type; + bq_pkt.buffersize = 8192; + bq_pkt.buffer[0] = OFFS_WRT(trackbuf, 0); + bq_pkt.buffer[1] = 0; + + err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); + if (err) { + printf("%s %04x\n", err_pxefailed, err); + call16(kaboom, NULL, NULL); + } + + return bq_pkt.buffersize; +} + + + +#if GPXE + +/* + * Return 1 if and only if the buffer pointed to by + * url is a URL (contains ://) + * + */ +static int is_url(char *url) +{ + while (*url) { + if(! strncmp(url, "://", 3)) + return 1; + + url++; + } + return 0; +} + + +/* + * Return CF=0 if and only if the buffer pointed to by DS:SI is a URL + * (contains ://) *and* the gPXE extensions API is available. No + * registers modified. + */ +static int is_gpxe(char *url) +{ + int err; + static __lowmem struct gpxe_file_api_check ac; + char *gpxe_warning_msg = "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; + + if (! is_url(url)) + return 0; + + ac.size = 20; + ac.magic = 0x91d447b2; + /* If has_gpxe is greater than one, means the gpxe status is unknow */ + while (has_gpxe > 1) { + err = pxe_call(PXENV_FILE_API_CHECK, &ac); + if (err || ac.magic != 0xe9c17b20) + printf("%s\n", gpxe_warning_msg); + else + has_gpxe = (~ac.provider & 0xffff) & 0x4b ? 0 : 1; + + if (!has_gpxe) + printf("%s\n", gpxe_warning_msg); + } + + if (has_gpxe == 1) + return 1; + else + return 0; +} + +/** + * Get a fresh packet from a gPXE socket + * @param: file -> socket structure + * + */ +static void get_packet_gpxe(struct open_file_t *file) +{ + static __lowmem struct gpxe_file_read fr; + int err; + + while (1) { + fr.filehandle = file->tftp_remoteport; + fr.buffer[0] = file->tftp_pktbuf; + fr.buffer[1] = PKTBUF_SEG; + fr.buffersize = PKTBUF_SIZE; + err = pxe_call(PXENV_FILE_READ, &fr); + if (!err) /* successed */ + break; + + if (fr.status == PXENV_STATUS_TFTP_OPEN) + continue; + call16(kaboom, NULL, NULL); + } + + file->tftp_bytesleft = fr.buffersize; + file->tftp_filepos += fr.buffersize; + + if (file->tftp_bytesleft == 0) + file->tftp_filesize = file->tftp_filepos; + + /* if we're done here, close the file */ + if (file->tftp_filesize > file->tftp_filepos) + return; + + /* Got EOF, close it */ + file->tftp_goteof = 1; + pxe_call(PXENV_FILE_CLOSE, &fr); +} +#endif /* GPXE */ + + +/* + * mangle a filename pointed to by _src_ into a buffer pointed + * to by _dst_; ends on encountering any whitespace. + * + * The first four bytes of the manged name is the IP address of + * the download host, 0 for no host, or -1 for a gPXE URL. + * + */ +static void pxe_mangle_name(char *dst, char *src) +{ + char *p = src; + uint32_t ip = 0; + int i = 0; + +#if GPXE + if (is_url(src)) + goto prefix_done; +#endif + + ip = ServerIP; + if (*p == 0) + goto noip; + if (! strncmp(p, "::", 2)) + goto gotprefix; + else { + while (*p && strncmp(p, "::", 2)) + p ++; + if (! *p) + goto noip; + /* + * we have a :: prefix of ip sort, it could be either a DNS + * name or dot-quad IP address. Try the dot-quad first. + */ + p = src; + if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) + goto gotprefix; + else { +#if 0 + extern void dns_resolv(void); + call16(dns_resolv, regs, regs); + p = (char *)MK_PTR(regs->ds, regs->esi.w[0]); + ip = regs->eax.l; + if (! strncmp(p, "::", 2)) + if (ip) + goto gotprefix; +#endif + } + } + noip: + p = src; + ip = 0; + goto prefix_done; + + gotprefix: + p += 2; /* skip double colon */ + + prefix_done: + *(uint32_t *)dst = ip; + dst += 4; + i = FILENAME_MAX - 5; + + do { + if (*p <= ' ') + break; + *dst++ = *p++; + }while (i--); + + i ++; + while (i) { + *dst++ = 0; + i --; + } + +#if 0 + printf("the name before mangling: "); + dump16(src); + printf("the name after mangling: "); + dump16((char *)MK_PTR(regs->ds, regs->edi.w[0])); +#endif +} + + +/* + * Does the opposite of mangle_name; converts a DOS-mangled + * filename to the conventional representation. This is + * needed for the BOOT_IMAGE= parameter for the kernel. + * + * it returns the lenght of the filename. + */ +static int pxe_unmangle_name(char *dst, char *src) +{ + uint32_t ip = *(uint32_t *)src; + int ip_len = 0; + + if (ip != 0 && ip != -1) { + ip_len = gendotquad(dst, *(uint32_t *)src); + dst += ip_len; + } + src += 4;; + strcpy(dst, src); + + return strlen(src) + ip_len; +} + +/* + * + ; + ; Get a fresh packet if the buffer is drained, and we haven't hit + ; EOF yet. The buffer should be filled immediately after draining! + ; + ; expects fs -> pktbuf_seg and ds:si -> socket structure + ; +*/ +static void fill_buffer(struct open_file_t *file) +{ + int err; + int last_pkt; + const uint8_t *timeout_ptr = TimeoutTable; + uint8_t timeout; + uint16_t buffersize; + uint16_t old_time; + void *data = NULL; + static __lowmem struct pxe_udp_read_pkt pkt; + + if (file->tftp_bytesleft || file->tftp_goteof) + return; + +#if GPXE + if (file->tftp_localport == 0xffff) { + get_packet_gpxe(file); + return; + } +#endif + + + /* + * Start by ACKing the previous packet; this should cause + * the next packet to be sent. + */ + ack_again: + ack_packet(file, file->tftp_lastpkt); + + timeout_ptr = TimeoutTable; + timeout = *timeout_ptr++; + old_time = BIOS_timer; + while (timeout) { + pkt.buffer[0] = file->tftp_pktbuf; + pkt.buffer[1] = PKTBUF_SEG; + pkt.buffersize = PKTBUF_SIZE; + pkt.sip = file->tftp_remoteip; + pkt.dip = MyIP; + pkt.rport = file->tftp_remoteport; + pkt.lport = file->tftp_localport; + err = pxe_call(PXENV_UDP_READ, &pkt); + if (err) { + if (BIOS_timer == old_time) + continue; + + BIOS_timer = old_time; + timeout--; /* decrease one timer tick */ + if (!timeout) { + timeout = *timeout_ptr++; + if (!timeout) + break; + } + continue; + } + + if (pkt.buffersize < 4) /* Bad size for a DATA packet */ + continue; + + data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf); + if (*(uint16_t *)data != TFTP_DATA) /* Not a data packet */ + continue; + + /* If goes here, recevie OK, break */ + break; + } + + /* time runs out */ + if (timeout == 0) + call16(kaboom, NULL, NULL); + + last_pkt = file->tftp_lastpkt; + last_pkt = ntohs(last_pkt); /* Host byte order */ + last_pkt++; + last_pkt = htons(last_pkt); /* Network byte order */ + if (*(uint16_t *)(data + 2) != last_pkt) { + /* + * Wrong packet, ACK the packet and try again. + * This is presumably because the ACK got lost, + * so the server just resent the previous packet. + */ +#if 0 + printf("Wrong packet, wanted %04x, got %04x\n", htons(last_pkt), htons(*(uint16_t *)(data+2))); +#endif + goto ack_again; + } + + /* It's the packet we want. We're also EOF if the size < blocksize */ + file->tftp_lastpkt = last_pkt; /* Update last packet number */ + buffersize = pkt.buffersize - 4; /* Skip TFTP header */ + file->tftp_dataptr = file->tftp_pktbuf + 4; + file->tftp_filepos += buffersize; + file->tftp_bytesleft = buffersize; + if (buffersize < file->tftp_blksize) { + /* it's the last block, ACK packet immediately */ + ack_packet(file, *(uint16_t *)(data + 2)); + + /* Make sure we know we are at end of file */ + file->tftp_filesize = file->tftp_filepos; + file->tftp_goteof = 1; + } +} + + +/** + * getfssec: Get multiple clusters from a file, given the starting cluster. + * In this case, get multiple blocks from a specific TCP connection. + * + * @param: fs, the fs_info structure address, in pxe, we don't use this. + * @param: buf, buffer to store the read data + * @param: openfile, TFTP socket pointer + * @param: blocks, 512-byte block count; 0FFFFh = until end of file + * + * @return: the bytes read + * + */ +static uint32_t pxe_getfssec(struct file *gfile, char *buf, + int blocks, bool *have_more) +{ + struct open_file_t *file = gfile->open_file; + int count = blocks; + int chunk; + int bytes_read = 0; + + count <<= TFTP_BLOCKSIZE_LG2; + while (count) { + fill_buffer(file); /* If we have no 'fresh' buffer, get it */ + if (! file->tftp_bytesleft) + break; + + chunk = count; + if (chunk > file->tftp_bytesleft) + chunk = file->tftp_bytesleft; + file->tftp_bytesleft -= chunk; + memcpy(buf, MK_PTR(PKTBUF_SEG, file->tftp_dataptr), chunk); + file->tftp_dataptr += chunk; + buf += chunk; + bytes_read += chunk; + count -= chunk; + } + + + if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) { + fill_buffer(file); + *have_more = 1; + } else if (file->tftp_goteof) { + /* + * The socket is closed and the buffer drained; the caller will + * call close_file and therefore free the socket. + */ + *have_more = 0; + } + + return bytes_read; + } + + + +/* + * Fill the packet tail with the tftp informations then retures the lenght + */ +static int fill_tail(char *dst) +{ + static const char tail[] = "octet\0""tsize\0""0\0""blksize\0""1408"; + + memcpy(dst, tail, sizeof tail); + return sizeof tail; +} + + +/* + * + * + * searchdir: + * + * Open a TFTP connection to the server + * + * On entry: + * DS:DI = mangled filename + * If successful: + * ZF clear + * SI = socket pointer + * EAX = file length in bytes, or -1 if unknown + * If unsuccessful + * ZF set + * + */ +static void pxe_searchdir(char *filename, struct file *file) +{ + extern char tftp_proto_err[]; + char *buf = packet_buf; + char *p = filename; + char *options; + char *data; + struct open_file_t *open_file; + static __lowmem struct pxe_udp_write_pkt uw_pkt; + static __lowmem struct pxe_udp_read_pkt ur_pkt; + static __lowmem struct gpxe_file_open fo; + static __lowmem struct gpxe_get_file_size gs; + const struct tftp_options *tftp_opt; + int i = 0; + int err; + int buffersize; + const uint8_t *timeout_ptr; + uint8_t timeout; + uint16_t oldtime; + uint16_t tid; + uint16_t opcode; + uint16_t blk_num; + uint32_t ip; + uint32_t opdata, *opdata_ptr; + + open_file = allocate_socket(); + if (!open_file) { + file->file_len = 0; + file->open_file = NULL; + return; + } + + timeout_ptr = TimeoutTable; /* Reset timeout */ + + sendreq: + uw_pkt.buffer[0] = OFFS_WRT(buf, 0); + uw_pkt.buffer[1] = 0; + *(uint16_t *)buf = TFTP_RRQ; /* TFTP opcode */ + buf += 2; + + ip = *(uint32_t *)p; /* ip <- server override (if any) */ + p += 4; + if (ip == 0) { + /* Have prefix */ + strcpy(buf, PathPrefix); + buf += strlen(PathPrefix); + ip = ServerIP; /* Get the default server */ + } + + strcpy(buf, p); /* Copy the filename */ + buf += strlen(p) + 1; /* advance the pointer, null char included */ + +#if GPXE + if (is_gpxe(packet_buf + 2)) { + fo.status = PXENV_STATUS_BAD_FUNC; + fo.filename[0] = OFFS_WRT(packet_buf + 2, 0); + fo.filename[1] = 0; + err = pxe_call(PXENV_FILE_OPEN, &fo); + if (err) + goto done; + + open_file->tftp_localport = -1; + open_file->tftp_remoteport = fo.filehandle; + gs.filehandle = fo.filehandle; + +#if 0 + err = pxe_call(PXENV_GET_FILE_SIZE, &gs); + if (!err) + open_file->tftp_filesize = gs.filesize; + else +#endif + open_file->tftp_filesize = -1; + goto done; + } +#endif /* GPXE */ + + open_file->tftp_remoteip = ip; + tid = open_file->tftp_localport; /* TID(local port No) */ + uw_pkt.sip = ip; + uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; + uw_pkt.lport = tid; + uw_pkt.rport = ServerPort; + buf += fill_tail(buf); + uw_pkt.buffersize = buf - packet_buf; + err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); + if (err || uw_pkt.status != 0) + goto failure; /* + * In fact, the 'failure' target will not do + * a failure thing; it will move on to the + * next timeout, then tries again until + * _real_ time out + */ + + /* + * Danger, Will Robinson! We need to support tiemout + * and retry lest we just lost a packet ... + */ + + /* Packet transmitted OK, now we need to receive */ + timeout = *timeout_ptr++; + oldtime = BIOS_timer; + while (timeout) { + buf = packet_buf; + ur_pkt.buffer[0] = OFFS_WRT(buf, 0); + ur_pkt.buffer[1] = 0; + ur_pkt.buffersize = 2048; + ur_pkt.dip = MyIP; + ur_pkt.lport = tid; + err = pxe_call(PXENV_UDP_READ, &ur_pkt); + if (err) { + if (oldtime == BIOS_timer) + continue; + timeout --; /* Decrease one timer tick */ + if (!timeout) + goto failure; + } + + /* Make sure the packet actually came from the server */ + if (ur_pkt.sip == open_file->tftp_remoteip) + break; + } + + /* Got packet; reset timeout */ + timeout_ptr = TimeoutTable; + open_file->tftp_remoteport = ur_pkt.rport; + + /* filesize <- -1 == unknown */ + open_file->tftp_filesize = -1; + /* Default blksize unless blksize option negotiated */ + open_file->tftp_blksize = TFTP_BLOCKSIZE; + buffersize = ur_pkt.buffersize - 2; /* bytes after opcode */ + if (buffersize < 0) + goto failure; /* Garbled reply */ + + /* + * Get the opcode type, and parse it + */ + opcode = *(uint16_t *)packet_buf; + switch (opcode) { + case TFTP_ERROR: + open_file->tftp_filesize = 0; + break; /* ERROR reply; don't try again */ + + case TFTP_DATA: + /* + * If the server doesn't support any options, we'll get a + * DATA reply instead of OACK. Stash the data in the file + * buffer and go with the default value for all options... + * + * We got a DATA packet, meaning no options are + * suported. Save the data away and consider the + * length undefined, *unless* this is the only + * data packet... + */ + buffersize -= 2; + if (buffersize < 0) + goto failure; + data = packet_buf + 2; + blk_num = *(uint16_t *)data; + data += 2; + if (blk_num != htons(1)) + goto failure; + open_file->tftp_lastpkt = blk_num; + if (buffersize > TFTP_BLOCKSIZE) + goto err_reply; /* Corrupt */ + else if (buffersize < TFTP_BLOCKSIZE) { + /* + * This is the final EOF packet, already... + * We know the filesize, but we also want to + * ack the packet and set the EOF flag. + */ + open_file->tftp_filesize = buffersize; + open_file->tftp_goteof = 1; + ack_packet(open_file, blk_num); + } + + open_file->tftp_bytesleft = buffersize; + open_file->tftp_dataptr = open_file->tftp_pktbuf; + memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize); + break; + + case TFTP_OACK: + /* + * Now we need to parse the OACK packet to get the transfer + * and packet sizes. + */ + + options = packet_buf + 2; + p = options; + + while (buffersize) { + char *opt = p; + + /* + * If we find an option which starts with a NUL byte, + * (a null option), we're either seeing garbage that some + * TFTP servers add to the end of the packet, or we have + * no clue how to parse the rest of the packet (what is + * an option name and what is a value?) In either case, + * discard the rest. + */ + if (!*opt) + goto done; + + while (buffersize) { + if (!*p) + break; /* Found a final null */ + *p++ |= 0x20; + buffersize--; + } + if (!buffersize) + break; /* Unterminated option */ + + /* Consume the terminal null */ + p++; + buffersize--; + + if (!buffersize) + break; /* No option data */ + + /* + * Parse option pointed to by options; guaranteed to be + * null-terminated + */ + tftp_opt = tftp_options; + for (i = 0; i < tftp_nopts; i++) { + if (!strcmp(opt, tftp_opt->str_ptr)) + break; + tftp_opt++; + } + if (i == tftp_nopts) + goto err_reply; /* Non-negotitated option returned, + no idea what it means ...*/ + + /* get the address of the filed that we want to write on */ + opdata_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset); + opdata = 0; + + /* do convert a number-string to decimal number, just like atoi */ + while (buffersize--) { + uint8_t d = *p++; + if (d == '\0') + break; /* found a final null */ + d -= '0'; + if (d > 9) + goto err_reply; /* Not a decimal digit */ + opdata = opdata*10 + d; + } + *opdata_ptr = opdata; + } + break; + + default: + printf("TFTP unknown opcode %d\n", ntohs(opcode)); + goto err_reply; + } + +done: + if (!open_file->tftp_filesize) { + free_socket(open_file); + file->file_len = 0; + file->open_file = NULL; + return; + } + file->open_file = (void *)open_file; + file->file_len = open_file->tftp_filesize; + return; + +err_reply: + uw_pkt.rport = open_file->tftp_remoteport; + uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); + uw_pkt.buffer[1] = 0; + uw_pkt.buffersize = 24; + pxe_call(PXENV_UDP_WRITE, &uw_pkt); + printf("TFTP server sent an incomprehesible reply\n"); + call16(kaboom, NULL, NULL); + +failure: + timeout_ptr++; + if (*timeout_ptr) + goto sendreq; /* Try again */ +} + + +/* + * Store standard filename prefix + */ +static void get_prefix(void) +{ + int len; + char *p; + char c; + + if (DHCPMagic & 0x04) /* Did we get a path prefix option */ + goto got_prefix; + + strcpy(PathPrefix, BootFile); + len = strlen(PathPrefix); + p = &PathPrefix[len - 1]; + + while (len--) { + c = *p--; + c |= 0x20; + + c = (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c == '.' || c == '-'); + if (!c) + break; + }; + + if (len < 0) + p --; + + *(p + 2) = 0; /* Zero-terminate after delimiter */ + + got_prefix: + printf("%s%s\n", tftpprefix_msg, PathPrefix); + strcpy(CurrentDirName, PathPrefix); +} + + /** + * try to load a config file, if found, return 1, or return 0 + * + */ +static int try_load(com32sys_t *regs) +{ + extern char KernelName[]; + char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]); + + printf("Trying to load: %-50s ", config_name); + pxe_mangle_name(KernelName, config_name); + + regs->edi.w[0] = OFFS_WRT(KernelName, 0); + call16(core_open, regs, regs); + if (regs->eflags.l & EFLAGS_ZF) { + printf(" [FAILED]\n"); + return 0; + } else { + printf(" [ OK ]\n"); + return 1; + } +} + + + /* + * load configuration file + * + */ +static void pxe_load_config(com32sys_t *regs) +{ + extern void no_config(void); + char *cfgprefix = "pxelinux.cfg/"; + char *default_str = "default"; + char *config_file; /* Pointer to the variable suffix */ + char *p; + + uint8_t *uuid_ptr; + + int tries = 8; + char *last; + + get_prefix(); + if (DHCPMagic & 0x02) { + /* We got a DHCP option, try it first */ + if (try_load(regs)) + return; + } + + memcpy(ConfigName, cfgprefix, strlen(cfgprefix)); + config_file = ConfigName + strlen(cfgprefix); + /* + * Have to guess config file name ... + */ + + /* Try loading by UUID */ + if (HaveUUID) { + uuid_ptr = uuid_dashes; + p = config_file; + while (*uuid_ptr) { + int len = *uuid_ptr; + char *src = UUID; + + lchexbytes(p, src, len); + p += len * 2; + src += len; + uuid_ptr++; + *p++ = '-'; + } + /* Remove last dash and zero-terminate */ + *--p = '\0'; + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + } + + /* Try loading by MAC address */ + strcpy(config_file, MACStr); + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + +#if 0 + printf("MY IP: %p(%X)\n", MyIP, *(uint32_t *)MyIP); + #endif + + /* Nope, try hexadecimal IP prefixes... */ + uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */ + last = &config_file[8]; + while (tries) { + *last = '\0'; /* Zero-terminate string */ + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + last--; /* Drop one character */ + tries--; + }; + + /* Final attempt: "default" string */ + strcpy(config_file, default_str); + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + if (try_load(regs)) + return; + + printf("Unable to locate configuration file\n"); + call16(kaboom, NULL, NULL); +} + + + +/* + * Generate the botif string, and the hardware-based config string + */ +static void make_bootif_string(void) +{ + char *bootif_str = "BOOTIF="; + uint8_t *src = &MACType; /* MACType just followed by MAC */ + char *dst; + int i = MACLen + 1; /* MACType included */ + + strcpy(BOOTIFStr, bootif_str); + dst = strchr(BOOTIFStr, '\0'); + for (; i > 0; i--) { + lchexbytes(dst, src, 1); + dst += 2; + src += 1; + *dst++ = '-'; + } + *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */ + +#if 0 + printf("%s\n", BOOTIFStr); +#endif +} +/* + ; + ; genipopt + ; + ; Generate an ip=::: + ; option into IPOption based on a DHCP packet in trackbuf. + ; Assumes CS == DS == ES. + ; +*/ +static void genipopt(void) +{ + char *p = IPOption; + int ip_len; + + strcpy(p, "ip="); + p += 3; + + ip_len = gendotquad(p, MyIP); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, ServerIP); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, Gateway); + p += ip_len; + *p++ = ':'; + + ip_len = gendotquad(p, Netmask); +} + + +/* Generate ip= option and print the ip adress */ +static void ip_init(void) +{ + int ip = MyIP; + char *myipaddr_msg = "My IP address seems to be "; + + genipopt(); + + gendotquad(DotQuadBuf, ip); + + ip = ntohl(ip); + printf("%s %08X %s\n", myipaddr_msg, ip, DotQuadBuf); + + printf("%s\n", IPOption); +} + +/* + * Validity check on possible !PXE structure in buf + * return 1 for success, 0 for failure. + * + */ +static int is_pxe(const void *buf) +{ + const struct pxe_t *pxe = buf; + const uint8_t *p = buf; + int i = pxe->structlength; + uint8_t sum = 0; + + if (i < sizeof(struct pxe_t) || + memcmp(pxe->signature, "!PXE", 4)) + return 0; + + while (i--) + sum += *p++; + + return sum == 0; +} + +/** + * Just like is_pxe, it checks PXENV+ structure + * + */ +static int is_pxenv(const void *buf) +{ + const struct pxenv_t *pxenv = buf; + const uint8_t *p = buf; + int i = pxenv->length; + uint8_t sum = 0; + + /* The pxeptr field isn't present in old versions */ + if (i < offsetof(struct pxenv_t, pxeptr) || + memcmp(pxenv->signature, "PXENV+", 6)) + return 0; + + while (i--) + sum += *p++; + + return sum == 0; +} + + + +/********************************************************************* +; +; memory_scan_for_pxe_struct: +; memory_scan_for_pxenv_struct: +; +; If none of the standard methods find the !PXE/PXENV+ structure, +; look for it by scanning memory. +; +; On exit, if found: +; ZF = 1, ES:BX -> !PXE structure +; Otherwise: +; ZF = 0 +; +; Assumes DS == CS +; Clobbers AX, BX, CX, DX, SI, ES +; + ********************************************************************/ + +static const void *memory_scan(uintptr_t start, int (*func)(const void *)) +{ + const char *ptr; + + /* Scan each 16 bytes of conventional memory before the VGA region */ + for (ptr = (const char *)start; ptr < (const char *)0xA0000; ptr += 16) { + if (func(ptr)) + return ptr; /* found it! */ + ptr += 16; + } + return NULL; +} + +static const struct pxe_t *memory_scan_for_pxe_struct(void) +{ + extern uint16_t BIOS_fbm; /* Starting segment */ + + return memory_scan(BIOS_fbm << 10, is_pxe); +} + +static const struct pxenv_t *memory_scan_for_pxenv_struct(void) +{ + return memory_scan(0x10000, is_pxenv); +} + +/* + * Find the !PXE structure; we search for the following, in order: + * + * a. !PXE structure as SS:[SP + 4] + * b. PXENV+ structure at [ES:BX] + * c. INT 1Ah AX=0x5650 -> PXENV+ + * d. Search memory for !PXE + * e. Search memory for PXENV+ + * + * If we find a PXENV+ structure, we try to find a !PXE structure from + * if if the API version is 2.1 or later + * + */ +static void pxe_init(void) +{ + extern void pxe_int1a(void); + char plan = 'A'; + uint16_t seg, off; + uint16_t code_seg, code_len; + uint16_t data_seg, data_len; + char *base = GET_PTR(InitStack); + com32sys_t regs; + const char *type; + const struct pxenv_t *pxenv; + const struct pxe_t *pxe; + + /* Assume API version 2.1 */ + APIVer = 0x201; + + /* Plan A: !PXE structure as SS:[SP + 4] */ + off = *(uint16_t *)(base + 48); + seg = *(uint16_t *)(base + 50); + pxe = MK_PTR(seg, off); + if (is_pxe(pxe)) + goto have_pxe; + + /* Plan B: PXENV+ structure at [ES:BX] */ + plan++; + off = *(uint16_t *)(base + 24); /* Original BX */ + seg = *(uint16_t *)(base + 4); /* Original ES */ + pxenv = MK_PTR(seg, off); + if (is_pxenv(pxenv)) + goto have_pxenv; + + /* + * Plan C: PXENV+ structure via INT 1Ah AX=5650h + */ + plan++; + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x5650; + call16(pxe_int1a, ®s, ®s); + if (!(regs.eflags.l & EFLAGS_CF) && (regs.eax.w[0] == 0x564e)) { + pxenv = MK_PTR(regs.es, regs.ebx.w[0]); + if (is_pxenv(pxenv)) + goto have_pxenv; + } + + /* Plan D: !PXE memory scan */ + plan++; + if ((pxe = memory_scan_for_pxe_struct())) + goto have_pxe; + + /* Plan E: PXENV+ memory scan */ + plan++; + if ((pxenv = memory_scan_for_pxenv_struct())) + goto have_pxenv; + + /* Found nothing at all !! */ + printf("%s\n", err_nopxe); + call16(kaboom, NULL, NULL); + + have_pxenv: + APIVer = pxenv->version; + printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer); + + /* if the API version number is 0x0201 or higher, use the !PXE structure */ + if (APIVer >= 0x201) { + if (pxenv->length >= sizeof(struct pxenv_t)) { + pxe = GET_PTR(pxenv->pxeptr); + if (is_pxe(pxe)) + goto have_pxe; + /* + * Nope, !PXE structure missing despite API 2.1+, or at least + * the pointer is missing. Do a last-ditch attempt to find it + */ + if ((pxe = memory_scan_for_pxe_struct())) + goto have_pxe; + } + } + + /* Otherwise, no dice, use PXENV+ structure */ + data_len = pxenv->undidatasize; + data_seg = pxenv->undidataseg; + code_len = pxenv->undicodesize; + code_seg = pxenv->undicodeseg; + PXEEntry = pxenv->rmentry; + type = "PXENV+"; + goto have_entrypoint; + + have_pxe: + data_len = pxe->seg[PXE_Seg_UNDIData].size; + data_seg = pxe->seg[PXE_Seg_UNDIData].sel; + code_len = pxe->seg[PXE_Seg_UNDICode].size; + code_seg = pxe->seg[PXE_Seg_UNDICode].sel; + PXEEntry = pxe->entrypointsp; + type = "!PXE"; + + have_entrypoint: + printf("%s entry point found (we hope) at %04X:%04X via plan %c\n", + type, PXEEntry.seg, PXEEntry.offs, plan); + printf("UNDI code segment at %04X len %04X\n", code_seg, code_len); + printf("UNDI data segment at %04X len %04X\n", data_seg, data_len); + + code_seg = code_seg + ((code_len + 15) >> 4); + data_seg = data_seg + ((data_len + 15) >> 4); + + RealBaseMem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */ +} + +/* + * Initialize UDP stack + * + */ +static void udp_init(void) +{ + int err; + static __lowmem struct pxe_udp_open_pkt uo_pkt; + uo_pkt.sip = MyIP; + err = pxe_call(PXENV_UDP_OPEN, &uo_pkt); + if (err || uo_pkt.status) { + printf("%s", err_udpinit); + printf("%d\n", uo_pkt.status); + call16(kaboom, NULL, NULL); + } +} + + +/* + * Network-specific initialization + */ +static void network_init(void) +{ + struct bootp_t *bp = (struct bootp_t *)trackbuf; + int pkt_len; + + *LocalDomain = 0; /* No LocalDomain received */ + + /* + * Get the DHCP client identifiers (query info 1) + */ + printf("%s", get_packet_msg); + pkt_len = pxe_get_cached_info(1); + parse_dhcp(pkt_len); + /* + ; We don't use flags from the request packet, so + ; this is a good time to initialize DHCPMagic... + ; Initialize it to 1 meaning we will accept options found; + ; in earlier versions of PXELINUX bit 0 was used to indicate + ; we have found option 208 with the appropriate magic number; + ; we no longer require that, but MAY want to re-introduce + ; it in the future for vendor encapsulated options. + */ + *(char *)&DHCPMagic = 1; + + + /* + * Get the BOOTP/DHCP packet that brought us file (and an IP + * address). This lives in the DHCPACK packet (query info 2) + */ + pkt_len = pxe_get_cached_info(2); + parse_dhcp(pkt_len); + /* + * Save away MAC address (assume this is in query info 2. If this + * turns out to be problematic it might be better getting it from + * the query info 1 packet + */ + MACLen = bp->hardlen > 16 ? 0 : bp->hardlen; + MACType = bp->hardware; + memcpy(MAC, bp->macaddr, MACLen); + + + /* + * Get the boot file and other info. This lives in the CACHED_REPLY + * packet (query info 3) + */ + pkt_len = pxe_get_cached_info(3); + parse_dhcp(pkt_len); + + printf("\n"); + + + + make_bootif_string(); + ip_init(); + + /* + * Check to see if we got any PXELINUX-specific DHCP options; in particular, + * if we didn't get the magic enable, do not recognize any other options. + */ + if ((DHCPMagic & 1) == 0) + DHCPMagic = 0; + + udp_init(); +} + +/* + * Initialize pxe fs + * + */ +static int pxe_fs_init(struct fs_info *fs) +{ + (void)fs; /* drop the compile warning message */ + + /* Initialize the Files structure */ + files_init(); + + /* do the pxe initialize */ + pxe_init(); + + /* Network-specific initialization */ + network_init(); + + return 0; +} + +const struct fs_ops pxe_fs_ops = { + .fs_name = "pxe", + .fs_flags = FS_NODEV, + .fs_init = pxe_fs_init, + .searchdir = pxe_searchdir, + .getfssec = pxe_getfssec, + .close_file = pxe_close_file, + .mangle_name = pxe_mangle_name, + .unmangle_name = pxe_unmangle_name, + .load_config = pxe_load_config +}; diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h new file mode 100644 index 00000000..1f66032e --- /dev/null +++ b/core/fs/pxe/pxe.h @@ -0,0 +1,219 @@ +/* ----------------------------------------------------------------------- + * + * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe.h + * + * PXE opcodes + * + */ +#ifndef PXE_H +#define PXE_H + +#include + +/* + * Some basic defines... + */ +#define PKTBUF_SIZE (65536 / MAX_OPEN) + +#define TFTP_BLOCKSIZE_LG2 9 +#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) +#define PKTBUF_SEG 0x4000 +#define DNS_MAX_SERVERS 4 + +#define is_digit(c) (((c) >= '0') && ((c) <= '9')) + +/* + * TFTP operation codes + */ +#define TFTP_RRQ htons(1) // Read rest +#define TFTP_WRQ htons(2) // Write rest +#define TFTP_DATA htons(3) // Data packet +#define TFTP_ACK htons(4) // ACK packet +#define TFTP_ERROR htons(5) // ERROR packet +#define TFTP_OACK htons(6) // OACK packet + +/* + * TFTP error codes + */ +#define TFTP_EUNDEF htons(0) // Unspecified error +#define TFTP_ENOTFOUND htons(1) // File not found +#define TFTP_EACCESS htons(2) // Access violation +#define TFTP_ENOSPACE htons(3) // Disk full +#define TFTP_EBADOP htons(4) // Invalid TFTP operation +#define TFTP_EBADID htons(5) // Unknown transfer +#define TFTP_EEXISTS htons(6) // File exists +#define TFTP_ENOUSER htons(7) // No such user +#define TFTP_EOPTNEG htons(8) // Option negotiation failure + +#define BOOTP_OPTION_MAGIC htonl(0x63825363) +#define MAC_MAX 32 + +/* + * structures + */ + +struct pxenv_t { + uint8_t signature[6]; /* PXENV+ */ + uint16_t version; + uint8_t length; + uint8_t checksum; + segoff16_t rmentry; + uint32_t pmoffset; + uint16_t pmselector; + uint16_t stackseg; + uint16_t stacksize; + uint16_t bc_codeseg; + uint16_t bc_codesize; + uint16_t bc_dataseg; + uint16_t bc_datasize; + uint16_t undidataseg; + uint16_t undidatasize; + uint16_t undicodeseg; + uint16_t undicodesize; + segoff16_t pxeptr; +} __packed; + +struct pxe_t { + uint8_t signature[4]; /* !PXE */ + uint8_t structlength; + uint8_t structcksum; + uint8_t structrev; + uint8_t _pad1; + segoff16_t undiromid; + segoff16_t baseromid; + segoff16_t entrypointsp; + segoff16_t entrypointesp; + segoff16_t statuscallout; + uint8_t _pad2; + uint8_t segdesccnt; + uint16_t firstselector; + pxe_segdesc_t seg[7]; +} __packed; + +enum pxe_segments { + PXE_Seg_Stack = 0, + PXE_Seg_UNDIData = 1, + PXE_Seg_UNDICode = 2, + PXE_Seg_UNDICodeWrite = 3, + PXE_Seg_BC_Data = 4, + PXE_Seg_BC_Code = 5, + PXE_Seg_BC_CodeWrite = 6 +}; + +struct bootp_t { + uint8_t opcode; /* BOOTP/DHCP "opcode" */ + uint8_t hardware; /* ARP hreadware type */ + uint8_t hardlen; /* Hardware address length */ + uint8_t gatehops; /* Used by forwarders */ + uint32_t ident; /* Transaction ID */ + uint16_t seconds; /* Seconds elapsed */ + uint16_t flags; /* Broadcast flags */ + uint32_t cip; /* Cient IP */ + uint32_t yip; /* "Your" IP */ + uint32_t sip; /* Next Server IP */ + uint32_t gip; /* Relay agent IP */ + uint8_t macaddr[16]; /* Client MAC address */ + uint8_t sname[64]; /* Server name (optional) */ + char bootfile[128]; /* Boot file name */ + uint32_t option_magic; /* Vendor option magic cookie */ + uint8_t options[1260]; /* Vendor options */ +} __attribute__ ((packed)); + +struct open_file_t { + uint16_t tftp_localport; /* Local port number (0=not in us)*/ + uint16_t tftp_remoteport; /* Remote port number */ + uint32_t tftp_remoteip; /* Remote IP address */ + uint32_t tftp_filepos; /* bytes downloaded (includeing buffer) */ + uint32_t tftp_filesize; /* Total file size(*) */ + uint32_t tftp_blksize; /* Block size for this connection(*) */ + uint16_t tftp_bytesleft; /* Unclaimed data bytes */ + uint16_t tftp_lastpkt; /* Sequence number of last packet (NBO) */ + uint16_t tftp_dataptr; /* Pointer to available data */ + uint8_t tftp_goteof; /* 1 if the EOF packet received */ + uint8_t tftp_unused; /* Currently unused */ + /* These values are preinitialized and not zeroed on close */ + uint16_t tftp_nextport; /* Next port number for this slot (HBO) */ + uint16_t tftp_pktbuf; /* Packet buffer offset */ +} __attribute__ ((packed)); + +struct pxe_udp_write_pkt { + uint16_t status; + uint32_t sip; + uint32_t gip; + uint16_t lport; + uint16_t rport; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +struct pxe_udp_read_pkt { + uint16_t status; + uint32_t sip; + uint32_t dip; + uint16_t rport; + uint16_t lport; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +struct pxe_bootp_query_pkt { + uint16_t status; + uint16_t packettype; + uint16_t buffersize; + uint16_t buffer[2]; + uint16_t bufferlimit; +} __attribute__ ((packed)); + +struct pxe_udp_open_pkt { + uint16_t status; + uint32_t sip; +} __attribute__ ((packed)); + +struct gpxe_file_api_check { + uint16_t status; + uint16_t size; + uint32_t magic; + uint32_t provider; + uint32_t apimask; + uint32_t flags; +} __attribute__ ((packed)); + +struct gpxe_file_open { + uint16_t status; + uint16_t filehandle; + uint16_t filename[2]; + uint32_t reserved; +} __attribute__ ((packed)); + +struct gpxe_get_file_size { + uint16_t status; + uint16_t filehandle; + uint32_t filesize; +} __attribute__ ((packed)); + +struct gpxe_file_read { + uint16_t status; + uint16_t filehandle; + uint16_t buffersize; + uint16_t buffer[2]; +} __attribute__ ((packed)); + +/* + * functions + */ +int ip_ok(uint32_t); +void parse_dhcp(int); +void parse_dhcp_options(void *, int, int); + +#endif /* pxe.h */ diff --git a/core/include/ext2_fs.h b/core/include/ext2_fs.h deleted file mode 100644 index d579eade..00000000 --- a/core/include/ext2_fs.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef __EXT2_FS_H -#define __EXT2_FS_H - -#include - -#define EXT2_SUPER_MAGIC 0xEF53 - -#define EXT2_GOOD_OLD_REV 0 // The good old (original) format -#define EXT2_DYNAMIC_REV 1 // V2 format w/ dynamic inode sizes -#define EXT2_GOOD_OLD_INODE_SIZE 128 - -// Special inode numbers -#define EXT2_BAD_INO 1 // Bad blocks inode -#define EXT2_ROOT_INO 2 // Root inode -#define EXT2_BOOT_LOADER_INO 5 // Boot loader inode -#define EXT2_UNDEL_DIR_INO 6 // Undelete directory inode -#define EXT3_RESIZE_INO 7 // Reserved group descriptors inode -#define EXT3_JOURNAL_INO 8 // Journal inode - -// We're readonly, so we only care about incompat features. -#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 -#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 -#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 -#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - -#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) - - -/* for EXT4 extent */ -#define EXT4_EXT_MAGIC 0xf30a -#define EXT4_EXTENTS_FLAG 0x00080000 - -/* - * File types and file modes - */ -#define S_IFDIR 0040000 // Directory -#define S_IFCHR 0020000 // Character device -#define S_IFBLK 0060000 // Block device -#define S_IFREG 0100000 // Regular file -#define S_IFIFO 0010000 // FIFO -#define S_IFLNK 0120000 // Symbolic link -#define S_IFSOCK 0140000 // Socket - -#define S_IFSHIFT 12 - -#define T_IFDIR (S_IFDIR >> S_IFSHIFT) -#define T_IFCHR (S_IFCHR >> S_IFSHIFT) -#define T_IFBLK (S_IFBLK >> S_IFSHIFT) -#define T_IFREG (S_IFREG >> S_IFSHIFT) -#define T_IFIFO (S_IFIFO >> S_IFSHIFT) -#define T_IFLNK (S_IFLNK >> S_IFSHIFT) -#define T_IFSOCK (S_IFSOCK >> S_IFSHIFT) - - -#define ext2_group_desc_lg2size 5 - - - -/* - * super block structure: - * include/linux/ext2_fs.h - */ -struct ext2_super_block { - uint32_t s_inodes_count; /* Inodes count */ - uint32_t s_blocks_count; /* Blocks count */ - uint32_t s_r_blocks_count; /* Reserved blocks count */ - uint32_t s_free_blocks_count; /* Free blocks count */ - uint32_t s_free_inodes_count; /* Free inodes count */ - uint32_t s_first_data_block; /* First Data Block */ - uint32_t s_log_block_size; /* Block size */ - uint32_t s_log_frag_size; /* Fragment size */ - uint32_t s_blocks_per_group; /* # Blocks per group */ - uint32_t s_frags_per_group; /* # Fragments per group */ - uint32_t s_inodes_per_group; /* # Inodes per group */ - uint32_t s_mtime; /* Mount time */ - uint32_t s_wtime; /* Write time */ - uint16_t s_mnt_count; /* Mount count */ - int16_t s_max_mnt_count; /* Maximal mount count */ - uint16_t s_magic; /* Magic signature */ - uint16_t s_state; /* File system state */ - uint16_t s_errors; /* Behaviour when detecting errors */ - uint16_t s_minor_rev_level; - uint32_t s_lastcheck; /* time of last check */ - uint32_t s_checkinterval; /* max. time between checks */ - uint32_t s_creator_os; /* OS */ - uint32_t s_rev_level; /* Revision level */ - uint16_t s_def_resuid; /* Default uid for reserved blocks */ - uint16_t s_def_resgid; /* Default gid for reserved blocks */ - - uint32_t s_first_ino; /* First non-reserved inode */ - uint16_t s_inode_size; /* size of inode structure */ - uint16_t s_block_group_nr; /* block group # of this superblock */ - uint32_t s_feature_compat; /* compatible feature set */ - uint32_t s_feature_incompat; /* incompatible feature set */ - uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ - uint8_t s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ - uint32_t s_algorithm_usage_bitmap; /* For compression */ - uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - uint8_t s_prealloc_dir_blocks; - uint16_t s_padding1; - uint32_t s_reserved[204]; /* Padding to the end of the block */ -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_super_block_size != 1024 -#error ext2_super_block definition bogus -#endif -#endif -*******************************************************************************/ - -/* - * ext2 group desc structure: - */ -struct ext2_group_desc { - uint32_t bg_block_bitmap; /* Blocks bitmap block */ - uint32_t bg_inode_bitmap; /* Inodes bitmap block */ - uint32_t bg_inode_table; /* Inodes table block */ - uint16_t bg_free_blocks_count; /* Free blocks count */ - uint16_t bg_free_inodes_count; /* Free inodes count */ - uint16_t bg_used_dirs_count; /* Directories count */ - uint16_t bg_pad; - uint32_t bg_reserved[3]; -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_group_desc_size != 32 -#error ext2_group_desc definition bogus -#endif -#endif -*******************************************************************************/ - - -/* - * ext2 inode structure: - */ -struct ext2_inode { - uint16_t i_mode; /* File mode */ - uint16_t i_uid; /* Owner Uid */ - uint32_t i_size; /* 4: Size in bytes */ - uint32_t i_atime; /* Access time */ - uint32_t i_ctime; /* 12: Creation time */ - uint32_t i_mtime; /* Modification time */ - uint32_t i_dtime; /* 20: Deletion Time */ - uint16_t i_gid; /* Group Id */ - uint16_t i_links_count; /* 24: Links count */ - uint32_t i_blocks; /* Blocks count */ - uint32_t i_flags; /* 32: File flags */ - uint32_t l_i_reserved1; - uint32_t i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ - uint32_t i_version; /* File version (for NFS) */ - uint32_t i_file_acl; /* File ACL */ - uint32_t i_dir_acl; /* Directory ACL */ - uint32_t i_faddr; /* Fragment address */ - uint8_t l_i_frag; /* Fragment number */ - uint8_t l_i_fsize; /* Fragment size */ - uint16_t i_pad1; - uint32_t l_i_reserved2[2]; -}; - -/******************************************************************************* -#ifndef DEPEND -#if ext2_inode_size != 128 -#error ext2_inode definition bogus -#endif -#endif -*******************************************************************************/ - - -#define EXT2_NAME_LEN 255 -struct ext2_dir_entry { - unsigned int d_inode; /* Inode number */ - unsigned short d_rec_len; /* Directory entry length */ - unsigned char d_name_len; /* Name length */ - unsigned char d_file_type; - char d_name[EXT2_NAME_LEN]; /* File name */ -}; - -/******************************************************************************* -#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) -*******************************************************************************/ - - - - - - -/* - * This is the extent on-disk structure. - * It's used at the bottom of the tree. - */ -struct ext4_extent { - uint32_t ee_block; /* first logical block extent covers */ - uint16_t ee_len; /* number of blocks covered by extent */ - uint16_t ee_start_hi; /* high 16 bits of physical block */ - uint32_t ee_start_lo; /* low 32 bits of physical block */ -}; - -/* - * This is index on-disk structure. - * It's used at all the levels except the bottom. - */ -struct ext4_extent_idx { - uint32_t ei_block; /* index covers logical blocks from 'block' */ - uint32_t ei_leaf_lo; /* pointer to the physical block of the next * - * level. leaf or next index could be there */ - uint16_t ei_leaf_hi; /* high 16 bits of physical block */ - uint16_t ei_unused; -}; - -/* - * Each block (leaves and indexes), even inode-stored has header. - */ -struct ext4_extent_header { - uint16_t eh_magic; /* probably will support different formats */ - uint16_t eh_entries; /* number of valid entries */ - uint16_t eh_max; /* capacity of store in entries */ - uint16_t eh_depth; /* has tree real underlying blocks? */ - uint32_t eh_generation; /* generation of the tree */ -}; - - - -#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) ) -#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) ) - - - - - - - -/* function declartion */ -/******************************************************************************* -extern struct open_file_t * ext2_read(char *); -extern int ext2_read(struct open_file_t *, char *, int); -*******************************************************************************/ - - -#endif /* ext2_fs.h */ diff --git a/core/include/fat_fs.h b/core/include/fat_fs.h deleted file mode 100644 index 71c1d9a7..00000000 --- a/core/include/fat_fs.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef FAT_FS_H -#define FAT_FS_H - -#include - -#define FAT_DIR_ENTRY_SIZE 32 -#define DIRENT_SHIFT 5 - -#define FAT_ATTR_READ_ONLY 0x01 -#define FAT_ATTR_HIDDEN 0x02 -#define FAT_ATTR_SYSTEM 0x04 -#define FAT_ATTR_VOLUME_ID 0x08 -#define FAT_ATTR_DIRECTORY 0x10 -#define FAT_ATTR_ARCHIVE 0x20 - -#define FAT_MAXFILE 256 - -#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY \ - | FAT_ATTR_HIDDEN \ - | FAT_ATTR_SYSTEM \ - | FAT_ATTR_VOLUME_ID) - -#define FAT_ATTR_VALID (FAT_ATTR_READ_ONLY \ - | FAT_ATTR_HIDDEN \ - | FAT_ATTR_SYSTEM \ - | FAT_ATTR_DIRECTORY \ - | FAT_ATTR_ARCHIVE) - -enum fat_type{ FAT12, FAT16, FAT32 }; - -/* - * The fat file system structures - */ - -struct fat_bpb { - uint8_t jmp_boot[3]; - uint8_t oem_name[8]; - uint16_t sector_size; - uint8_t bxSecPerClust; - uint16_t bxResSectors; - uint8_t bxFATs; - uint16_t bxRootDirEnts; - uint16_t bxSectors; - uint8_t media; - uint16_t bxFATsecs; - uint16_t sectors_per_track; - uint16_t num_heads; - uint32_t num_hidden_sectors; - uint32_t bsHugeSectors; - - union { - struct { - uint8_t num_ph_drive; - uint8_t reserved; - uint8_t boot_sig; - uint32_t num_serial; - uint8_t label[11]; - uint8_t fstype[8]; - } __attribute__ ((packed)) fat12_16; - - struct { - uint32_t bxFATsecs_32; - uint16_t extended_flags; - uint16_t fs_version; - uint32_t root_cluster; - uint16_t fs_info; - uint16_t backup_boot_sector; - uint8_t reserved[12]; - uint8_t num_ph_drive; - uint8_t reserved1; - uint8_t boot_sig; - uint32_t num_serial; - uint8_t label[11]; - uint8_t fstype[8]; - } __attribute__ ((packed)) fat32; - - } __attribute__ ((packed)) u; - -} __attribute__ ((packed)); - - - -struct fat_dir_entry { - char name[11]; - uint8_t attr; - uint8_t nt_reserved; - uint8_t c_time_tenth; - uint16_t c_time; - uint16_t c_date; - uint16_t a_date; - uint16_t first_cluster_high; - uint16_t w_time; - uint16_t w_date; - uint16_t first_cluster_low; - uint32_t file_size; -} __attribute__ ((packed)); - - - -struct fat_long_name_entry { - uint8_t id; - uint16_t name1[5]; - uint8_t attr; - uint8_t reserved; - uint8_t checksum; - uint16_t name2[6]; - uint16_t first_cluster; - uint16_t name3[2]; -} __attribute__ ((packed)); - - - - -#endif /* fat_fs.h */ diff --git a/core/include/iso9660_fs.h b/core/include/iso9660_fs.h deleted file mode 100644 index ca123b16..00000000 --- a/core/include/iso9660_fs.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ISO9660_FS_H -#define ISO9660_FS_H - -#include - -struct iso_dir_entry { - uint8_t length; /* 00 */ - uint8_t ext_attr_length; /* 01 */ - uint8_t extent[8]; /* 02 */ - uint8_t size[8]; /* 0a */ - uint8_t date[7]; /* 12 */ - uint8_t flags; /* 19 */ - uint8_t file_unit_size; /* 1a */ - uint8_t interleave; /* 1b */ - uint8_t volume_sequence_number[4]; /* 1c */ - uint8_t name_len; /* 20 */ - //uint8_t name[]; /* 21 */ -}; - - -#endif /* iso9660_fs.h */ diff --git a/core/include/pxe.h b/core/include/pxe.h deleted file mode 100644 index 1f66032e..00000000 --- a/core/include/pxe.h +++ /dev/null @@ -1,219 +0,0 @@ -/* ----------------------------------------------------------------------- - * - * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved - * - * 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, Inc., 53 Temple Place Ste 330, - * Boston MA 02111-1307, USA; either version 2 of the License, or - * (at your option) any later version; incorporated herein by reference. - * - * ----------------------------------------------------------------------- */ - -/* - * pxe.h - * - * PXE opcodes - * - */ -#ifndef PXE_H -#define PXE_H - -#include - -/* - * Some basic defines... - */ -#define PKTBUF_SIZE (65536 / MAX_OPEN) - -#define TFTP_BLOCKSIZE_LG2 9 -#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) -#define PKTBUF_SEG 0x4000 -#define DNS_MAX_SERVERS 4 - -#define is_digit(c) (((c) >= '0') && ((c) <= '9')) - -/* - * TFTP operation codes - */ -#define TFTP_RRQ htons(1) // Read rest -#define TFTP_WRQ htons(2) // Write rest -#define TFTP_DATA htons(3) // Data packet -#define TFTP_ACK htons(4) // ACK packet -#define TFTP_ERROR htons(5) // ERROR packet -#define TFTP_OACK htons(6) // OACK packet - -/* - * TFTP error codes - */ -#define TFTP_EUNDEF htons(0) // Unspecified error -#define TFTP_ENOTFOUND htons(1) // File not found -#define TFTP_EACCESS htons(2) // Access violation -#define TFTP_ENOSPACE htons(3) // Disk full -#define TFTP_EBADOP htons(4) // Invalid TFTP operation -#define TFTP_EBADID htons(5) // Unknown transfer -#define TFTP_EEXISTS htons(6) // File exists -#define TFTP_ENOUSER htons(7) // No such user -#define TFTP_EOPTNEG htons(8) // Option negotiation failure - -#define BOOTP_OPTION_MAGIC htonl(0x63825363) -#define MAC_MAX 32 - -/* - * structures - */ - -struct pxenv_t { - uint8_t signature[6]; /* PXENV+ */ - uint16_t version; - uint8_t length; - uint8_t checksum; - segoff16_t rmentry; - uint32_t pmoffset; - uint16_t pmselector; - uint16_t stackseg; - uint16_t stacksize; - uint16_t bc_codeseg; - uint16_t bc_codesize; - uint16_t bc_dataseg; - uint16_t bc_datasize; - uint16_t undidataseg; - uint16_t undidatasize; - uint16_t undicodeseg; - uint16_t undicodesize; - segoff16_t pxeptr; -} __packed; - -struct pxe_t { - uint8_t signature[4]; /* !PXE */ - uint8_t structlength; - uint8_t structcksum; - uint8_t structrev; - uint8_t _pad1; - segoff16_t undiromid; - segoff16_t baseromid; - segoff16_t entrypointsp; - segoff16_t entrypointesp; - segoff16_t statuscallout; - uint8_t _pad2; - uint8_t segdesccnt; - uint16_t firstselector; - pxe_segdesc_t seg[7]; -} __packed; - -enum pxe_segments { - PXE_Seg_Stack = 0, - PXE_Seg_UNDIData = 1, - PXE_Seg_UNDICode = 2, - PXE_Seg_UNDICodeWrite = 3, - PXE_Seg_BC_Data = 4, - PXE_Seg_BC_Code = 5, - PXE_Seg_BC_CodeWrite = 6 -}; - -struct bootp_t { - uint8_t opcode; /* BOOTP/DHCP "opcode" */ - uint8_t hardware; /* ARP hreadware type */ - uint8_t hardlen; /* Hardware address length */ - uint8_t gatehops; /* Used by forwarders */ - uint32_t ident; /* Transaction ID */ - uint16_t seconds; /* Seconds elapsed */ - uint16_t flags; /* Broadcast flags */ - uint32_t cip; /* Cient IP */ - uint32_t yip; /* "Your" IP */ - uint32_t sip; /* Next Server IP */ - uint32_t gip; /* Relay agent IP */ - uint8_t macaddr[16]; /* Client MAC address */ - uint8_t sname[64]; /* Server name (optional) */ - char bootfile[128]; /* Boot file name */ - uint32_t option_magic; /* Vendor option magic cookie */ - uint8_t options[1260]; /* Vendor options */ -} __attribute__ ((packed)); - -struct open_file_t { - uint16_t tftp_localport; /* Local port number (0=not in us)*/ - uint16_t tftp_remoteport; /* Remote port number */ - uint32_t tftp_remoteip; /* Remote IP address */ - uint32_t tftp_filepos; /* bytes downloaded (includeing buffer) */ - uint32_t tftp_filesize; /* Total file size(*) */ - uint32_t tftp_blksize; /* Block size for this connection(*) */ - uint16_t tftp_bytesleft; /* Unclaimed data bytes */ - uint16_t tftp_lastpkt; /* Sequence number of last packet (NBO) */ - uint16_t tftp_dataptr; /* Pointer to available data */ - uint8_t tftp_goteof; /* 1 if the EOF packet received */ - uint8_t tftp_unused; /* Currently unused */ - /* These values are preinitialized and not zeroed on close */ - uint16_t tftp_nextport; /* Next port number for this slot (HBO) */ - uint16_t tftp_pktbuf; /* Packet buffer offset */ -} __attribute__ ((packed)); - -struct pxe_udp_write_pkt { - uint16_t status; - uint32_t sip; - uint32_t gip; - uint16_t lport; - uint16_t rport; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - -struct pxe_udp_read_pkt { - uint16_t status; - uint32_t sip; - uint32_t dip; - uint16_t rport; - uint16_t lport; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - -struct pxe_bootp_query_pkt { - uint16_t status; - uint16_t packettype; - uint16_t buffersize; - uint16_t buffer[2]; - uint16_t bufferlimit; -} __attribute__ ((packed)); - -struct pxe_udp_open_pkt { - uint16_t status; - uint32_t sip; -} __attribute__ ((packed)); - -struct gpxe_file_api_check { - uint16_t status; - uint16_t size; - uint32_t magic; - uint32_t provider; - uint32_t apimask; - uint32_t flags; -} __attribute__ ((packed)); - -struct gpxe_file_open { - uint16_t status; - uint16_t filehandle; - uint16_t filename[2]; - uint32_t reserved; -} __attribute__ ((packed)); - -struct gpxe_get_file_size { - uint16_t status; - uint16_t filehandle; - uint32_t filesize; -} __attribute__ ((packed)); - -struct gpxe_file_read { - uint16_t status; - uint16_t filehandle; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - -/* - * functions - */ -int ip_ok(uint32_t); -void parse_dhcp(int); -void parse_dhcp_options(void *, int, int); - -#endif /* pxe.h */ diff --git a/core/iso9660.c b/core/iso9660.c deleted file mode 100644 index 583513cd..00000000 --- a/core/iso9660.c +++ /dev/null @@ -1,561 +0,0 @@ -#include -#include -//#include "cache.h" -#include "core.h" -#include "disk.h" -#include "iso9660_fs.h" -#include "fs.h" - -#define DEBUG 1 - -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) -#define ISO_SECTOR_SHIFT 11 -#define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) -#define ROOT_DIR_WORD 0x002f -#define TRACKBUF_SIZE 8192 - - -struct open_file_t { - sector_t file_sector; - uint32_t file_bytesleft; - uint32_t file_left; -}; - -static struct open_file_t Files[MAX_OPEN]; - -struct dir_t { - uint32_t dir_lba; /* Directory start (LBA) */ - uint32_t dir_len; /* Length in bytes */ - uint32_t dir_clust; /* Length in clusters */ -}; -static struct dir_t RootDir; -static struct dir_t CurrentDir; - -static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; - -static char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ -static char *ISOFileNameEnd = &ISOFileName[64]; - -/* - * use to store the block shift, since we treat the hd-mode as 512 bytes - * sector size, 2048 bytes block size. we still treat the cdrom as 2048 - * bytes sector size and also the block size. - */ -static int block_shift; - -/** - * allocate_file: - * - * allocate a file structure - * - */ -static struct open_file_t *allocate_file(void) -{ - struct open_file_t *file = Files; - int i; - - for (i = 0; i < MAX_OPEN; i++) { - if ( file->file_sector == 0 ) /* found it */ - return file; - file++; - } - - return NULL; /* not found */ -} - - -/** - * close_file: - * - * Deallocates a file structure - * - */ -static inline void close_pvt(struct open_file_t *file) -{ - file->file_sector = 0; -} - -static void iso_close_file(struct file *file) -{ - close_pvt(file->open_file); -} - -/** - * mangle_name: - * - * Mangle a filename pointed to by src into a buffer pointed - * to by dst; ends on encountering any whitespace. - * dst is preserved. - * - * This verifies that a filename is < FilENAME_MAX characters, - * doesn't contain whitespace, zero-pads the output buffer, - * and removes trailing dots and redumndant slashes, so "repe - * cmpsb" can do a compare, and the path-searching routine gets - * a bit of an easier job. - * - */ -static void iso_mangle_name(char *dst, char *src) -{ - char *p = dst; - int i = FILENAME_MAX - 1; - - while ( *src > ' ' ) { - if ( *src == '/' ) { - if ( *(src+1) == '/' ) { - i --; - src ++; - continue; - } - } - - *dst++ = *src ++; - i --; - } - - while ( 1 ) { - if ( dst == p ) - break; - - if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) - break; - - dst --; - i ++; - } - - i ++; - for (; i > 0; i -- ) - *dst++ = '\0'; -} - - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int iso_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - -/** - * compare the names si and di and report if they are - * equal from an ISO 9600 perspective. - * - * @param: de_name, the name from the file system. - * @param: len, the length of de_name, and will return the real name of the de_name - * ';' and other terminates excluded. - * @param: file_name, the name we want to check, is expected to end with a null - * - * @return: 1 on match, or 0. - * - */ -static int iso_compare_names(char *de_name, int *len, char *file_name) -{ - char *p = ISOFileName; - char c1, c2; - - int i = 0; - - while ( (i < *len) && *de_name && (*de_name != ';') && (p < ISOFileNameEnd - 1) ) { - *p++ = *de_name++; - i++; - } - - /* Remove terminal dots */ - while ( *(p-1) == '.' ) { - if ( *len <= 2 ) - break; - - if ( p <= ISOFileName ) - break; - p --; - i--; - } - - if ( i <= 0 ) - return 0; - - *p = '\0'; - - /* return the 'real' length of de_name */ - *len = i; - - p = ISOFileName; - - /* i is the 'real' name length of file_name */ - while ( i ) { - c1 = *p++; - c2 = *file_name++; - - if ( (c1 == 0) && (c2 == 0) ) - return 1; /* success */ - - else if ( (c1 == 0) || ( c2 == 0 ) ) - return 0; - - c1 |= 0x20; - c2 |= 0x20; /* convert to lower case */ - if ( c1 != c2 ) - return 0; - i --; - } - - return 1; -} - -static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, int count) -{ - /* changed those to _sector_ */ - block <<= block_shift; - count <<= block_shift; - return disk->rdwr_sectors(disk, buf, block, count, 0); -} - -/** - * iso_getfssec: - * - * Get multiple clusters from a file, given the file pointer. - * - * @param: buf - * @param: file, the address of the open file structure - * @param: sectors, how many we want to read at once - * @param: have_more, to indicate if we have reach the end of the file - * - */ -static uint32_t iso_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) -{ - uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; - struct disk *disk = fs->fs_dev->disk; - - if ( sectors > file->file_left ) - sectors = file->file_left; - - cdrom_read_sectors(disk, buf, file->file_sector, sectors); - - file->file_sector += sectors; - file->file_left -= sectors; - - if ( bytes_read >= file->file_bytesleft ) { - bytes_read = file->file_bytesleft; - *have_more = 0; - } else - *have_more = 1; - file->file_bytesleft -= bytes_read; - - return bytes_read; -} - - - -/** - * do_search_dir: - * - * find a file or directory with name within the _dir_ directory. - * - * the return value will tell us what we find, it's a file or dir? - * on 1 be dir, 2 be file, 0 be error. - * - * res will return the result. - * - */ -static int do_search_dir(struct fs_info *fs, struct dir_t *dir, - char *name, uint32_t *file_len, void **res) -{ - struct open_file_t *file; - struct iso_dir_entry *de; - struct iso_dir_entry tmpde; - - uint32_t offset = 0; /* let's start it with the start */ - uint32_t file_pos = 0; - char *de_name; - int de_len; - int de_name_len; - int have_more; - - file = allocate_file(); - if ( !file ) - return 0; - - file->file_left = dir->dir_clust; - file->file_sector = dir->dir_lba; - - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); - de = (struct iso_dir_entry *)trackbuf; - - while ( file_pos < dir->dir_len ) { - int found = 0; - - if ( (char *)de >= (char *)(trackbuf + TRACKBUF_SIZE) ) { - if ( !have_more ) - return 0; - - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); - offset = 0; - } - - de = (struct iso_dir_entry *) (trackbuf + offset); - - de_len = de->length; - - if ( de_len == 0) { - offset = file_pos = (file_pos+ISO_SECTOR_SIZE) & ~(ISO_SECTOR_SIZE-1); - continue; - } - - - offset += de_len; - - /* Make sure we have a full directory entry */ - if ( offset >= TRACKBUF_SIZE ) { - int slop = TRACKBUF_SIZE - offset + de_len; - memcpy(&tmpde, de, slop); - offset &= TRACKBUF_SIZE - 1; - file->file_sector ++; - if ( offset ) { - if ( !have_more ) - return 0; - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); - memcpy((void*)&tmpde + slop, trackbuf, offset); - } - de = &tmpde; - } - - if ( de_len < 33 ) { - printf("Corrutped directory entry in sector %d\n", file->file_sector); - return 0; - } - - de_name_len = de->name_len; - de_name = (char *)((void *)de + 0x21); - - - if ( (de_name_len == 1) && (*de_name == 0) ) { - found = iso_compare_names(".", &de_name_len, name); - - } else if ( (de_name_len == 1) && (*de_name == 1) ) { - de_name_len = 2; - found = iso_compare_names("..", &de_name_len, name); - - } else - found = iso_compare_names(de_name, &de_name_len, name); - - if (found) - break; - - file_pos += de_len; - } - - if ( file_pos >= dir->dir_len ) - return 0; /* not found */ - - - if ( *(name+de_name_len) && (*(name+de_name_len) != '/' ) ) { - printf("Something wrong happened during searching file %s\n", name); - - *res = NULL; - return 0; - } - - if ( de->flags & 0x02 ) { - /* it's a directory */ - dir = &CurrentDir; - dir->dir_lba = *(uint32_t *)de->extent; - dir->dir_len = *(uint32_t *)de->size; - dir->dir_clust = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - - *file_len = dir->dir_len; - *res = dir; - - /* we can close it now */ - close_pvt(file); - - /* Mark we got a directory */ - return 1; - } else { - /* it's a file */ - file->file_sector = *(uint32_t *)de->extent; - file->file_bytesleft = *(uint32_t *)de->size; - file->file_left = (file->file_bytesleft + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - - *file_len = file->file_bytesleft; - *res = file; - - /* Mark we got a file */ - return 2; - } -} - - -/** - * iso_searchdir: - * - * open a file - * - * searchdir_iso is a special entry point for ISOLINUX only. In addition - * to the above, searchdir_iso passes a file flag mask in AL. This is - * useful for searching for directories. - * - * well, it's not like the searchidr function in EXT fs or FAT fs; it also - * can read a diretory.(Just thought of mine, liu) - * - */ -static void iso_searchdir(char *filename, struct file *file) -{ - struct open_file_t *open_file = NULL; - struct dir_t *dir; - uint32_t file_len = 0; - int ret; - void *res; - - dir = &CurrentDir; - if ( *filename == '/' ) { - dir = &RootDir; - filename ++; - } - - while ( *filename ) { - ret = do_search_dir(file->fs, dir, filename, &file_len, &res); - if ( ret == 1 ) - dir = (struct dir_t *)res; - else if ( ret == 2 ) - break; - else - goto err; - - /* find the end */ - while ( *filename && (*filename != '/') ) - filename ++; - - /* skip the slash */ - while ( *filename && (*filename == '/') ) - filename++; - } - - /* well , we need recheck it , becuase it can be a directory */ - if ( ret == 2 ) { - open_file = (struct open_file_t *)res; - goto found; - } else { - open_file = allocate_file(); - if ( !open_file ) - goto err; - - open_file->file_sector = dir->dir_lba; - open_file->file_bytesleft = dir->dir_len; - open_file->file_left = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - goto found; - } - err: - close_pvt(open_file); - file_len = 0; - open_file = NULL; - - found: - file->file_len = file_len; - file->open_file = (void*)open_file; - -#if 0 - if (open_file) { - printf("file bytesleft: %d\n", open_file->file_bytesleft); - printf("file sector : %d\n", open_file->file_sector); - printf("file in sector: %d\n", open_file->file_in_sec); - printf("file offsector: %d\n", open_file->file_in_off); - } -#endif -} - -static void iso_load_config(com32sys_t *regs) -{ - char *config_name = "isolinux.cfg"; - com32sys_t out_regs; - - strcpy(ConfigName, config_name); - - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); -} - - -static int iso_fs_init(struct fs_info *fs) -{ - char *iso_dir; - char *boot_dir = "/boot/isolinux"; - char *isolinux_dir = "/isolinux"; - int len; - int bi_pvd = 16; - struct file file; - struct open_file_t *open_file; - struct disk *disk = fs->fs_dev->disk; - - block_shift = ISO_SECTOR_SHIFT - disk->sector_shift; - cdrom_read_sectors(disk, trackbuf, bi_pvd, 1); - CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); - -#ifdef DEBUG - printf("Root directory at LBA = 0x%x\n", RootDir.dir_lba); -#endif - - CurrentDir.dir_len = RootDir.dir_len = *(uint32_t*)(trackbuf + 156 + 10); - CurrentDir.dir_clust = RootDir.dir_clust = (RootDir.dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - - /* - * Look for an isolinux directory, and if found, - * make it the current directory instead of the - * root directory. - * - * Also copy the name of the directory to CurrrentDirName - */ - *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; - - iso_dir = boot_dir; - file.fs = fs; - iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ - if ( !file.file_len ) { - iso_dir = isolinux_dir; - iso_searchdir(isolinux_dir, &file); /* search for /isolinux */ - if ( !file.file_len ) { - printf("No isolinux directory found!\n"); - return 0; - } - } - - strcpy(CurrentDirName, iso_dir); - len = strlen(CurrentDirName); - CurrentDirName[len] = '/'; - CurrentDirName[len+1] = '\0'; - - open_file = (struct open_file_t *)file.open_file; - CurrentDir.dir_len = open_file->file_bytesleft; - CurrentDir.dir_clust = open_file->file_left; - CurrentDir.dir_lba = open_file->file_sector; - close_pvt(open_file); - -#ifdef DEBUG - printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); -#endif - - /* we do not use cache for now, so we can just return 0 */ - return 0; -} - - -const struct fs_ops iso_fs_ops = { - .fs_name = "iso", - .fs_flags = 0, - .fs_init = iso_fs_init, - .searchdir = iso_searchdir, - .getfssec = iso_getfssec, - .close_file = iso_close_file, - .mangle_name = iso_mangle_name, - .unmangle_name = iso_unmangle_name, - .load_config = iso_load_config -}; diff --git a/core/pxe.c b/core/pxe.c deleted file mode 100644 index 0b5102a2..00000000 --- a/core/pxe.c +++ /dev/null @@ -1,1559 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define FILENAME_MAX_LG2 7 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) - -#define GPXE 1 -#define USE_PXE_PROVIDED_STACK 0 - -static struct open_file_t Files[MAX_OPEN]; - -static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; -static char *err_pxefailed = "PXE API call failed, error "; -static char *err_udpinit = "Failed to initialize UDP stack\n"; - -static char *tftpprefix_msg = "TFTP prefix: "; -static char *get_packet_msg = "Getting cached packet "; - -static int has_gpxe; -static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; -int HaveUUID = 0; - -static const uint8_t TimeoutTable[] = { - 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, - 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 -}; - -struct tftp_options { - const char *str_ptr; /* string pointer */ - size_t offset; /* offset into socket structre */ -}; -static const struct tftp_options tftp_options[] = -{ - { "tsize", offsetof(struct open_file_t, tftp_filesize) }, - { "blksize", offsetof(struct open_file_t, tftp_blksize) }, -}; -static const int tftp_nopts = sizeof tftp_options / sizeof tftp_options[0]; - -/* - * Initialize the Files structure - */ -static void files_init(void) -{ - int i; - struct open_file_t *socket = Files; - uint16_t pktbuf = 0; - uint16_t nextport = 49152; - - for (i = 0; i < MAX_OPEN; i++) { - socket->tftp_pktbuf = pktbuf; - socket->tftp_nextport = nextport; - pktbuf += PKTBUF_SIZE; - nextport++; - socket++; - } -} - -/* - * Allocate a local UDP port structure. - * return the socket pointer if success, or null if failure - * - */ -static struct open_file_t *allocate_socket(void) -{ - int i; - struct open_file_t *socket = Files; - uint16_t nextport; - - for (i = 0; i < MAX_OPEN; i++) { - if (!socket->tftp_localport) - break; - socket++; - } - - if (i == MAX_OPEN) - return NULL; - - /* - * Allocate a socket number. Socket numbers are made guaranteed - * unique by including the socket slot number; add a counter value - * to keep the numbers from being likely to get immediately - * reused. The mask enforces wraparound to the range 49152-57343. - */ - nextport = socket->tftp_nextport; - socket->tftp_nextport = (nextport + (1 << MAX_OPEN_LG2)) & 0xdfff; - socket->tftp_localport = htons(nextport); /* Socket now in use */ - return socket; -} - -/* - * free socket, socket in SI; return SI = 0, ZF = 1 for convenience - */ -static void free_socket(struct open_file_t *file) -{ - /* tftp_nextport and tftp_pktbuf are not cleared */ - memset(file, 0, offsetof(struct open_file_t, tftp_nextport)); -} - -static void pxe_close_file(struct file *file) -{ - /* - * XXX: we really should see if the connection is open as send - * a courtesy ERROR packet so the server knows the connection is - * dead. - */ - free_socket(file->open_file); -} - -/** - * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal - * - * @param: dst, output buffer - * @param: src, input buffer - * @param: count, number of bytes - * - */ -static void lchexbytes(char *dst, const void *src, int count) -{ - uint8_t half; - uint8_t c; - const uint8_t *s = src; - - for(; count > 0; count--) { - c = *s++; - half = ((c >> 4) & 0x0f) + '0'; - *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; - - half = (c & 0x0f) + '0'; - *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half; - } -} - -/** - * just like the lchexbytes, except to upper-case - * - */ -static void uchexbytes(char *dst, const void *src, int count) -{ - uint8_t half; - uint8_t c; - const uint8_t *s = src; - - for(; count > 0; count--) { - c = *s++; - half = ((c >> 4) & 0x0f) + '0'; - *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; - - half = (c & 0x0f) + '0'; - *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half; - } -} - - - - -/* - * - * Tests an IP address in EAX for validity; return with 0 for bad, 1 for good. - * We used to refuse class E, but class E addresses are likely to become - * assignable unicast addresses in the near future. - * - */ -int ip_ok(uint32_t ip) -{ - if (ip == -1) /* Refuse the all-one address */ - goto bad; - if ((ip & 0xff) == 0) /* Refuse network zero */ - goto bad; - if ((ip & 0xff) == 0xff) /* Refuse loopback */ - goto bad; - if ((ip & 0xf0) == 0xe0) /* Refuse class D */ - goto bad; - - return 1; - - bad: - return 0; -} - - -/********************************************************************* -; -; gendotquad -; -; Take an IP address (in network byte order) in EAX and -; output a dotted quad string to ES:DI. -; DI points to terminal null at end of string on exit. -; - *********************************************************************/ -/** - * @param: dst, to store the converted ip string - * @param: ip, the ip address that needed convert. - * - * @return: the ip string length - */ -int gendotquad(char *dst, uint32_t ip) -{ - int part; - int i = 0, j; - char temp[4]; - char *p = dst; - - for (; i < 4; i++) { - j = 0; - part = ip & 0xff; - do { - temp[j++] = (part % 10) + '0'; - }while(part /= 10); - for (; j > 0; j--) - *p++ = temp[j-1]; - *p++ = '.'; - - ip >>= 8; - } - /* drop the last dot '.' and zero-terminate string*/ - *(--p) = 0; - - return p - dst; -} - -/* - * parse the ip_str and return the ip address with *res. - * return the the string address after the ip string - * - */ -static char *parse_dotquad(char *ip_str, uint32_t *res) -{ - char *p = ip_str; - int i = 0; - uint8_t part = 0; - uint32_t ip = 0; - - for (; i < 4; i++) { - while (is_digit(*p)) { - part = part * 10 + *p - '0'; - p++; - } - if (i != 3 && *p != '.') - return NULL; - - ip = (ip << 8) | part; - part = 0; - p++; - } - p --; - - *res = ip; - return p; -} - -/* - * the ASM pxenv function wrapper, return 1 if error, or 0 - * - */ -static int pxe_call(int opcode, void *data) -{ - extern void pxenv(void); - com32sys_t in_regs, out_regs; - -#if 0 - printf("pxe_call op %04x data %p\n", opcode, data); -#endif - - memset(&in_regs, 0, sizeof in_regs); - - in_regs.ebx.w[0] = opcode; - in_regs.es = SEG(data); - in_regs.edi.w[0] = OFFS(data); - call16(pxenv, &in_regs, &out_regs); - - return out_regs.eflags.l & EFLAGS_CF; /* CF SET for fail */ -} - -/** - * - * Send ACK packet. This is a common operation and so is worth canning. - * - * @param: file, TFTP block pointer - * @param: ack_num, Packet # to ack (network byte order) - * - */ -static void ack_packet(struct open_file_t *file, uint16_t ack_num) -{ - int err; - static __lowmem struct pxe_udp_write_pkt uw_pkt; - - /* Packet number to ack */ - ack_packet_buf[1] = ack_num; - uw_pkt.lport = file->tftp_localport; - uw_pkt.rport = file->tftp_remoteport; - uw_pkt.sip = file->tftp_remoteip; - uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; - uw_pkt.buffer[0] = OFFS_WRT(ack_packet_buf, 0); - uw_pkt.buffer[1] = 0; /* seems SEG and OFFS stuff doesn't work here */ - uw_pkt.buffersize = 4; - - err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); -#if 0 - printf("sent %s\n", err ? "FAILED" : "OK"); -#endif -} - - -/** - * Get a DHCP packet from the PXE stack into the trackbuf - * - * @param: type, packet type - * @return: buffer size - * - */ -static int pxe_get_cached_info(int type) -{ - int err; - static __lowmem struct pxe_bootp_query_pkt bq_pkt; - printf(" %02x", type); - - bq_pkt.status = 0; - bq_pkt.packettype = type; - bq_pkt.buffersize = 8192; - bq_pkt.buffer[0] = OFFS_WRT(trackbuf, 0); - bq_pkt.buffer[1] = 0; - - err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); - if (err) { - printf("%s %04x\n", err_pxefailed, err); - call16(kaboom, NULL, NULL); - } - - return bq_pkt.buffersize; -} - - - -#if GPXE - -/* - * Return 1 if and only if the buffer pointed to by - * url is a URL (contains ://) - * - */ -static int is_url(char *url) -{ - while (*url) { - if(! strncmp(url, "://", 3)) - return 1; - - url++; - } - return 0; -} - - -/* - * Return CF=0 if and only if the buffer pointed to by DS:SI is a URL - * (contains ://) *and* the gPXE extensions API is available. No - * registers modified. - */ -static int is_gpxe(char *url) -{ - int err; - static __lowmem struct gpxe_file_api_check ac; - char *gpxe_warning_msg = "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; - - if (! is_url(url)) - return 0; - - ac.size = 20; - ac.magic = 0x91d447b2; - /* If has_gpxe is greater than one, means the gpxe status is unknow */ - while (has_gpxe > 1) { - err = pxe_call(PXENV_FILE_API_CHECK, &ac); - if (err || ac.magic != 0xe9c17b20) - printf("%s\n", gpxe_warning_msg); - else - has_gpxe = (~ac.provider & 0xffff) & 0x4b ? 0 : 1; - - if (!has_gpxe) - printf("%s\n", gpxe_warning_msg); - } - - if (has_gpxe == 1) - return 1; - else - return 0; -} - -/** - * Get a fresh packet from a gPXE socket - * @param: file -> socket structure - * - */ -static void get_packet_gpxe(struct open_file_t *file) -{ - static __lowmem struct gpxe_file_read fr; - int err; - - while (1) { - fr.filehandle = file->tftp_remoteport; - fr.buffer[0] = file->tftp_pktbuf; - fr.buffer[1] = PKTBUF_SEG; - fr.buffersize = PKTBUF_SIZE; - err = pxe_call(PXENV_FILE_READ, &fr); - if (!err) /* successed */ - break; - - if (fr.status == PXENV_STATUS_TFTP_OPEN) - continue; - call16(kaboom, NULL, NULL); - } - - file->tftp_bytesleft = fr.buffersize; - file->tftp_filepos += fr.buffersize; - - if (file->tftp_bytesleft == 0) - file->tftp_filesize = file->tftp_filepos; - - /* if we're done here, close the file */ - if (file->tftp_filesize > file->tftp_filepos) - return; - - /* Got EOF, close it */ - file->tftp_goteof = 1; - pxe_call(PXENV_FILE_CLOSE, &fr); -} -#endif /* GPXE */ - - -/* - * mangle a filename pointed to by _src_ into a buffer pointed - * to by _dst_; ends on encountering any whitespace. - * - * The first four bytes of the manged name is the IP address of - * the download host, 0 for no host, or -1 for a gPXE URL. - * - */ -static void pxe_mangle_name(char *dst, char *src) -{ - char *p = src; - uint32_t ip = 0; - int i = 0; - -#if GPXE - if (is_url(src)) - goto prefix_done; -#endif - - ip = ServerIP; - if (*p == 0) - goto noip; - if (! strncmp(p, "::", 2)) - goto gotprefix; - else { - while (*p && strncmp(p, "::", 2)) - p ++; - if (! *p) - goto noip; - /* - * we have a :: prefix of ip sort, it could be either a DNS - * name or dot-quad IP address. Try the dot-quad first. - */ - p = src; - if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) - goto gotprefix; - else { -#if 0 - extern void dns_resolv(void); - call16(dns_resolv, regs, regs); - p = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - ip = regs->eax.l; - if (! strncmp(p, "::", 2)) - if (ip) - goto gotprefix; -#endif - } - } - noip: - p = src; - ip = 0; - goto prefix_done; - - gotprefix: - p += 2; /* skip double colon */ - - prefix_done: - *(uint32_t *)dst = ip; - dst += 4; - i = FILENAME_MAX - 5; - - do { - if (*p <= ' ') - break; - *dst++ = *p++; - }while (i--); - - i ++; - while (i) { - *dst++ = 0; - i --; - } - -#if 0 - printf("the name before mangling: "); - dump16(src); - printf("the name after mangling: "); - dump16((char *)MK_PTR(regs->ds, regs->edi.w[0])); -#endif -} - - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int pxe_unmangle_name(char *dst, char *src) -{ - uint32_t ip = *(uint32_t *)src; - int ip_len = 0; - - if (ip != 0 && ip != -1) { - ip_len = gendotquad(dst, *(uint32_t *)src); - dst += ip_len; - } - src += 4;; - strcpy(dst, src); - - return strlen(src) + ip_len; -} - -/* - * - ; - ; Get a fresh packet if the buffer is drained, and we haven't hit - ; EOF yet. The buffer should be filled immediately after draining! - ; - ; expects fs -> pktbuf_seg and ds:si -> socket structure - ; -*/ -static void fill_buffer(struct open_file_t *file) -{ - int err; - int last_pkt; - const uint8_t *timeout_ptr = TimeoutTable; - uint8_t timeout; - uint16_t buffersize; - uint16_t old_time; - void *data = NULL; - static __lowmem struct pxe_udp_read_pkt pkt; - - if (file->tftp_bytesleft || file->tftp_goteof) - return; - -#if GPXE - if (file->tftp_localport == 0xffff) { - get_packet_gpxe(file); - return; - } -#endif - - - /* - * Start by ACKing the previous packet; this should cause - * the next packet to be sent. - */ - ack_again: - ack_packet(file, file->tftp_lastpkt); - - timeout_ptr = TimeoutTable; - timeout = *timeout_ptr++; - old_time = BIOS_timer; - while (timeout) { - pkt.buffer[0] = file->tftp_pktbuf; - pkt.buffer[1] = PKTBUF_SEG; - pkt.buffersize = PKTBUF_SIZE; - pkt.sip = file->tftp_remoteip; - pkt.dip = MyIP; - pkt.rport = file->tftp_remoteport; - pkt.lport = file->tftp_localport; - err = pxe_call(PXENV_UDP_READ, &pkt); - if (err) { - if (BIOS_timer == old_time) - continue; - - BIOS_timer = old_time; - timeout--; /* decrease one timer tick */ - if (!timeout) { - timeout = *timeout_ptr++; - if (!timeout) - break; - } - continue; - } - - if (pkt.buffersize < 4) /* Bad size for a DATA packet */ - continue; - - data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf); - if (*(uint16_t *)data != TFTP_DATA) /* Not a data packet */ - continue; - - /* If goes here, recevie OK, break */ - break; - } - - /* time runs out */ - if (timeout == 0) - call16(kaboom, NULL, NULL); - - last_pkt = file->tftp_lastpkt; - last_pkt = ntohs(last_pkt); /* Host byte order */ - last_pkt++; - last_pkt = htons(last_pkt); /* Network byte order */ - if (*(uint16_t *)(data + 2) != last_pkt) { - /* - * Wrong packet, ACK the packet and try again. - * This is presumably because the ACK got lost, - * so the server just resent the previous packet. - */ -#if 0 - printf("Wrong packet, wanted %04x, got %04x\n", htons(last_pkt), htons(*(uint16_t *)(data+2))); -#endif - goto ack_again; - } - - /* It's the packet we want. We're also EOF if the size < blocksize */ - file->tftp_lastpkt = last_pkt; /* Update last packet number */ - buffersize = pkt.buffersize - 4; /* Skip TFTP header */ - file->tftp_dataptr = file->tftp_pktbuf + 4; - file->tftp_filepos += buffersize; - file->tftp_bytesleft = buffersize; - if (buffersize < file->tftp_blksize) { - /* it's the last block, ACK packet immediately */ - ack_packet(file, *(uint16_t *)(data + 2)); - - /* Make sure we know we are at end of file */ - file->tftp_filesize = file->tftp_filepos; - file->tftp_goteof = 1; - } -} - - -/** - * getfssec: Get multiple clusters from a file, given the starting cluster. - * In this case, get multiple blocks from a specific TCP connection. - * - * @param: fs, the fs_info structure address, in pxe, we don't use this. - * @param: buf, buffer to store the read data - * @param: openfile, TFTP socket pointer - * @param: blocks, 512-byte block count; 0FFFFh = until end of file - * - * @return: the bytes read - * - */ -static uint32_t pxe_getfssec(struct file *gfile, char *buf, - int blocks, bool *have_more) -{ - struct open_file_t *file = gfile->open_file; - int count = blocks; - int chunk; - int bytes_read = 0; - - count <<= TFTP_BLOCKSIZE_LG2; - while (count) { - fill_buffer(file); /* If we have no 'fresh' buffer, get it */ - if (! file->tftp_bytesleft) - break; - - chunk = count; - if (chunk > file->tftp_bytesleft) - chunk = file->tftp_bytesleft; - file->tftp_bytesleft -= chunk; - memcpy(buf, MK_PTR(PKTBUF_SEG, file->tftp_dataptr), chunk); - file->tftp_dataptr += chunk; - buf += chunk; - bytes_read += chunk; - count -= chunk; - } - - - if (file->tftp_bytesleft || (file->tftp_filepos < file->tftp_filesize)) { - fill_buffer(file); - *have_more = 1; - } else if (file->tftp_goteof) { - /* - * The socket is closed and the buffer drained; the caller will - * call close_file and therefore free the socket. - */ - *have_more = 0; - } - - return bytes_read; - } - - - -/* - * Fill the packet tail with the tftp informations then retures the lenght - */ -static int fill_tail(char *dst) -{ - static const char tail[] = "octet\0""tsize\0""0\0""blksize\0""1408"; - - memcpy(dst, tail, sizeof tail); - return sizeof tail; -} - - -/* - * - * - * searchdir: - * - * Open a TFTP connection to the server - * - * On entry: - * DS:DI = mangled filename - * If successful: - * ZF clear - * SI = socket pointer - * EAX = file length in bytes, or -1 if unknown - * If unsuccessful - * ZF set - * - */ -static void pxe_searchdir(char *filename, struct file *file) -{ - extern char tftp_proto_err[]; - char *buf = packet_buf; - char *p = filename; - char *options; - char *data; - struct open_file_t *open_file; - static __lowmem struct pxe_udp_write_pkt uw_pkt; - static __lowmem struct pxe_udp_read_pkt ur_pkt; - static __lowmem struct gpxe_file_open fo; - static __lowmem struct gpxe_get_file_size gs; - const struct tftp_options *tftp_opt; - int i = 0; - int err; - int buffersize; - const uint8_t *timeout_ptr; - uint8_t timeout; - uint16_t oldtime; - uint16_t tid; - uint16_t opcode; - uint16_t blk_num; - uint32_t ip; - uint32_t opdata, *opdata_ptr; - - open_file = allocate_socket(); - if (!open_file) { - file->file_len = 0; - file->open_file = NULL; - return; - } - - timeout_ptr = TimeoutTable; /* Reset timeout */ - - sendreq: - uw_pkt.buffer[0] = OFFS_WRT(buf, 0); - uw_pkt.buffer[1] = 0; - *(uint16_t *)buf = TFTP_RRQ; /* TFTP opcode */ - buf += 2; - - ip = *(uint32_t *)p; /* ip <- server override (if any) */ - p += 4; - if (ip == 0) { - /* Have prefix */ - strcpy(buf, PathPrefix); - buf += strlen(PathPrefix); - ip = ServerIP; /* Get the default server */ - } - - strcpy(buf, p); /* Copy the filename */ - buf += strlen(p) + 1; /* advance the pointer, null char included */ - -#if GPXE - if (is_gpxe(packet_buf + 2)) { - fo.status = PXENV_STATUS_BAD_FUNC; - fo.filename[0] = OFFS_WRT(packet_buf + 2, 0); - fo.filename[1] = 0; - err = pxe_call(PXENV_FILE_OPEN, &fo); - if (err) - goto done; - - open_file->tftp_localport = -1; - open_file->tftp_remoteport = fo.filehandle; - gs.filehandle = fo.filehandle; - -#if 0 - err = pxe_call(PXENV_GET_FILE_SIZE, &gs); - if (!err) - open_file->tftp_filesize = gs.filesize; - else -#endif - open_file->tftp_filesize = -1; - goto done; - } -#endif /* GPXE */ - - open_file->tftp_remoteip = ip; - tid = open_file->tftp_localport; /* TID(local port No) */ - uw_pkt.sip = ip; - uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; - uw_pkt.lport = tid; - uw_pkt.rport = ServerPort; - buf += fill_tail(buf); - uw_pkt.buffersize = buf - packet_buf; - err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); - if (err || uw_pkt.status != 0) - goto failure; /* - * In fact, the 'failure' target will not do - * a failure thing; it will move on to the - * next timeout, then tries again until - * _real_ time out - */ - - /* - * Danger, Will Robinson! We need to support tiemout - * and retry lest we just lost a packet ... - */ - - /* Packet transmitted OK, now we need to receive */ - timeout = *timeout_ptr++; - oldtime = BIOS_timer; - while (timeout) { - buf = packet_buf; - ur_pkt.buffer[0] = OFFS_WRT(buf, 0); - ur_pkt.buffer[1] = 0; - ur_pkt.buffersize = 2048; - ur_pkt.dip = MyIP; - ur_pkt.lport = tid; - err = pxe_call(PXENV_UDP_READ, &ur_pkt); - if (err) { - if (oldtime == BIOS_timer) - continue; - timeout --; /* Decrease one timer tick */ - if (!timeout) - goto failure; - } - - /* Make sure the packet actually came from the server */ - if (ur_pkt.sip == open_file->tftp_remoteip) - break; - } - - /* Got packet; reset timeout */ - timeout_ptr = TimeoutTable; - open_file->tftp_remoteport = ur_pkt.rport; - - /* filesize <- -1 == unknown */ - open_file->tftp_filesize = -1; - /* Default blksize unless blksize option negotiated */ - open_file->tftp_blksize = TFTP_BLOCKSIZE; - buffersize = ur_pkt.buffersize - 2; /* bytes after opcode */ - if (buffersize < 0) - goto failure; /* Garbled reply */ - - /* - * Get the opcode type, and parse it - */ - opcode = *(uint16_t *)packet_buf; - switch (opcode) { - case TFTP_ERROR: - open_file->tftp_filesize = 0; - break; /* ERROR reply; don't try again */ - - case TFTP_DATA: - /* - * If the server doesn't support any options, we'll get a - * DATA reply instead of OACK. Stash the data in the file - * buffer and go with the default value for all options... - * - * We got a DATA packet, meaning no options are - * suported. Save the data away and consider the - * length undefined, *unless* this is the only - * data packet... - */ - buffersize -= 2; - if (buffersize < 0) - goto failure; - data = packet_buf + 2; - blk_num = *(uint16_t *)data; - data += 2; - if (blk_num != htons(1)) - goto failure; - open_file->tftp_lastpkt = blk_num; - if (buffersize > TFTP_BLOCKSIZE) - goto err_reply; /* Corrupt */ - else if (buffersize < TFTP_BLOCKSIZE) { - /* - * This is the final EOF packet, already... - * We know the filesize, but we also want to - * ack the packet and set the EOF flag. - */ - open_file->tftp_filesize = buffersize; - open_file->tftp_goteof = 1; - ack_packet(open_file, blk_num); - } - - open_file->tftp_bytesleft = buffersize; - open_file->tftp_dataptr = open_file->tftp_pktbuf; - memcpy(MK_PTR(PKTBUF_SEG, open_file->tftp_pktbuf), data, buffersize); - break; - - case TFTP_OACK: - /* - * Now we need to parse the OACK packet to get the transfer - * and packet sizes. - */ - - options = packet_buf + 2; - p = options; - - while (buffersize) { - char *opt = p; - - /* - * If we find an option which starts with a NUL byte, - * (a null option), we're either seeing garbage that some - * TFTP servers add to the end of the packet, or we have - * no clue how to parse the rest of the packet (what is - * an option name and what is a value?) In either case, - * discard the rest. - */ - if (!*opt) - goto done; - - while (buffersize) { - if (!*p) - break; /* Found a final null */ - *p++ |= 0x20; - buffersize--; - } - if (!buffersize) - break; /* Unterminated option */ - - /* Consume the terminal null */ - p++; - buffersize--; - - if (!buffersize) - break; /* No option data */ - - /* - * Parse option pointed to by options; guaranteed to be - * null-terminated - */ - tftp_opt = tftp_options; - for (i = 0; i < tftp_nopts; i++) { - if (!strcmp(opt, tftp_opt->str_ptr)) - break; - tftp_opt++; - } - if (i == tftp_nopts) - goto err_reply; /* Non-negotitated option returned, - no idea what it means ...*/ - - /* get the address of the filed that we want to write on */ - opdata_ptr = (uint32_t *)((char *)open_file + tftp_opt->offset); - opdata = 0; - - /* do convert a number-string to decimal number, just like atoi */ - while (buffersize--) { - uint8_t d = *p++; - if (d == '\0') - break; /* found a final null */ - d -= '0'; - if (d > 9) - goto err_reply; /* Not a decimal digit */ - opdata = opdata*10 + d; - } - *opdata_ptr = opdata; - } - break; - - default: - printf("TFTP unknown opcode %d\n", ntohs(opcode)); - goto err_reply; - } - -done: - if (!open_file->tftp_filesize) { - free_socket(open_file); - file->file_len = 0; - file->open_file = NULL; - return; - } - file->open_file = (void *)open_file; - file->file_len = open_file->tftp_filesize; - return; - -err_reply: - uw_pkt.rport = open_file->tftp_remoteport; - uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); - uw_pkt.buffer[1] = 0; - uw_pkt.buffersize = 24; - pxe_call(PXENV_UDP_WRITE, &uw_pkt); - printf("TFTP server sent an incomprehesible reply\n"); - call16(kaboom, NULL, NULL); - -failure: - timeout_ptr++; - if (*timeout_ptr) - goto sendreq; /* Try again */ -} - - -/* - * Store standard filename prefix - */ -static void get_prefix(void) -{ - int len; - char *p; - char c; - - if (DHCPMagic & 0x04) /* Did we get a path prefix option */ - goto got_prefix; - - strcpy(PathPrefix, BootFile); - len = strlen(PathPrefix); - p = &PathPrefix[len - 1]; - - while (len--) { - c = *p--; - c |= 0x20; - - c = (c >= '0' && c <= '9') || - (c >= 'a' && c <= 'z') || - (c == '.' || c == '-'); - if (!c) - break; - }; - - if (len < 0) - p --; - - *(p + 2) = 0; /* Zero-terminate after delimiter */ - - got_prefix: - printf("%s%s\n", tftpprefix_msg, PathPrefix); - strcpy(CurrentDirName, PathPrefix); -} - - /** - * try to load a config file, if found, return 1, or return 0 - * - */ -static int try_load(com32sys_t *regs) -{ - extern char KernelName[]; - char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]); - - printf("Trying to load: %-50s ", config_name); - pxe_mangle_name(KernelName, config_name); - - regs->edi.w[0] = OFFS_WRT(KernelName, 0); - call16(core_open, regs, regs); - if (regs->eflags.l & EFLAGS_ZF) { - printf(" [FAILED]\n"); - return 0; - } else { - printf(" [ OK ]\n"); - return 1; - } -} - - - /* - * load configuration file - * - */ -static void pxe_load_config(com32sys_t *regs) -{ - extern void no_config(void); - char *cfgprefix = "pxelinux.cfg/"; - char *default_str = "default"; - char *config_file; /* Pointer to the variable suffix */ - char *p; - - uint8_t *uuid_ptr; - - int tries = 8; - char *last; - - get_prefix(); - if (DHCPMagic & 0x02) { - /* We got a DHCP option, try it first */ - if (try_load(regs)) - return; - } - - memcpy(ConfigName, cfgprefix, strlen(cfgprefix)); - config_file = ConfigName + strlen(cfgprefix); - /* - * Have to guess config file name ... - */ - - /* Try loading by UUID */ - if (HaveUUID) { - uuid_ptr = uuid_dashes; - p = config_file; - while (*uuid_ptr) { - int len = *uuid_ptr; - char *src = UUID; - - lchexbytes(p, src, len); - p += len * 2; - src += len; - uuid_ptr++; - *p++ = '-'; - } - /* Remove last dash and zero-terminate */ - *--p = '\0'; - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; - } - - /* Try loading by MAC address */ - strcpy(config_file, MACStr); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; - -#if 0 - printf("MY IP: %p(%X)\n", MyIP, *(uint32_t *)MyIP); - #endif - - /* Nope, try hexadecimal IP prefixes... */ - uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */ - last = &config_file[8]; - while (tries) { - *last = '\0'; /* Zero-terminate string */ - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; - last--; /* Drop one character */ - tries--; - }; - - /* Final attempt: "default" string */ - strcpy(config_file, default_str); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; - - printf("Unable to locate configuration file\n"); - call16(kaboom, NULL, NULL); -} - - - -/* - * Generate the botif string, and the hardware-based config string - */ -static void make_bootif_string(void) -{ - char *bootif_str = "BOOTIF="; - uint8_t *src = &MACType; /* MACType just followed by MAC */ - char *dst; - int i = MACLen + 1; /* MACType included */ - - strcpy(BOOTIFStr, bootif_str); - dst = strchr(BOOTIFStr, '\0'); - for (; i > 0; i--) { - lchexbytes(dst, src, 1); - dst += 2; - src += 1; - *dst++ = '-'; - } - *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */ - -#if 0 - printf("%s\n", BOOTIFStr); -#endif -} -/* - ; - ; genipopt - ; - ; Generate an ip=::: - ; option into IPOption based on a DHCP packet in trackbuf. - ; Assumes CS == DS == ES. - ; -*/ -static void genipopt(void) -{ - char *p = IPOption; - int ip_len; - - strcpy(p, "ip="); - p += 3; - - ip_len = gendotquad(p, MyIP); - p += ip_len; - *p++ = ':'; - - ip_len = gendotquad(p, ServerIP); - p += ip_len; - *p++ = ':'; - - ip_len = gendotquad(p, Gateway); - p += ip_len; - *p++ = ':'; - - ip_len = gendotquad(p, Netmask); -} - - -/* Generate ip= option and print the ip adress */ -static void ip_init(void) -{ - int ip = MyIP; - char *myipaddr_msg = "My IP address seems to be "; - - genipopt(); - - gendotquad(DotQuadBuf, ip); - - ip = ntohl(ip); - printf("%s %08X %s\n", myipaddr_msg, ip, DotQuadBuf); - - printf("%s\n", IPOption); -} - -/* - * Validity check on possible !PXE structure in buf - * return 1 for success, 0 for failure. - * - */ -static int is_pxe(const void *buf) -{ - const struct pxe_t *pxe = buf; - const uint8_t *p = buf; - int i = pxe->structlength; - uint8_t sum = 0; - - if (i < sizeof(struct pxe_t) || - memcmp(pxe->signature, "!PXE", 4)) - return 0; - - while (i--) - sum += *p++; - - return sum == 0; -} - -/** - * Just like is_pxe, it checks PXENV+ structure - * - */ -static int is_pxenv(const void *buf) -{ - const struct pxenv_t *pxenv = buf; - const uint8_t *p = buf; - int i = pxenv->length; - uint8_t sum = 0; - - /* The pxeptr field isn't present in old versions */ - if (i < offsetof(struct pxenv_t, pxeptr) || - memcmp(pxenv->signature, "PXENV+", 6)) - return 0; - - while (i--) - sum += *p++; - - return sum == 0; -} - - - -/********************************************************************* -; -; memory_scan_for_pxe_struct: -; memory_scan_for_pxenv_struct: -; -; If none of the standard methods find the !PXE/PXENV+ structure, -; look for it by scanning memory. -; -; On exit, if found: -; ZF = 1, ES:BX -> !PXE structure -; Otherwise: -; ZF = 0 -; -; Assumes DS == CS -; Clobbers AX, BX, CX, DX, SI, ES -; - ********************************************************************/ - -static const void *memory_scan(uintptr_t start, int (*func)(const void *)) -{ - const char *ptr; - - /* Scan each 16 bytes of conventional memory before the VGA region */ - for (ptr = (const char *)start; ptr < (const char *)0xA0000; ptr += 16) { - if (func(ptr)) - return ptr; /* found it! */ - ptr += 16; - } - return NULL; -} - -static const struct pxe_t *memory_scan_for_pxe_struct(void) -{ - extern uint16_t BIOS_fbm; /* Starting segment */ - - return memory_scan(BIOS_fbm << 10, is_pxe); -} - -static const struct pxenv_t *memory_scan_for_pxenv_struct(void) -{ - return memory_scan(0x10000, is_pxenv); -} - -/* - * Find the !PXE structure; we search for the following, in order: - * - * a. !PXE structure as SS:[SP + 4] - * b. PXENV+ structure at [ES:BX] - * c. INT 1Ah AX=0x5650 -> PXENV+ - * d. Search memory for !PXE - * e. Search memory for PXENV+ - * - * If we find a PXENV+ structure, we try to find a !PXE structure from - * if if the API version is 2.1 or later - * - */ -static void pxe_init(void) -{ - extern void pxe_int1a(void); - char plan = 'A'; - uint16_t seg, off; - uint16_t code_seg, code_len; - uint16_t data_seg, data_len; - char *base = GET_PTR(InitStack); - com32sys_t regs; - const char *type; - const struct pxenv_t *pxenv; - const struct pxe_t *pxe; - - /* Assume API version 2.1 */ - APIVer = 0x201; - - /* Plan A: !PXE structure as SS:[SP + 4] */ - off = *(uint16_t *)(base + 48); - seg = *(uint16_t *)(base + 50); - pxe = MK_PTR(seg, off); - if (is_pxe(pxe)) - goto have_pxe; - - /* Plan B: PXENV+ structure at [ES:BX] */ - plan++; - off = *(uint16_t *)(base + 24); /* Original BX */ - seg = *(uint16_t *)(base + 4); /* Original ES */ - pxenv = MK_PTR(seg, off); - if (is_pxenv(pxenv)) - goto have_pxenv; - - /* - * Plan C: PXENV+ structure via INT 1Ah AX=5650h - */ - plan++; - memset(®s, 0, sizeof regs); - regs.eax.w[0] = 0x5650; - call16(pxe_int1a, ®s, ®s); - if (!(regs.eflags.l & EFLAGS_CF) && (regs.eax.w[0] == 0x564e)) { - pxenv = MK_PTR(regs.es, regs.ebx.w[0]); - if (is_pxenv(pxenv)) - goto have_pxenv; - } - - /* Plan D: !PXE memory scan */ - plan++; - if ((pxe = memory_scan_for_pxe_struct())) - goto have_pxe; - - /* Plan E: PXENV+ memory scan */ - plan++; - if ((pxenv = memory_scan_for_pxenv_struct())) - goto have_pxenv; - - /* Found nothing at all !! */ - printf("%s\n", err_nopxe); - call16(kaboom, NULL, NULL); - - have_pxenv: - APIVer = pxenv->version; - printf("Found PXENV+ structure\nPXE API version is %04x\n", APIVer); - - /* if the API version number is 0x0201 or higher, use the !PXE structure */ - if (APIVer >= 0x201) { - if (pxenv->length >= sizeof(struct pxenv_t)) { - pxe = GET_PTR(pxenv->pxeptr); - if (is_pxe(pxe)) - goto have_pxe; - /* - * Nope, !PXE structure missing despite API 2.1+, or at least - * the pointer is missing. Do a last-ditch attempt to find it - */ - if ((pxe = memory_scan_for_pxe_struct())) - goto have_pxe; - } - } - - /* Otherwise, no dice, use PXENV+ structure */ - data_len = pxenv->undidatasize; - data_seg = pxenv->undidataseg; - code_len = pxenv->undicodesize; - code_seg = pxenv->undicodeseg; - PXEEntry = pxenv->rmentry; - type = "PXENV+"; - goto have_entrypoint; - - have_pxe: - data_len = pxe->seg[PXE_Seg_UNDIData].size; - data_seg = pxe->seg[PXE_Seg_UNDIData].sel; - code_len = pxe->seg[PXE_Seg_UNDICode].size; - code_seg = pxe->seg[PXE_Seg_UNDICode].sel; - PXEEntry = pxe->entrypointsp; - type = "!PXE"; - - have_entrypoint: - printf("%s entry point found (we hope) at %04X:%04X via plan %c\n", - type, PXEEntry.seg, PXEEntry.offs, plan); - printf("UNDI code segment at %04X len %04X\n", code_seg, code_len); - printf("UNDI data segment at %04X len %04X\n", data_seg, data_len); - - code_seg = code_seg + ((code_len + 15) >> 4); - data_seg = data_seg + ((data_len + 15) >> 4); - - RealBaseMem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */ -} - -/* - * Initialize UDP stack - * - */ -static void udp_init(void) -{ - int err; - static __lowmem struct pxe_udp_open_pkt uo_pkt; - uo_pkt.sip = MyIP; - err = pxe_call(PXENV_UDP_OPEN, &uo_pkt); - if (err || uo_pkt.status) { - printf("%s", err_udpinit); - printf("%d\n", uo_pkt.status); - call16(kaboom, NULL, NULL); - } -} - - -/* - * Network-specific initialization - */ -static void network_init(void) -{ - struct bootp_t *bp = (struct bootp_t *)trackbuf; - int pkt_len; - - *LocalDomain = 0; /* No LocalDomain received */ - - /* - * Get the DHCP client identifiers (query info 1) - */ - printf("%s", get_packet_msg); - pkt_len = pxe_get_cached_info(1); - parse_dhcp(pkt_len); - /* - ; We don't use flags from the request packet, so - ; this is a good time to initialize DHCPMagic... - ; Initialize it to 1 meaning we will accept options found; - ; in earlier versions of PXELINUX bit 0 was used to indicate - ; we have found option 208 with the appropriate magic number; - ; we no longer require that, but MAY want to re-introduce - ; it in the future for vendor encapsulated options. - */ - *(char *)&DHCPMagic = 1; - - - /* - * Get the BOOTP/DHCP packet that brought us file (and an IP - * address). This lives in the DHCPACK packet (query info 2) - */ - pkt_len = pxe_get_cached_info(2); - parse_dhcp(pkt_len); - /* - * Save away MAC address (assume this is in query info 2. If this - * turns out to be problematic it might be better getting it from - * the query info 1 packet - */ - MACLen = bp->hardlen > 16 ? 0 : bp->hardlen; - MACType = bp->hardware; - memcpy(MAC, bp->macaddr, MACLen); - - - /* - * Get the boot file and other info. This lives in the CACHED_REPLY - * packet (query info 3) - */ - pkt_len = pxe_get_cached_info(3); - parse_dhcp(pkt_len); - - printf("\n"); - - - - make_bootif_string(); - ip_init(); - - /* - * Check to see if we got any PXELINUX-specific DHCP options; in particular, - * if we didn't get the magic enable, do not recognize any other options. - */ - if ((DHCPMagic & 1) == 0) - DHCPMagic = 0; - - udp_init(); -} - -/* - * Initialize pxe fs - * - */ -static int pxe_fs_init(struct fs_info *fs) -{ - (void)fs; /* drop the compile warning message */ - - /* Initialize the Files structure */ - files_init(); - - /* do the pxe initialize */ - pxe_init(); - - /* Network-specific initialization */ - network_init(); - - return 0; -} - -const struct fs_ops pxe_fs_ops = { - .fs_name = "pxe", - .fs_flags = FS_NODEV, - .fs_init = pxe_fs_init, - .searchdir = pxe_searchdir, - .getfssec = pxe_getfssec, - .close_file = pxe_close_file, - .mangle_name = pxe_mangle_name, - .unmangle_name = pxe_unmangle_name, - .load_config = pxe_load_config -}; -- cgit v1.2.1 From 0456f52098e30355a09ad2e05c3a26fc2dbc1752 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 20:56:46 -0700 Subject: core: make FILENAME_MAX common; librarize mangle/unmangle FILENAME_MAX was 2^8 in all variants by now; make it a common define. Libraries mangle/unmangle; we have generic_mangle_name for Unix-like filesystems, and unmangle now defaults to simple strcpy. Signed-off-by: H. Peter Anvin --- core/config.inc | 6 +++++ core/diskfs.inc | 1 - core/extlinux.asm | 1 - core/fs.c | 18 ++++++++------ core/fs/ext2/ext2.c | 60 ++--------------------------------------------- core/fs/fat/fat.c | 49 +++++++++++++++----------------------- core/fs/iso9660/iso9660.c | 29 +++++------------------ core/fs/lib/mangle.c | 47 +++++++++++++++++++++++++++++++++++++ core/fs/pxe/pxe.c | 36 +++++++++++----------------- core/include/core.h | 1 - core/include/fs.h | 22 ++++++++++++++--- core/isolinux.asm | 2 -- core/ldlinux.asm | 1 - core/pxelinux.asm | 2 -- 14 files changed, 124 insertions(+), 151 deletions(-) create mode 100644 core/fs/lib/mangle.c diff --git a/core/config.inc b/core/config.inc index 5a3d1c5a..269e13ec 100644 --- a/core/config.inc +++ b/core/config.inc @@ -31,6 +31,12 @@ MAX_FKEYS equ 12 ; Number of F-key help files ; %assign HAS_LOCALBOOT 1 +; +; log2(Max filename size Including final null) +; +FILENAME_MAX_LG2 equ 8 +FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size + ; ; Version number definitinons ; diff --git a/core/diskfs.inc b/core/diskfs.inc index 474657a6..b8d03762 100644 --- a/core/diskfs.inc +++ b/core/diskfs.inc @@ -21,7 +21,6 @@ ; ; Some semi-configurable constants... change on your own risk. ; -FILENAME_MAX equ (1 << FILENAME_MAX_LG2) ; Max mangled filename size NULLFILE equ 0 ; Null character == empty filename NULLOFFSET equ 0 ; Position in which to look retry_count equ 16 ; How patient are we with the disk? diff --git a/core/extlinux.asm b/core/extlinux.asm index fd9cfdd2..1f5423b2 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -23,7 +23,6 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ extlinux_id -FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) extern ext2_fs_ops ROOT_FS_OPS equ ext2_fs_ops diff --git a/core/fs.c b/core/fs.c index c4bf0387..ad6659b2 100644 --- a/core/fs.c +++ b/core/fs.c @@ -61,8 +61,8 @@ void load_config(com32sys_t *regs) void mangle_name(com32sys_t *regs) { - char *src = MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = MK_PTR(regs->es, regs->edi.w[0]); + const char *src = MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = MK_PTR(regs->es, regs->edi.w[0]); this_fs->fs_ops->mangle_name(dst, src); } @@ -70,13 +70,17 @@ void mangle_name(com32sys_t *regs) void unmangle_name(com32sys_t *regs) { - char *src = MK_PTR(regs->ds, regs->esi.w[0]); - char *dst = MK_PTR(regs->es, regs->edi.w[0]); - int len; + const char *src = MK_PTR(regs->ds, regs->esi.w[0]); + char *dst = MK_PTR(regs->es, regs->edi.w[0]); + + if (this_fs->fs_ops->unmangle_name) + this_fs->fs_ops->unmangle_name(dst, src); + else + strcpy(dst, src); - len = this_fs->fs_ops->unmangle_name(dst, src); /* Update the di register to point to the last null char */ - regs->edi.w[0] += len; + dst = strchr(dst, '\0'); + regs->edi.w[0] = OFFS_WRT(dst, regs->es); } diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c index 91eff8ff..546a127a 100644 --- a/core/fs/ext2/ext2.c +++ b/core/fs/ext2/ext2.c @@ -6,8 +6,6 @@ #include "ext2_fs.h" #include "fs.h" -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define MAX_SYMLINKS 64 #define SYMLINK_SECTORS 2 @@ -98,60 +96,6 @@ static void ext2_close_file(struct file *file) close_pvt(file->open_file); } -/** - * mangle_name: - * - * Mangle a filename pointed to by DS:SI(of regs) into a - * buffer pointed to by ES:DI(of regs); ends on encountering - * any whitespace. - * - */ -static void ext2_mangle_name(char *dst, char *src) -{ - char *p = dst; - int i = FILENAME_MAX -1; - - while(*src > ' ') { - if (*src == '/') { - if (*(src+1) == '/') { - src ++; - i --; - continue; - } - } - i --; - *dst++ = *src++; - } - - while (1) { - if (dst == p) - break; - if (*(dst-1) != '/') - break; - - dst --; - i ++; - } - - i ++; - for (; i > 0; i --) - *dst++ = '\0'; -} - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int ext2_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - - /** * get_group_desc: * @@ -812,7 +756,7 @@ const struct fs_ops ext2_fs_ops = { .searchdir = ext2_searchdir, .getfssec = ext2_getfssec, .close_file = ext2_close_file, - .mangle_name = ext2_mangle_name, - .unmangle_name = ext2_unmangle_name, + .mangle_name = generic_mangle_name, + .unmangle_name = NULL, .load_config = ext2_load_config }; diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 83dc9081..1b1c532e 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -6,9 +6,6 @@ #include "fat_fs.h" #include "fs.h" - -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define ROOT_DIR_WORD 0x002f /* file structure. This holds the information for each currently open file */ @@ -352,55 +349,47 @@ static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, * ends on encountering any whitespace. * */ -static void vfat_mangle_name(char *dst, char *src) +static void vfat_mangle_name(char *dst, const char *src) { char *p = dst; + char c; int i = FILENAME_MAX -1; - while(*src > ' ') { - if ( *src == '\\' ) - *src = '/'; + /* + * Copy the filename, converting backslash to slash and + * collapsing duplicate separators. + */ + while (not_whitespace(c = *src)) { + if (c == '\\') + c = '/'; - if (*src == '/') { - if (*(src+1) == '/') { - src ++; - i --; + if (c == '/') { + if (src[1] == '/' || src[1] == '\\') { + src++; + i--; continue; } } - i --; + i--; *dst++ = *src++; } + /* Strip terminal slashes or whitespace */ while (1) { if (dst == p) break; if ((*(dst-1) != '/') && (*(dst-1) != '.')) break; - dst --; - i ++; + dst--; + i++; } - i ++; + i++; for (; i > 0; i --) *dst++ = '\0'; } - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int vfat_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - /** * mangle_dos_name: * @@ -959,6 +948,6 @@ const struct fs_ops vfat_fs_ops = { .getfssec = vfat_getfssec, .close_file = vfat_close_file, .mangle_name = vfat_mangle_name, - .unmangle_name = vfat_unmangle_name, + .unmangle_name = NULL, .load_config = vfat_load_config }; diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 583513cd..2995e34d 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -8,14 +8,11 @@ #define DEBUG 1 -#define FILENAME_MAX_LG2 8 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) #define ISO_SECTOR_SHIFT 11 #define ISO_SECTOR_SIZE (1 << ISO_SECTOR_SHIFT) #define ROOT_DIR_WORD 0x002f #define TRACKBUF_SIZE 8192 - struct open_file_t { sector_t file_sector; uint32_t file_bytesleft; @@ -95,22 +92,22 @@ static void iso_close_file(struct file *file) * a bit of an easier job. * */ -static void iso_mangle_name(char *dst, char *src) +static void iso_mangle_name(char *dst, const char *src) { char *p = dst; int i = FILENAME_MAX - 1; - while ( *src > ' ' ) { + while (not_whitespace(*src)) { if ( *src == '/' ) { if ( *(src+1) == '/' ) { - i --; - src ++; + i--; + src++; continue; } } *dst++ = *src ++; - i --; + i--; } while ( 1 ) { @@ -129,20 +126,6 @@ static void iso_mangle_name(char *dst, char *src) *dst++ = '\0'; } - -/* - * Does the opposite of mangle_name; converts a DOS-mangled - * filename to the conventional representation. This is - * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. - */ -static int iso_unmangle_name(char *dst, char *src) -{ - strcpy(dst, src); - return strlen(src); -} - /** * compare the names si and di and report if they are * equal from an ISO 9600 perspective. @@ -556,6 +539,6 @@ const struct fs_ops iso_fs_ops = { .getfssec = iso_getfssec, .close_file = iso_close_file, .mangle_name = iso_mangle_name, - .unmangle_name = iso_unmangle_name, + .unmangle_name = NULL, .load_config = iso_load_config }; diff --git a/core/fs/lib/mangle.c b/core/fs/lib/mangle.c new file mode 100644 index 00000000..813099fb --- /dev/null +++ b/core/fs/lib/mangle.c @@ -0,0 +1,47 @@ +/** + * mangle_name: + * + * Mangle a filename pointed to by src into a buffer pointed + * to by dst; ends on encountering any whitespace. + * dst is preserved. + * + * This verifies that a filename is < FILENAME_MAX characters, + * doesn't contain whitespace, zero-pads the output buffer, + * and removes redundant slashes. + * + */ + +#include +#include "fs.h" + +void generic_mangle_name(char *dst, const char *src) +{ + char *p = dst; + int i = FILENAME_MAX-1; + + while (not_whitespace(*src)) { + if (*src == '/') { + if (src[1] == '/') { + src++; + i--; + continue; + } + } + i--; + *dst++ = *src++; + } + + while (1) { + if (dst == p) + break; + if (dst[-1] != '/') + break; + + dst--; + i++; + } + + i++; + for (; i > 0; i --) + *dst++ = '\0'; +} diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index d4662f5c..38f6dffb 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -6,11 +6,7 @@ #include #include "pxe.h" -#define FILENAME_MAX_LG2 7 -#define FILENAME_MAX (1 << FILENAME_MAX_LG2) - #define GPXE 1 -#define USE_PXE_PROVIDED_STACK 0 static struct open_file_t Files[MAX_OPEN]; @@ -228,9 +224,9 @@ int gendotquad(char *dst, uint32_t ip) * return the the string address after the ip string * */ -static char *parse_dotquad(char *ip_str, uint32_t *res) +static const char *parse_dotquad(const char *ip_str, uint32_t *res) { - char *p = ip_str; + const char *p = ip_str; int i = 0; uint8_t part = 0; uint32_t ip = 0; @@ -343,10 +339,10 @@ static int pxe_get_cached_info(int type) * url is a URL (contains ://) * */ -static int is_url(char *url) +static int is_url(const char *url) { while (*url) { - if(! strncmp(url, "://", 3)) + if (!strncmp(url, "://", 3)) return 1; url++; @@ -438,9 +434,9 @@ static void get_packet_gpxe(struct open_file_t *file) * the download host, 0 for no host, or -1 for a gPXE URL. * */ -static void pxe_mangle_name(char *dst, char *src) +static void pxe_mangle_name(char *dst, const char *src) { - char *p = src; + const char *p = src; uint32_t ip = 0; int i = 0; @@ -492,15 +488,15 @@ static void pxe_mangle_name(char *dst, char *src) i = FILENAME_MAX - 5; do { - if (*p <= ' ') - break; - *dst++ = *p++; - }while (i--); + if (!not_whitespace(*p)) + break; + *dst++ = *p++; + } while (i--); - i ++; + i++; while (i) { *dst++ = 0; - i --; + i--; } #if 0 @@ -516,10 +512,8 @@ static void pxe_mangle_name(char *dst, char *src) * Does the opposite of mangle_name; converts a DOS-mangled * filename to the conventional representation. This is * needed for the BOOT_IMAGE= parameter for the kernel. - * - * it returns the lenght of the filename. */ -static int pxe_unmangle_name(char *dst, char *src) +static void pxe_unmangle_name(char *dst, const char *src) { uint32_t ip = *(uint32_t *)src; int ip_len = 0; @@ -528,10 +522,8 @@ static int pxe_unmangle_name(char *dst, char *src) ip_len = gendotquad(dst, *(uint32_t *)src); dst += ip_len; } - src += 4;; + src += 4; strcpy(dst, src); - - return strlen(src) + ip_len; } /* diff --git a/core/include/core.h b/core/include/core.h index 12ec37ea..f7a69284 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -81,5 +81,4 @@ extern char UUID[]; extern volatile uint16_t BIOS_timer; - #endif /* CORE_H */ diff --git a/core/include/fs.h b/core/include/fs.h index 21e1349d..2840edb0 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -16,6 +16,9 @@ #define MAX_OPEN_LG2 5 #define MAX_OPEN (1 << MAX_OPEN_LG2) +#define FILENAME_MAX_LG2 8 +#define FILENAME_MAX (1 << FILENAME_MAX_LG2) + struct fs_info { const struct fs_ops *fs_ops; struct device *fs_dev; @@ -42,13 +45,18 @@ struct fs_ops { void (*searchdir)(char *, struct file *); uint32_t (*getfssec)(struct file *, char *, int, bool *); void (*close_file)(struct file *); - void (*mangle_name)(char *, char *); - int (*unmangle_name)(char *, char *); + void (*mangle_name)(char *, const char *); + void (*unmangle_name)(char *, const char *); void (*load_config)(com32sys_t *); }; enum dev_type {CHS, EDD}; - + +/* + * Generic functions that filesystem drivers may choose to use + */ +void generic_mangle_name(char *, const char *); + /* * Struct device contains: * the pointer points to the disk structure, @@ -65,4 +73,12 @@ struct device { uint32_t cache_size; }; +/* + * Our definition of "not whitespace" + */ +static inline bool not_whitespace(char c) +{ + return (unsigned char)c > ' '; +} + #endif /* FS_H */ diff --git a/core/isolinux.asm b/core/isolinux.asm index 2816dd8f..09844781 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -26,8 +26,6 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ isolinux_id -FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) -FILENAME_MAX equ (1 << FILENAME_MAX_LG2) NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 0 ; Position in which to look retry_count equ 6 ; How patient are we with the BIOS? diff --git a/core/ldlinux.asm b/core/ldlinux.asm index f57b2390..20f0ee94 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -29,7 +29,6 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ syslinux_id -FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) extern vfat_fs_ops ROOT_FS_OPS equ vfat_fs_ops diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 2e8b3190..49c81f1e 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -29,8 +29,6 @@ ; Some semi-configurable constants... change on your own risk. ; my_id equ pxelinux_id -FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null) -FILENAME_MAX equ (1 << FILENAME_MAX_LG2) NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 4 ; Position in which to look REBOOT_TIME equ 5*60 ; If failure, time until full reset -- cgit v1.2.1 From 9d74e76846da90d73f77ea9e8275a071d869fd31 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:23:10 -0700 Subject: com32: remove strpcpy() - we already have stpcpy() Remove strpcpy(); it is exactly the same thing as stpcpy() which we already have, and which is more "standard" (in the sense that none of these are actually standard...) Signed-off-by: H. Peter Anvin --- com32/include/string.h | 1 - com32/lib/Makefile | 2 +- com32/lib/strpcpy.c | 20 -------------------- com32/mboot/mboot.c | 2 +- 4 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 com32/lib/strpcpy.c diff --git a/com32/include/string.h b/com32/include/string.h index c964ee3b..af9792b6 100644 --- a/com32/include/string.h +++ b/com32/include/string.h @@ -23,7 +23,6 @@ __extern char *strcat(char *, const char *); __extern char *strchr(const char *, int); __extern int strcmp(const char *, const char *); __extern char *strcpy(char *, const char *); -__extern char *strpcpy(char *, const char *); __extern size_t strcspn(const char *, const char *); __extern char *strdup(const char *); __extern char *strndup(const char *, size_t); diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 1806ec20..0f43aee0 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -17,7 +17,7 @@ LIBOBJS = \ exit.o onexit.o \ perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \ sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \ - strchr.o strcmp.o strcpy.o strpcpy.o strdup.o strlen.o \ + strchr.o strcmp.o strcpy.o strdup.o strlen.o \ strerror.o strnlen.o \ strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \ stpcpy.o stpncpy.o \ diff --git a/com32/lib/strpcpy.c b/com32/lib/strpcpy.c deleted file mode 100644 index a4fd2a06..00000000 --- a/com32/lib/strpcpy.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * strpcpy.c - * - * strpcpy() - strcpy() which returns a pointer to the final null - */ - -#include - -char *strpcpy(char *dst, const char *src) -{ - char *q = dst; - const char *p = src; - char ch; - - do { - *q++ = ch = *p++; - } while (ch); - - return q - 1; -} diff --git a/com32/mboot/mboot.c b/com32/mboot/mboot.c index e7bb8dbb..62ebf523 100644 --- a/com32/mboot/mboot.c +++ b/com32/mboot/mboot.c @@ -135,7 +135,7 @@ static int get_modules(char **argv, struct module_data **mdp) char *p; mp->cmdline = p = malloc(arglen); for (; *argp && strcmp(*argp, module_separator); argp++) { - p = strpcpy(p, *argp); + p = stpcpy(p, *argp); *p++ = ' '; } *--p = '\0'; -- cgit v1.2.1 From 43c00b21090c396f92502a6b6fc9c2bd35f59684 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:30:45 -0700 Subject: iso9660: adjust to the new VFS I missed converting iso9660 over to the new VFS. Do it now. In particular, getfssec now takes a struct file *. Signed-off-by: H. Peter Anvin --- core/fs/iso9660/iso9660.c | 224 +++++++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 110 deletions(-) diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 2995e34d..ec84dc50 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -34,9 +34,9 @@ static uint16_t BufSafe = TRACKBUF_SIZE >> ISO_SECTOR_SHIFT; static char ISOFileName[64]; /* ISO filename canonicalizatin buffer */ static char *ISOFileNameEnd = &ISOFileName[64]; -/* +/* * use to store the block shift, since we treat the hd-mode as 512 bytes - * sector size, 2048 bytes block size. we still treat the cdrom as 2048 + * sector size, 2048 bytes block size. we still treat the cdrom as 2048 * bytes sector size and also the block size. */ static int block_shift; @@ -51,21 +51,21 @@ static struct open_file_t *allocate_file(void) { struct open_file_t *file = Files; int i; - + for (i = 0; i < MAX_OPEN; i++) { if ( file->file_sector == 0 ) /* found it */ return file; file++; } - + return NULL; /* not found */ } - + /** * close_file: - * - * Deallocates a file structure + * + * Deallocates a file structure * */ static inline void close_pvt(struct open_file_t *file) @@ -85,7 +85,7 @@ static void iso_close_file(struct file *file) * to by dst; ends on encountering any whitespace. * dst is preserved. * - * This verifies that a filename is < FilENAME_MAX characters, + * This verifies that a filename is < FilENAME_MAX characters, * doesn't contain whitespace, zero-pads the output buffer, * and removes trailing dots and redumndant slashes, so "repe * cmpsb" can do a compare, and the path-searching routine gets @@ -96,7 +96,7 @@ static void iso_mangle_name(char *dst, const char *src) { char *p = dst; int i = FILENAME_MAX - 1; - + while (not_whitespace(*src)) { if ( *src == '/' ) { if ( *(src+1) == '/' ) { @@ -105,30 +105,30 @@ static void iso_mangle_name(char *dst, const char *src) continue; } } - + *dst++ = *src ++; i--; } - + while ( 1 ) { if ( dst == p ) break; - - if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) + + if ( (*(dst-1) != '.') && (*(dst-1) != '/') ) break; - + dst --; i ++; } - + i ++; for (; i > 0; i -- ) *dst++ = '\0'; } - + /** * compare the names si and di and report if they are - * equal from an ISO 9600 perspective. + * equal from an ISO 9600 perspective. * * @param: de_name, the name from the file system. * @param: len, the length of de_name, and will return the real name of the de_name @@ -139,56 +139,56 @@ static void iso_mangle_name(char *dst, const char *src) * */ static int iso_compare_names(char *de_name, int *len, char *file_name) -{ +{ char *p = ISOFileName; char c1, c2; - + int i = 0; - + while ( (i < *len) && *de_name && (*de_name != ';') && (p < ISOFileNameEnd - 1) ) { *p++ = *de_name++; i++; } - + /* Remove terminal dots */ while ( *(p-1) == '.' ) { if ( *len <= 2 ) break; - + if ( p <= ISOFileName ) break; p --; i--; } - + if ( i <= 0 ) return 0; - + *p = '\0'; - + /* return the 'real' length of de_name */ *len = i; - + p = ISOFileName; - + /* i is the 'real' name length of file_name */ while ( i ) { c1 = *p++; c2 = *file_name++; - + if ( (c1 == 0) && (c2 == 0) ) return 1; /* success */ - + else if ( (c1 == 0) || ( c2 == 0 ) ) return 0; - + c1 |= 0x20; c2 |= 0x20; /* convert to lower case */ if ( c1 != c2 ) return 0; i --; } - + return 1; } @@ -207,32 +207,32 @@ static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, in * * @param: buf * @param: file, the address of the open file structure - * @param: sectors, how many we want to read at once + * @param: sectors, how many we want to read at once * @param: have_more, to indicate if we have reach the end of the file * */ -static uint32_t iso_getfssec(struct fs_info *fs, char *buf, - void *open_file, int sectors, int *have_more) +static uint32_t iso_getfssec(struct file *gfile, char *buf, + int sectors, bool *have_more) { uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT; - struct open_file_t *file = (struct open_file_t *)open_file; - struct disk *disk = fs->fs_dev->disk; - + struct open_file_t *file = gfile->open_file; + struct disk *disk = gfile->fs->fs_dev->disk; + if ( sectors > file->file_left ) sectors = file->file_left; - + cdrom_read_sectors(disk, buf, file->file_sector, sectors); - + file->file_sector += sectors; file->file_left -= sectors; - + if ( bytes_read >= file->file_bytesleft ) { bytes_read = file->file_bytesleft; *have_more = 0; } else *have_more = 1; file->file_bytesleft -= bytes_read; - + return bytes_read; } @@ -242,126 +242,130 @@ static uint32_t iso_getfssec(struct fs_info *fs, char *buf, * do_search_dir: * * find a file or directory with name within the _dir_ directory. - * + * * the return value will tell us what we find, it's a file or dir? * on 1 be dir, 2 be file, 0 be error. * * res will return the result. * */ -static int do_search_dir(struct fs_info *fs, struct dir_t *dir, - char *name, uint32_t *file_len, void **res) +static int do_search_dir(struct fs_info *fs, struct dir_t *dir, + char *name, uint32_t *file_len, void **res) { struct open_file_t *file; struct iso_dir_entry *de; struct iso_dir_entry tmpde; - + struct file xfile; + uint32_t offset = 0; /* let's start it with the start */ uint32_t file_pos = 0; char *de_name; int de_len; int de_name_len; - int have_more; - + bool have_more; + file = allocate_file(); if ( !file ) return 0; - + file->file_left = dir->dir_clust; file->file_sector = dir->dir_lba; - - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + + xfile.fs = fs; + xfile.open_file = file; + + iso_getfssec(&xfile, trackbuf, BufSafe, &have_more); de = (struct iso_dir_entry *)trackbuf; - + while ( file_pos < dir->dir_len ) { int found = 0; - + if ( (char *)de >= (char *)(trackbuf + TRACKBUF_SIZE) ) { - if ( !have_more ) + if ( !have_more ) return 0; - - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + + iso_getfssec(&xfile, trackbuf, BufSafe, &have_more); offset = 0; } - + de = (struct iso_dir_entry *) (trackbuf + offset); - + de_len = de->length; - + if ( de_len == 0) { offset = file_pos = (file_pos+ISO_SECTOR_SIZE) & ~(ISO_SECTOR_SIZE-1); continue; } - - + + offset += de_len; - + /* Make sure we have a full directory entry */ if ( offset >= TRACKBUF_SIZE ) { int slop = TRACKBUF_SIZE - offset + de_len; memcpy(&tmpde, de, slop); offset &= TRACKBUF_SIZE - 1; - file->file_sector ++; + file->file_sector++; if ( offset ) { - if ( !have_more ) + if ( !have_more ) return 0; - iso_getfssec(fs, trackbuf, file, BufSafe, &have_more); + iso_getfssec(&xfile, trackbuf, BufSafe, &have_more); memcpy((void*)&tmpde + slop, trackbuf, offset); } de = &tmpde; } - + if ( de_len < 33 ) { printf("Corrutped directory entry in sector %d\n", file->file_sector); return 0; } - + de_name_len = de->name_len; de_name = (char *)((void *)de + 0x21); - - + + if ( (de_name_len == 1) && (*de_name == 0) ) { found = iso_compare_names(".", &de_name_len, name); - + } else if ( (de_name_len == 1) && (*de_name == 1) ) { de_name_len = 2; found = iso_compare_names("..", &de_name_len, name); - - } else + + } else found = iso_compare_names(de_name, &de_name_len, name); - + if (found) break; - + file_pos += de_len; } - - if ( file_pos >= dir->dir_len ) + + if ( file_pos >= dir->dir_len ) return 0; /* not found */ - + if ( *(name+de_name_len) && (*(name+de_name_len) != '/' ) ) { printf("Something wrong happened during searching file %s\n", name); - + *res = NULL; return 0; } - + if ( de->flags & 0x02 ) { - /* it's a directory */ - dir = &CurrentDir; + /* it's a directory */ + dir = &CurrentDir; dir->dir_lba = *(uint32_t *)de->extent; dir->dir_len = *(uint32_t *)de->size; dir->dir_clust = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - + *file_len = dir->dir_len; *res = dir; - + /* we can close it now */ - close_pvt(file); - + close_pvt(file); + /* Mark we got a directory */ - return 1; + return 1; } else { /* it's a file */ file->file_sector = *(uint32_t *)de->extent; @@ -370,10 +374,10 @@ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, *file_len = file->file_bytesleft; *res = file; - + /* Mark we got a file */ return 2; - } + } } @@ -383,7 +387,7 @@ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, * open a file * * searchdir_iso is a special entry point for ISOLINUX only. In addition - * to the above, searchdir_iso passes a file flag mask in AL. This is + * to the above, searchdir_iso passes a file flag mask in AL. This is * useful for searching for directories. * * well, it's not like the searchidr function in EXT fs or FAT fs; it also @@ -397,7 +401,7 @@ static void iso_searchdir(char *filename, struct file *file) uint32_t file_len = 0; int ret; void *res; - + dir = &CurrentDir; if ( *filename == '/' ) { dir = &RootDir; @@ -410,18 +414,18 @@ static void iso_searchdir(char *filename, struct file *file) dir = (struct dir_t *)res; else if ( ret == 2 ) break; - else + else goto err; - + /* find the end */ while ( *filename && (*filename != '/') ) filename ++; - + /* skip the slash */ while ( *filename && (*filename == '/') ) - filename++; + filename++; } - + /* well , we need recheck it , becuase it can be a directory */ if ( ret == 2 ) { open_file = (struct open_file_t *)res; @@ -430,7 +434,7 @@ static void iso_searchdir(char *filename, struct file *file) open_file = allocate_file(); if ( !open_file ) goto err; - + open_file->file_sector = dir->dir_lba; open_file->file_bytesleft = dir->dir_len; open_file->file_left = (dir->dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; @@ -440,7 +444,7 @@ static void iso_searchdir(char *filename, struct file *file) close_pvt(open_file); file_len = 0; open_file = NULL; - + found: file->file_len = file_len; file->open_file = (void*)open_file; @@ -459,9 +463,9 @@ static void iso_load_config(com32sys_t *regs) { char *config_name = "isolinux.cfg"; com32sys_t out_regs; - + strcpy(ConfigName, config_name); - + regs->edi.w[0] = OFFS_WRT(ConfigName, 0); memset(&out_regs, 0, sizeof out_regs); call16(core_open, regs, &out_regs); @@ -474,22 +478,22 @@ static int iso_fs_init(struct fs_info *fs) char *boot_dir = "/boot/isolinux"; char *isolinux_dir = "/isolinux"; int len; - int bi_pvd = 16; + int bi_pvd = 16; struct file file; struct open_file_t *open_file; struct disk *disk = fs->fs_dev->disk; - + block_shift = ISO_SECTOR_SHIFT - disk->sector_shift; cdrom_read_sectors(disk, trackbuf, bi_pvd, 1); CurrentDir.dir_lba = RootDir.dir_lba = *(uint32_t *)(trackbuf + 156 + 2); - + #ifdef DEBUG printf("Root directory at LBA = 0x%x\n", RootDir.dir_lba); #endif - + CurrentDir.dir_len = RootDir.dir_len = *(uint32_t*)(trackbuf + 156 + 10); CurrentDir.dir_clust = RootDir.dir_clust = (RootDir.dir_len + ISO_SECTOR_SIZE - 1) >> ISO_SECTOR_SHIFT; - + /* * Look for an isolinux directory, and if found, * make it the current directory instead of the @@ -498,7 +502,7 @@ static int iso_fs_init(struct fs_info *fs) * Also copy the name of the directory to CurrrentDirName */ *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; - + iso_dir = boot_dir; file.fs = fs; iso_searchdir(boot_dir, &file); /* search for /boot/isolinux */ @@ -508,24 +512,24 @@ static int iso_fs_init(struct fs_info *fs) if ( !file.file_len ) { printf("No isolinux directory found!\n"); return 0; - } + } } - + strcpy(CurrentDirName, iso_dir); len = strlen(CurrentDirName); CurrentDirName[len] = '/'; CurrentDirName[len+1] = '\0'; - + open_file = (struct open_file_t *)file.open_file; CurrentDir.dir_len = open_file->file_bytesleft; CurrentDir.dir_clust = open_file->file_left; CurrentDir.dir_lba = open_file->file_sector; close_pvt(open_file); - + #ifdef DEBUG printf("isolinux directory at LBA = 0x%x\n", CurrentDir.dir_lba); -#endif - +#endif + /* we do not use cache for now, so we can just return 0 */ return 0; } -- cgit v1.2.1 From a1fc1f47b4e6080edabb517a070e3c1918c1b3a1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:31:49 -0700 Subject: core: use stpcpy() as generic_unmangle_name() We can use stpcpy() as generic_unmangle_name(); this also gives us the pointer to the end that the assembly code wants and expects. Signed-off-by: H. Peter Anvin --- core/fs.c | 6 +----- core/fs/ext2/ext2.c | 2 +- core/fs/fat/fat.c | 2 +- core/fs/iso9660/iso9660.c | 2 +- core/fs/pxe/pxe.c | 6 +++--- core/include/fs.h | 4 +++- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/core/fs.c b/core/fs.c index ad6659b2..2804468b 100644 --- a/core/fs.c +++ b/core/fs.c @@ -73,13 +73,9 @@ void unmangle_name(com32sys_t *regs) const char *src = MK_PTR(regs->ds, regs->esi.w[0]); char *dst = MK_PTR(regs->es, regs->edi.w[0]); - if (this_fs->fs_ops->unmangle_name) - this_fs->fs_ops->unmangle_name(dst, src); - else - strcpy(dst, src); + dst = this_fs->fs_ops->unmangle_name(dst, src); /* Update the di register to point to the last null char */ - dst = strchr(dst, '\0'); regs->edi.w[0] = OFFS_WRT(dst, regs->es); } diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c index 546a127a..34aba24f 100644 --- a/core/fs/ext2/ext2.c +++ b/core/fs/ext2/ext2.c @@ -757,6 +757,6 @@ const struct fs_ops ext2_fs_ops = { .getfssec = ext2_getfssec, .close_file = ext2_close_file, .mangle_name = generic_mangle_name, - .unmangle_name = NULL, + .unmangle_name = generic_unmangle_name, .load_config = ext2_load_config }; diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 1b1c532e..0611caec 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -948,6 +948,6 @@ const struct fs_ops vfat_fs_ops = { .getfssec = vfat_getfssec, .close_file = vfat_close_file, .mangle_name = vfat_mangle_name, - .unmangle_name = NULL, + .unmangle_name = generic_unmangle_name, .load_config = vfat_load_config }; diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index ec84dc50..1d08805b 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -543,6 +543,6 @@ const struct fs_ops iso_fs_ops = { .getfssec = iso_getfssec, .close_file = iso_close_file, .mangle_name = iso_mangle_name, - .unmangle_name = NULL, + .unmangle_name = generic_unmangle_name, .load_config = iso_load_config }; diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 38f6dffb..ceb12102 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -513,7 +513,7 @@ static void pxe_mangle_name(char *dst, const char *src) * filename to the conventional representation. This is * needed for the BOOT_IMAGE= parameter for the kernel. */ -static void pxe_unmangle_name(char *dst, const char *src) +static char *pxe_unmangle_name(char *dst, const char *src) { uint32_t ip = *(uint32_t *)src; int ip_len = 0; @@ -523,9 +523,9 @@ static void pxe_unmangle_name(char *dst, const char *src) dst += ip_len; } src += 4; - strcpy(dst, src); + return stpcpy(dst, src); } - + /* * ; diff --git a/core/include/fs.h b/core/include/fs.h index 2840edb0..04e85ef8 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "core.h" #include "disk.h" @@ -46,7 +47,7 @@ struct fs_ops { uint32_t (*getfssec)(struct file *, char *, int, bool *); void (*close_file)(struct file *); void (*mangle_name)(char *, const char *); - void (*unmangle_name)(char *, const char *); + char * (*unmangle_name)(char *, const char *); void (*load_config)(com32sys_t *); }; @@ -56,6 +57,7 @@ enum dev_type {CHS, EDD}; * Generic functions that filesystem drivers may choose to use */ void generic_mangle_name(char *, const char *); +#define generic_unmangle_name stpcpy /* * Struct device contains: -- cgit v1.2.1 From ff30d914fe20fd5e4743b906ecfe0239f1c4e013 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:37:29 -0700 Subject: netinet/in.h: put in explicit casts for all the hton/ntoh macros For the macro versions of hton/ntoh, use casts everywhere. Signed-off-by: H. Peter Anvin --- com32/include/netinet/in.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h index 97458bf9..9c5173be 100644 --- a/com32/include/netinet/in.h +++ b/com32/include/netinet/in.h @@ -5,7 +5,7 @@ #include -#define __htons_macro(v) (((v) << 8) | ((v) >> 8)) +#define __htons_macro(v) (((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8)) static inline uint16_t __htons(uint16_t v) { @@ -15,10 +15,10 @@ static inline uint16_t __htons(uint16_t v) #define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x)) #define ntohs(x) htons(x) -#define __htonl_macro(v) ((((v) & 0x000000ff) << 24) | \ - (((v) & 0x0000ff00) << 8) | \ - (((v) & 0x00ff0000) >> 8) | \ - (((v) & 0xff000000) >> 24)) +#define __htonl_macro(v) ((((uint32_t)(v) & 0x000000ff) << 24) | \ + (((uint32_t)(v) & 0x0000ff00) << 8) | \ + (((uint32_t)(v) & 0x00ff0000) >> 8) | \ + (((uint32_t)(v) & 0xff000000) >> 24)) static inline uint32_t __htonl(uint32_t v) { @@ -35,7 +35,7 @@ static inline uint32_t __htonl(uint32_t v) #define __htonq_macro(v) \ (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ - (__htonl_macro((uint32_t)((v) >> 32)))) + (__htonl_macro((uint32_t)((uint64_t)(v) >> 32)))) static inline uint64_t __htonq(uint64_t v) { -- cgit v1.2.1 From 69269947f6f716dcb01f3bf00e9a4ca00c04c10c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:39:52 -0700 Subject: netinet/in.h: add __constfunc to inlines All the byte-swapping functions are true constfuncs... Signed-off-by: H. Peter Anvin --- com32/include/netinet/in.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h index 9c5173be..ea0a1788 100644 --- a/com32/include/netinet/in.h +++ b/com32/include/netinet/in.h @@ -4,10 +4,11 @@ /* COM32 will be running on an i386 platform */ #include +#include #define __htons_macro(v) (((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8)) -static inline uint16_t __htons(uint16_t v) +static inline __constfunc uint16_t __htons(uint16_t v) { return __htons_macro(v); } @@ -20,12 +21,12 @@ static inline uint16_t __htons(uint16_t v) (((uint32_t)(v) & 0x00ff0000) >> 8) | \ (((uint32_t)(v) & 0xff000000) >> 24)) -static inline uint32_t __htonl(uint32_t v) +static inline __constfunc uint32_t __htonl(uint32_t v) { if (__builtin_constant_p(v)) { return __htonl_macro(v); } else { - asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0":"+q"(v)); + asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" : "+q"(v)); return v; } } @@ -37,7 +38,7 @@ static inline uint32_t __htonl(uint32_t v) (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ (__htonl_macro((uint32_t)((uint64_t)(v) >> 32)))) -static inline uint64_t __htonq(uint64_t v) +static inline __constfunc uint64_t __htonq(uint64_t v) { return ((uint64_t) __htonl(v) << 32) | __htonl(v >> 32); } -- cgit v1.2.1 From 39851b279e6001157094ea87ffe27d0ad152edb4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Aug 2009 21:51:54 -0700 Subject: core: cleaner way to call kaboom from 32-bit code Make kaboom() a noreturn function directly callable from 32-bit code. Do a special macro hack to keep it from interfering with the symbol kaboom in 16-bit code. Signed-off-by: H. Peter Anvin --- core/call16.c | 2 ++ core/fs/pxe/pxe.c | 17 ++++++++--------- core/include/core.h | 9 ++++++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/core/call16.c b/core/call16.c index 1e369e29..86d70461 100644 --- a/core/call16.c +++ b/core/call16.c @@ -19,6 +19,8 @@ #include #include "core.h" +const com32sys_t zero_regs; /* Common all-zero register set */ + void call16(void (*func)(void), const com32sys_t *ireg, com32sys_t *oreg) { core_farcall((size_t)func, ireg, oreg); diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index ceb12102..d03847d3 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -324,7 +324,7 @@ static int pxe_get_cached_info(int type) err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); if (err) { printf("%s %04x\n", err_pxefailed, err); - call16(kaboom, NULL, NULL); + kaboom(); } return bq_pkt.buffersize; @@ -404,9 +404,8 @@ static void get_packet_gpxe(struct open_file_t *file) if (!err) /* successed */ break; - if (fr.status == PXENV_STATUS_TFTP_OPEN) - continue; - call16(kaboom, NULL, NULL); + if (fr.status != PXENV_STATUS_TFTP_OPEN) + kaboom(); } file->tftp_bytesleft = fr.buffersize; @@ -603,7 +602,7 @@ static void fill_buffer(struct open_file_t *file) /* time runs out */ if (timeout == 0) - call16(kaboom, NULL, NULL); + kaboom(); last_pkt = file->tftp_lastpkt; last_pkt = ntohs(last_pkt); /* Host byte order */ @@ -996,7 +995,7 @@ err_reply: uw_pkt.buffersize = 24; pxe_call(PXENV_UDP_WRITE, &uw_pkt); printf("TFTP server sent an incomprehesible reply\n"); - call16(kaboom, NULL, NULL); + kaboom(); failure: timeout_ptr++; @@ -1146,7 +1145,7 @@ static void pxe_load_config(com32sys_t *regs) return; printf("Unable to locate configuration file\n"); - call16(kaboom, NULL, NULL); + kaboom(); } @@ -1382,7 +1381,7 @@ static void pxe_init(void) /* Found nothing at all !! */ printf("%s\n", err_nopxe); - call16(kaboom, NULL, NULL); + kaboom(); have_pxenv: APIVer = pxenv->version; @@ -1445,7 +1444,7 @@ static void udp_init(void) if (err || uo_pkt.status) { printf("%s", err_udpinit); printf("%d\n", uo_pkt.status); - call16(kaboom, NULL, NULL); + kaboom(); } } diff --git a/core/include/core.h b/core/include/core.h index f7a69284..ad00492d 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -25,6 +25,7 @@ void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); int __cdecl core_cfarcall(uint32_t, const void *, uint32_t); +extern const com32sys_t zero_regs; void call16(void (*)(void), const com32sys_t *, com32sys_t *); /* @@ -33,10 +34,16 @@ void call16(void (*)(void), const com32sys_t *, com32sys_t *); #define __lowmem __attribute((nocommon,section(".lowmem"))) #define __bss16 __attribute((nocommon,section(".bss16"))) +/* + * Death! The macro trick is to avoid symbol conflict with + * the real-mode symbol kaboom. + */ +__noreturn _kaboom(void); +#define kaboom() _kaboom() + /* * externs for pxelinux */ -extern void kaboom(void); extern void dns_mangle(void); extern uint32_t ServerIP; -- cgit v1.2.1 From 7d4c44aff907b8c1366ec8346281e92ce00d19ba Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Aug 2009 15:26:49 -0700 Subject: Revert "Run Nindent on com32/include/png.h" This reverts commit ab7b6c3380cd9188edbc99693d5562dcca055317. is part of libpng and hence externally maintained; it should not have been Nindented. Signed-off-by: H. Peter Anvin --- com32/include/png.h | 2906 +++++++++++++++++++++++---------------------------- 1 file changed, 1290 insertions(+), 1616 deletions(-) diff --git a/com32/include/png.h b/com32/include/png.h index d9e73c9c..800b912e 100644 --- a/com32/include/png.h +++ b/com32/include/png.h @@ -338,12 +338,12 @@ #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 /* Release-Specific Flags */ -#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with - PNG_LIBPNG_BUILD_STABLE only */ -#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with - PNG_LIBPNG_BUILD_SPECIAL */ -#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with - PNG_LIBPNG_BUILD_PRIVATE */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE @@ -352,7 +352,7 @@ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10208 /* 1.2.8 */ +#define PNG_LIBPNG_VER 10208 /* 1.2.8 */ #ifndef PNG_VERSION_INFO_ONLY /* include the compression library's header */ @@ -392,7 +392,7 @@ /* Inhibit C++ name-mangling for libpng functions but not for system calls. */ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* __cplusplus */ /* This file is arranged in several sections. The first section contains * structure and type definitions. The second section contains the external @@ -440,8 +440,8 @@ extern "C" { * the version above. */ #ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR(const char) png_libpng_ver[18]; - /* need room for 99.99.99beta99z */ +PNG_EXPORT_VAR (const char) png_libpng_ver[18]; + /* need room for 99.99.99beta99z */ #else #define png_libpng_ver png_get_header_ver(NULL) #endif @@ -449,81 +449,86 @@ extern "C" { #ifdef PNG_USE_GLOBAL_ARRAYS /* This was removed in version 1.0.5c */ /* Structures to facilitate easy interlacing. See png.c for more details */ - PNG_EXPORT_VAR(const int FARDATA) png_pass_start[7]; - PNG_EXPORT_VAR(const int FARDATA) png_pass_inc[7]; - PNG_EXPORT_VAR(const int FARDATA) png_pass_ystart[7]; - PNG_EXPORT_VAR(const int FARDATA) png_pass_yinc[7]; - PNG_EXPORT_VAR(const int FARDATA) png_pass_mask[7]; - PNG_EXPORT_VAR(const int FARDATA) png_pass_dsp_mask[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_start[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_inc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_ystart[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_yinc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_mask[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_dsp_mask[7]; #ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW - PNG_EXPORT_VAR(const int FARDATA) png_pass_width[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_width[7]; #endif /* This isn't currently used. If you need it, see png.c for more details. PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; */ #endif -#endif /* PNG_NO_EXTERN */ +#endif /* PNG_NO_EXTERN */ /* Three color definitions. The order of the red, green, and blue, (and the * exact size) is not important, although the size of the fields need to * be png_byte or png_uint_16 (as defined below). */ - typedef struct png_color_struct { - png_byte red; - png_byte green; - png_byte blue; - } png_color; - typedef png_color FAR *png_colorp; - typedef png_color FAR *FAR * png_colorpp; - - typedef struct png_color_16_struct { - png_byte index; /* used for palette files */ - png_uint_16 red; /* for use in red green blue files */ - png_uint_16 green; - png_uint_16 blue; - png_uint_16 gray; /* for use in grayscale files */ - } png_color_16; - typedef png_color_16 FAR *png_color_16p; - typedef png_color_16 FAR *FAR * png_color_16pp; - - typedef struct png_color_8_struct { - png_byte red; /* for use in red green blue files */ - png_byte green; - png_byte blue; - png_byte gray; /* for use in grayscale files */ - png_byte alpha; /* for alpha channel files */ - } png_color_8; - typedef png_color_8 FAR *png_color_8p; - typedef png_color_8 FAR *FAR * png_color_8pp; +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; /* * The following two structures are used for the in-core representation * of sPLT chunks. */ - typedef struct png_sPLT_entry_struct { - png_uint_16 red; - png_uint_16 green; - png_uint_16 blue; - png_uint_16 alpha; - png_uint_16 frequency; - } png_sPLT_entry; - typedef png_sPLT_entry FAR *png_sPLT_entryp; - typedef png_sPLT_entry FAR *FAR * png_sPLT_entrypp; +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; /* When the depth of the sPLT palette is 8 bits, the color and alpha samples * occupy the LSB of their respective members, and the MSB of each member * is zero-filled. The frequency member always occupies the full 16 bits. */ - typedef struct png_sPLT_struct { - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ - } png_sPLT_t; - typedef png_sPLT_t FAR *png_sPLT_tp; - typedef png_sPLT_t FAR *FAR * png_sPLT_tpp; +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; #ifdef PNG_TEXT_SUPPORTED /* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, @@ -534,26 +539,27 @@ PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; * regular zero-terminated C strings (possibly empty), never NULL pointers, * so they can be safely used in printf() and other string-handling functions. */ - typedef struct png_text_struct { - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ - png_size_t text_length; /* length of the text string */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ #ifdef PNG_iTXt_SUPPORTED - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ #endif - } png_text; - typedef png_text FAR *png_textp; - typedef png_text FAR *FAR * png_textpp; +} png_text; +typedef png_text FAR * png_textp; +typedef png_text FAR * FAR * png_textpp; #endif /* Supported compression types for text in PNG files (tEXt, and zTXt). @@ -564,7 +570,7 @@ PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; #define PNG_TEXT_COMPRESSION_zTXt 0 #define PNG_ITXT_COMPRESSION_NONE 1 #define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ /* png_time is a way to hold the time in an machine independent way. * Two conversions are provided, both from time_t and struct tm. There @@ -572,16 +578,17 @@ PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; * as I know. If you know of a portable way, send it to me. As a side * note - PNG has always been Year 2000 compliant! */ - typedef struct png_time_struct { - png_uint_16 year; /* full year, as in, 1995 */ - png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ - png_byte minute; /* minute of hour, 0 - 59 */ - png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ - } png_time; - typedef png_time FAR *png_timep; - typedef png_time FAR *FAR * png_timepp; +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef png_time FAR * FAR * png_timepp; #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) /* png_unknown_chunk is a structure to hold queued chunks for which there is @@ -589,16 +596,18 @@ PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; * up private chunks for output even though the library doesn't actually * know about their semantics. */ - typedef struct png_unknown_chunk_t { - png_byte name[5]; - png_byte *data; - png_size_t size; - - /* libpng-using applications should NOT directly modify this byte. */ - png_byte location; /* mode of operation at read time */ - } png_unknown_chunk; - typedef png_unknown_chunk FAR *png_unknown_chunkp; - typedef png_unknown_chunk FAR *FAR * png_unknown_chunkpp; +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; #endif /* png_info is a structure that holds the information in a PNG file so @@ -640,245 +649,246 @@ PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns * functions do not make their own copies. */ - typedef struct png_info_struct { - /* the following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ - png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ - png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ - png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ - png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ - /* The following three should have been named *_method not *_type */ - png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ - png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - - /* The following is informational only on read, and not used on writes. */ - png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte spare_byte; /* to align the data, and for future use */ - png_byte signature[8]; /* magic bytes read by libpng from start of file */ - - /* The rest of the data is optional. If you are reading, check the - * valid field to see if the information in these are valid. If you - * are writing, set the valid field to those chunks you want written, - * and initialize the appropriate fields below. - */ +typedef struct png_info_struct +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ #if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - /* The gAMA chunk describes the gamma characteristics of the system - * on which the image was created, normally in the range [1.0, 2.5]. - * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. - */ - float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ #endif #if defined(PNG_sRGB_SUPPORTED) - /* GR-P, 0.96a */ - /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ - png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ #endif #if defined(PNG_TEXT_SUPPORTED) - /* The tEXt, and zTXt chunks contain human-readable textual data in - * uncompressed, compressed, and optionally compressed forms, respectively. - * The data in "text" is an array of pointers to uncompressed, - * null-terminated C strings. Each chunk has a keyword that describes the - * textual data contained in that chunk. Keywords are not required to be - * unique, and the text string may be empty. Any number of text chunks may - * be in an image. - */ - int num_text; /* number of comments read/to write */ - int max_text; /* current size of text array */ - png_textp text; /* array of comments read/to write */ -#endif /* PNG_TEXT_SUPPORTED */ + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read/to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read/to write */ +#endif /* PNG_TEXT_SUPPORTED */ #if defined(PNG_tIME_SUPPORTED) - /* The tIME chunk holds the last time the displayed image data was - * modified. See the png_time struct for the contents of this struct. - */ - png_time mod_time; + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; #endif #if defined(PNG_sBIT_SUPPORTED) - /* The sBIT chunk specifies the number of significant high-order bits - * in the pixel data. Values are in the range [1, bit_depth], and are - * only specified for the channels in the pixel data. The contents of - * the low-order bits is not specified. Data is valid if - * (valid & PNG_INFO_sBIT) is non-zero. - */ - png_color_8 sig_bit; /* significant bits in color channels */ + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The tRNS chunk supplies transparency data for paletted images and - * other image types that don't need a full alpha channel. There are - * "num_trans" transparency values for a paletted image, stored in the - * same order as the palette colors, starting from index 0. Values - * for the data are in the range [0, 255], ranging from fully transparent - * to fully opaque, respectively. For non-paletted images, there is a - * single color specified that should be treated as fully transparent. - * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. - */ - png_bytep trans; /* transparent values for paletted image */ - png_color_16 trans_values; /* transparent color for non-palette image */ + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans; /* transparent values for paletted image */ + png_color_16 trans_values; /* transparent color for non-palette image */ #endif #if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The bKGD chunk gives the suggested image background color if the - * display program does not have its own background color and the image - * is needs to composited onto a background before display. The colors - * in "background" are normally in the same color space/depth as the - * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. - */ - png_color_16 background; + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; #endif #if defined(PNG_oFFs_SUPPORTED) - /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards - * and downwards from the top-left corner of the display, page, or other - * application-specific co-ordinate space. See the PNG_OFFSET_ defines - * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. - */ - png_int_32 x_offset; /* x offset on page */ - png_int_32 y_offset; /* y offset on page */ - png_byte offset_unit_type; /* offset units type */ + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ #endif #if defined(PNG_pHYs_SUPPORTED) - /* The pHYs chunk gives the physical pixel density of the image for - * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ - * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. - */ - png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ - png_uint_32 y_pixels_per_unit; /* vertical pixel density */ - png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ #endif #if defined(PNG_hIST_SUPPORTED) - /* The hIST chunk contains the relative frequency or importance of the - * various palette entries, so that a viewer can intelligently select a - * reduced-color palette, if required. Data is an array of "num_palette" - * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) - * is non-zero. - */ - png_uint_16p hist; + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; #endif #ifdef PNG_cHRM_SUPPORTED - /* The cHRM chunk describes the CIE color characteristics of the monitor - * on which the PNG was created. This data allows the viewer to do gamut - * mapping of the input image to ensure that the viewer sees the same - * colors in the image as the creator. Values are in the range - * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. - */ + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ #ifdef PNG_FLOATING_POINT_SUPPORTED - float x_white; - float y_white; - float x_red; - float y_red; - float x_green; - float y_green; - float x_blue; - float y_blue; + float x_white; + float y_white; + float x_red; + float y_red; + float x_green; + float y_green; + float x_blue; + float y_blue; #endif #endif #if defined(PNG_pCAL_SUPPORTED) - /* The pCAL chunk describes a transformation between the stored pixel - * values and original physical data values used to create the image. - * The integer range [0, 2^bit_depth - 1] maps to the floating-point - * range given by [pcal_X0, pcal_X1], and are further transformed by a - * (possibly non-linear) transformation function given by "pcal_type" - * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ - * defines below, and the PNG-Group's PNG extensions document for a - * complete description of the transformations and how they should be - * implemented, and for a description of the ASCII parameter strings. - * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. - */ - png_charp pcal_purpose; /* pCAL chunk description string */ - png_int_32 pcal_X0; /* minimum value */ - png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ - png_charpp pcal_params; /* ASCII strings containing parameter values */ - png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ - png_byte pcal_nparams; /* number of parameters given in pcal_params */ + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ #endif /* New members added in libpng-1.0.6 */ #ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ #endif #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunks that the library doesn't recognize. */ - png_unknown_chunkp unknown_chunks; - png_size_t unknown_chunks_num; + /* storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + png_size_t unknown_chunks_num; #endif #if defined(PNG_iCCP_SUPPORTED) - /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ - png_charp iccp_profile; /* International Color Consortium profile data */ - /* Note to maintainer: should be png_bytep */ - png_uint_32 iccp_proflen; /* ICC profile data length */ - png_byte iccp_compression; /* Always zero */ + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_charp iccp_profile; /* International Color Consortium profile data */ + /* Note to maintainer: should be png_bytep */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ #endif #if defined(PNG_sPLT_SUPPORTED) - /* data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes; - png_uint_32 splt_palettes_num; + /* data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; #endif #if defined(PNG_sCAL_SUPPORTED) - /* The sCAL chunk describes the actual physical dimensions of the - * subject matter of the graphic. The chunk contains a unit specification - * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel - * in the image. This external representation is converted to double - * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. - */ - png_byte scal_unit; /* unit of physical scale */ + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. This external representation is converted to double + * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ #ifdef PNG_FLOATING_POINT_SUPPORTED - double scal_pixel_width; /* width of one pixel */ - double scal_pixel_height; /* height of one pixel */ + double scal_pixel_width; /* width of one pixel */ + double scal_pixel_height; /* height of one pixel */ #endif #ifdef PNG_FIXED_POINT_SUPPORTED - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ #endif #endif #if defined(PNG_INFO_IMAGE_SUPPORTED) - /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ - /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers; /* the image bits */ + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ #endif #if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) - png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */ + png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */ #endif #if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) - png_fixed_point int_x_white; - png_fixed_point int_y_white; - png_fixed_point int_x_red; - png_fixed_point int_y_red; - png_fixed_point int_x_green; - png_fixed_point int_y_green; - png_fixed_point int_x_blue; - png_fixed_point int_y_blue; + png_fixed_point int_x_white; + png_fixed_point int_y_white; + png_fixed_point int_x_red; + png_fixed_point int_y_red; + png_fixed_point int_x_green; + png_fixed_point int_y_green; + png_fixed_point int_x_blue; + png_fixed_point int_y_blue; #endif - } png_info; +} png_info; - typedef png_info FAR *png_infop; - typedef png_info FAR *FAR * png_infopp; +typedef png_info FAR * png_infop; +typedef png_info FAR * FAR * png_infopp; /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) @@ -904,48 +914,48 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA /* This is for compression type. PNG 1.0-1.2 only define the single type. */ -#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ #define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE /* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ -#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ #define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE /* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ /* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ /* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ -#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ /* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ /* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ /* These are for the sRGB chunk. These values should NOT be changed. */ #define PNG_sRGB_INTENT_PERCEPTUAL 0 #define PNG_sRGB_INTENT_RELATIVE 1 #define PNG_sRGB_INTENT_SATURATION 2 #define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ /* This is for text chunks */ #define PNG_KEYWORD_MAX_LENGTH 79 @@ -969,27 +979,28 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #define PNG_INFO_oFFs 0x0100 #define PNG_INFO_tIME 0x0200 #define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using * the routines for other purposes. */ - typedef struct png_row_info_struct { - png_uint_32 width; /* width of row */ - png_uint_32 rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ - } png_row_info; - - typedef png_row_info FAR *png_row_infop; - typedef png_row_info FAR *FAR * png_row_infopp; +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; /* These are the function types for the I/O functions and for the functions * that allow the user to override the default I/O functions with his or her @@ -997,67 +1008,60 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * and error functions, while the png_rw_ptr type should match that of the * user read/write data functions. */ - typedef struct png_struct_def png_struct; - typedef png_struct FAR *png_structp; - - typedef void (PNGAPI * - png_error_ptr) PNGARG((png_structp, png_const_charp)); - typedef void (PNGAPI * - png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); - typedef void (PNGAPI * png_flush_ptr) PNGARG((png_structp)); - typedef void (PNGAPI * - png_read_status_ptr) PNGARG((png_structp, png_uint_32, int)); - typedef void (PNGAPI * - png_write_status_ptr) PNGARG((png_structp, png_uint_32, int)); +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED - typedef void (PNGAPI * - png_progressive_info_ptr) PNGARG((png_structp, png_infop)); - typedef void (PNGAPI * - png_progressive_end_ptr) PNGARG((png_structp, png_infop)); - typedef void (PNGAPI * - png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_LEGACY_SUPPORTED) - typedef void (PNGAPI * png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, - png_bytep)); +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); #endif #if defined(PNG_USER_CHUNKS_SUPPORTED) - typedef int (PNGAPI * - png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); #endif #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - typedef void (PNGAPI * png_unknown_chunk_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); #endif /* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ /* Flags for MNG supported features */ #define PNG_FLAG_MNG_EMPTY_PLTE 0x01 #define PNG_FLAG_MNG_FILTER_64 0x04 #define PNG_ALL_MNG_FEATURES 0x05 - typedef png_voidp(*png_malloc_ptr) PNGARG((png_structp, png_size_t)); - typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); /* The structure that holds the information to read and write PNG files. * The only people who need to care about what is inside of this are the @@ -1066,222 +1070,223 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * the jmp_buf. */ - struct png_struct_def { +struct png_struct_def +{ #ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf; /* used in png_error */ + jmp_buf jmpbuf; /* used in png_error */ #endif - png_error_ptr error_fn; /* function for printing errors and aborting */ - png_error_ptr warning_fn; /* function for printing warnings */ - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr read_user_transform_fn; /* user read transform */ + png_user_transform_ptr read_user_transform_fn; /* user read transform */ #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr write_user_transform_fn; /* user write transform */ + png_user_transform_ptr write_user_transform_fn; /* user write transform */ #endif /* These were added in libpng-1.0.2 */ #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - png_size_t zbuf_size; /* size of zbuf */ - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_uint_32 rowbytes; /* size of row in bytes */ - png_uint_32 irowbytes; /* size of current interlaced row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row */ - png_bytep row_buf; /* buffer to save current (unfiltered) row */ - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ - png_row_info row_info; /* used for transformation routines */ - - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte chunk_name[5]; /* null-terminated name of current chunk */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) #ifdef PNG_LEGACY_SUPPORTED - png_byte filler; /* filler byte for pixel expansion */ + png_byte filler; /* filler byte for pixel expansion */ #else - png_uint_16 filler; /* filler bytes for pixel expansion */ + png_uint_16 filler; /* filler bytes for pixel expansion */ #endif #endif #if defined(PNG_bKGD_SUPPORTED) - png_byte background_gamma_type; + png_byte background_gamma_type; # ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma; + float background_gamma; # endif - png_color_16 background; /* background color in screen gamma space */ + png_color_16 background; /* background color in screen gamma space */ #if defined(PNG_READ_GAMMA_SUPPORTED) - png_color_16 background_1; /* background normalized to gamma 1.0 */ + png_color_16 background_1; /* background normalized to gamma 1.0 */ #endif -#endif /* PNG_bKGD_SUPPORTED */ +#endif /* PNG_bKGD_SUPPORTED */ #if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_flush_ptr output_flush_fn; /* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ #ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma; /* file gamma value */ - float screen_gamma; /* screen gamma value (display_exponent) */ + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ #endif #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ + png_color_8 sig_bit; /* significant bits in each available channel */ #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit tranformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans; /* transparency values for paletted files */ - png_color_16 trans_values; /* transparency values for non-paletted files */ + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ #endif - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ #ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ # if defined(PNG_TEXT_SUPPORTED) - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) /* for the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; #endif #if defined(PNG_READ_DITHER_SUPPORTED) - png_bytep palette_lookup; /* lookup table for dithering */ - png_bytep dither_index; /* index translation for palette files */ + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ #endif #if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ + png_uint_16p hist; /* histogram */ #endif #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ #endif #if defined(PNG_TIME_RFC1123_SUPPORTED) - png_charp time_buffer; /* String to hold RFC 1123 time text */ + png_charp time_buffer; /* String to hold RFC 1123 time text */ #endif /* New members added in libpng-1.0.6 */ #ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ #endif #if defined(PNG_USER_CHUNKS_SUPPORTED) - png_voidp user_chunk_ptr; - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ #endif #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - int num_chunk_list; - png_bytep chunk_list; + int num_chunk_list; + png_bytep chunk_list; #endif /* New members added in libpng-1.0.3 */ #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_byte rgb_to_gray_status; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - png_uint_16 rgb_to_gray_blue_coeff; + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; #endif /* New member added in libpng-1.0.4 (renamed in 1.0.9) */ @@ -1290,69 +1295,70 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) /* changed from png_byte to png_uint_32 at version 1.2.0 */ #ifdef PNG_1_0_X - png_byte mng_features_permitted; + png_byte mng_features_permitted; #else - png_uint_32 mng_features_permitted; -#endif /* PNG_1_0_X */ + png_uint_32 mng_features_permitted; +#endif /* PNG_1_0_X */ #endif /* New member added in libpng-1.0.7 */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma; + png_fixed_point int_gamma; #endif /* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ #if defined(PNG_MNG_FEATURES_SUPPORTED) - png_byte filter_type; + png_byte filter_type; #endif #if defined(PNG_1_0_X) || (defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)) /* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ - png_uint_32 row_buf_size; + png_uint_32 row_buf_size; #endif /* New members added in libpng-1.2.0 */ #if !defined(PNG_1_0_X) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) - png_byte mmx_bitdepth_threshold; - png_uint_32 mmx_rowbytes_threshold; - png_uint_32 asm_flags; + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; + png_uint_32 asm_flags; #endif /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ #ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ #endif /* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ #if defined(PNG_READ_DITHER_SUPPORTED) /* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is */ - /* in the palette */ - png_bytep palette_to_index; /* which original index points to this */ - /* palette color */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index; /* which original index points to this */ + /* palette color */ #endif /* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; + png_byte compression_type; #ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; + png_uint_32 user_width_max; + png_uint_32 user_height_max; #endif - }; +}; + /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ - typedef png_structp version_1_2_8; +typedef png_structp version_1_2_8; - typedef png_struct FAR *FAR * png_structpp; +typedef png_struct FAR * FAR * png_structpp; /* Here are the function definitions most commonly used. This is not * the place to find out how to use libpng. See libpng.txt for the @@ -1361,244 +1367,218 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) */ /* Returns the version number of the library */ - extern PNG_EXPORT(png_uint_32, png_access_version_number) PNGARG((void)); +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); /* Tell lib we have already handled the first magic bytes. * Handling more than 8 bytes from the beginning of the file is an error. */ - extern PNG_EXPORT(void, png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a * PNG file. Returns zero if the supplied bytes match the 8-byte PNG * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ - extern PNG_EXPORT(int, png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); /* Simple signature checking function. This is the same as calling * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). */ - extern PNG_EXPORT(int, png_check_sig) PNGARG((png_bytep sig, int num)); +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); /* Allocate and initialize png_ptr struct for reading, and any other memory. */ - extern PNG_EXPORT(png_structp, png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); /* Allocate and initialize png_ptr struct for writing, and any other memory */ - extern PNG_EXPORT(png_structp, png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); #ifdef PNG_WRITE_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); #endif #ifdef PNG_WRITE_SUPPORTED - extern PNG_EXPORT(void, png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_uint_32 size)); +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); #endif /* Reset the compression stream */ - extern PNG_EXPORT(int, png_reset_zstream) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); /* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ #ifdef PNG_USER_MEM_SUPPORTED - extern PNG_EXPORT(png_structp, png_create_read_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); - extern PNG_EXPORT(png_structp, png_create_write_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); #endif /* Write a PNG chunk - size, type, (optional) data, CRC. */ - extern PNG_EXPORT(void, png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, - png_bytep data, - png_size_t length)); +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ - extern PNG_EXPORT(void, png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, - png_uint_32 length)); +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); /* Write the data of a PNG chunk started with png_write_chunk_start(). */ - extern PNG_EXPORT(void, png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, - png_size_t length)); +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ - extern PNG_EXPORT(void, png_write_chunk_end) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); /* Allocate and initialize the info structure */ - extern PNG_EXPORT(png_infop, png_create_info_struct) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); /* Initialize the info structure (old interface - DEPRECATED) */ - extern PNG_EXPORT(void, png_info_init) PNGARG((png_infop info_ptr)); +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); #undef png_info_init #define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ png_sizeof(png_info)); - extern PNG_EXPORT(void, png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t - png_info_struct_size)); +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); /* Writes all the PNG information before the image. */ - extern PNG_EXPORT(void, - png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - extern PNG_EXPORT(void, - png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED /* read the information before the actual image data. */ - extern PNG_EXPORT(void, png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); #endif #if defined(PNG_TIME_RFC1123_SUPPORTED) - extern PNG_EXPORT(png_charp, png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); #endif #if !defined(_WIN32_WCE) /* "time.h" functions are not supported on WindowsCE */ #if defined(PNG_WRITE_tIME_SUPPORTED) /* convert from a struct tm to png_time */ - extern PNG_EXPORT(void, png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * - ttime)); +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); /* convert from time_t to png_time. Uses gmtime() */ - extern PNG_EXPORT(void, png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_WRITE_tIME_SUPPORTED */ -#endif /* _WIN32_WCE */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ #if defined(PNG_READ_EXPAND_SUPPORTED) /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ - extern PNG_EXPORT(void, png_set_expand) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(void, - png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(void, - png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(void, - png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Use blue, green, red order for pixels. */ - extern PNG_EXPORT(void, png_set_bgr) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) /* Expand the grayscale to 24-bit RGB if necessary. */ - extern PNG_EXPORT(void, png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) /* Reduce RGB to grayscale. */ #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, - double red, - double green)); +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); #endif - extern PNG_EXPORT(void, - png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, - png_fixed_point red, - png_fixed_point - green)); - extern PNG_EXPORT(png_byte, - png_get_rgb_to_gray_status) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); #endif - extern PNG_EXPORT(void, png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp - palette)); +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - extern PNG_EXPORT(void, png_set_strip_alpha) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - extern PNG_EXPORT(void, png_set_swap_alpha) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - extern PNG_EXPORT(void, png_set_invert_alpha) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) /* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ - extern PNG_EXPORT(void, png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, - int flags)); +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); /* The values of the PNG_FILLER_ defines should NOT be changed */ #define PNG_FILLER_BEFORE 0 #define PNG_FILLER_AFTER 1 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ #if !defined(PNG_1_0_X) - extern PNG_EXPORT(void, png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, - int flags)); +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); #endif -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) /* Swap bytes in 16-bit depth files. */ - extern PNG_EXPORT(void, png_set_swap) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) /* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ - extern PNG_EXPORT(void, png_set_packing) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) /* Swap packing order of pixels in bytes. */ - extern PNG_EXPORT(void, png_set_packswap) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) /* Converts files to legal bit depths. */ - extern PNG_EXPORT(void, png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); #endif #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ defined(PNG_WRITE_INTERLACING_SUPPORTED) /* Have the code handle the interlacing. Returns the number of passes. */ - extern PNG_EXPORT(int, - png_set_interlace_handling) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) /* Invert monochrome files */ - extern PNG_EXPORT(void, png_set_invert_mono) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) /* Handle alpha and tRNS by replacing with a background color. */ #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_background) PNGARG((png_structp png_ptr, - png_color_16p - background_color, - int - background_gamma_code, - int need_expand, - double - background_gamma)); +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); #endif #define PNG_BACKGROUND_GAMMA_UNKNOWN 0 #define PNG_BACKGROUND_GAMMA_SCREEN 1 @@ -1608,25 +1588,21 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_16_TO_8_SUPPORTED) /* strip the second byte of information from a 16-bit depth file. */ - extern PNG_EXPORT(void, png_set_strip_16) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_DITHER_SUPPORTED) /* Turn on dithering, and reduce the palette to the number of colors available. */ - extern PNG_EXPORT(void, png_set_dither) PNGARG((png_structp png_ptr, - png_colorp palette, - int num_palette, - int maximum_colors, - png_uint_16p histogram, - int full_dither)); +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); #endif #if defined(PNG_READ_GAMMA_SUPPORTED) /* Handle gamma correction. Screen_gamma=(display_exponent) */ #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, - double default_file_gamma)); +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); #endif #endif @@ -1634,100 +1610,87 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) /* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ /* Deprecated and will be removed. Use png_permit_mng_features() instead. */ - extern PNG_EXPORT(void, png_permit_empty_plte) PNGARG((png_structp png_ptr, - int - empty_plte_permitted)); +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); #endif #if defined(PNG_WRITE_FLUSH_SUPPORTED) /* Set how many lines between output flushes - 0 for no flushing */ - extern PNG_EXPORT(void, - png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); /* Flush the current PNG output buffer */ - extern PNG_EXPORT(void, png_write_flush) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); #endif /* optional update palette with requested transformations */ - extern PNG_EXPORT(void, png_start_read_image) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); /* optional call to update the users info structure */ - extern PNG_EXPORT(void, png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED /* read one or more rows of image data. */ - extern PNG_EXPORT(void, png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, - png_bytepp display_row, - png_uint_32 num_rows)); +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); #endif #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED /* read a row of data. */ - extern PNG_EXPORT(void, png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); #endif #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED /* read the whole image into memory at once. */ - extern PNG_EXPORT(void, png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); #endif /* write a row of image data */ - extern PNG_EXPORT(void, png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); /* write a few rows of image data */ - extern PNG_EXPORT(void, png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, - png_uint_32 num_rows)); +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); /* write the image data */ - extern PNG_EXPORT(void, png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); /* writes the end of the PNG file. */ - extern PNG_EXPORT(void, png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED /* read the end of the PNG file. */ - extern PNG_EXPORT(void, png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); #endif /* free any memory associated with the png_info_struct */ - extern PNG_EXPORT(void, - png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp - info_ptr_ptr)); +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); /* free any memory associated with the png_struct and the png_info_structs */ - extern PNG_EXPORT(void, png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, - png_infopp - info_ptr_ptr, - png_infopp - end_info_ptr_ptr)); +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); /* free all memory used by the read (old method - NOT DLL EXPORTED) */ - extern void png_read_destroy - PNGARG((png_structp png_ptr, png_infop info_ptr, - png_infop end_info_ptr)); +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); /* free any memory associated with the png_struct and the png_info_structs */ - extern PNG_EXPORT(void, png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); /* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ - extern void png_write_destroy PNGARG((png_structp png_ptr)); +extern void png_write_destroy PNGARG((png_structp png_ptr)); /* set the libpng method of handling chunk CRC errors */ - extern PNG_EXPORT(void, png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, - int ancil_action)); +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); /* Values for png_set_crc_action() to say how to handle CRC errors in * ancillary and critical chunks, and whether to use the data contained @@ -1738,12 +1701,12 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * * value action:critical action:ancillary */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ /* These functions give the user control over the scan-line filtering in * libpng and the compression methods used by zlib. These functions are @@ -1756,9 +1719,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* set the filtering method(s) used by libpng. Currently, the only valid * value for "method" is 0. */ - extern PNG_EXPORT(void, - png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); /* Flags for png_set_filter() to say which filters to use. The flags * are chosen so that they don't conflict with real filter types @@ -1784,7 +1746,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #define PNG_FILTER_VALUE_PAETH 4 #define PNG_FILTER_VALUE_LAST 5 -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ /* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ * defines, either the default (minimum-sum-of-absolute-differences), or * the experimental method (weighted-minimum-sum-of-absolute-differences). @@ -1814,24 +1776,19 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * to the UNWEIGHTED method, but with added encoding time/computation. */ #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, - png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, - int num_weights, - png_doublep - filter_weights, - png_doublep - filter_costs)); +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); #endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ /* Heuristic used for row filter selection. These defines should NOT be * changed. */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ /* Set the library compression level. Currently, valid values range from * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 @@ -1840,22 +1797,20 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * for PNG images, and do considerably fewer caclulations. In the future, * these values may not correspond directly to the zlib compression levels. */ - extern PNG_EXPORT(void, - png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); - extern PNG_EXPORT(void, png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); - extern PNG_EXPORT(void, png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); - extern PNG_EXPORT(void, png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); - extern PNG_EXPORT(void, - png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); /* These next functions are called for input/output, memory, and error * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, @@ -1868,8 +1823,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #if !defined(PNG_NO_STDIO) /* Initialize the input/output for the PNG file to the default functions. */ - extern PNG_EXPORT(void, - png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); #endif /* Replace the (error and abort), and warning functions with user @@ -1880,167 +1834,126 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * default function will be used. */ - extern PNG_EXPORT(void, png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, - png_error_ptr error_fn, - png_error_ptr - warning_fn)); +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); /* Return the user pointer associated with the error functions */ - extern PNG_EXPORT(png_voidp, - png_get_error_ptr) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); /* Replace the default data output functions with a user supplied one(s). * If buffered output is not used, then output_flush_fn can be set to NULL. * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time * output_flush_fn will be ignored (and thus can be NULL). */ - extern PNG_EXPORT(void, png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, - png_rw_ptr write_data_fn, - png_flush_ptr - output_flush_fn)); +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); /* Replace the default data input function with a user supplied one. */ - extern PNG_EXPORT(void, png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, - png_rw_ptr read_data_fn)); +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); /* Return the user pointer associated with the I/O functions */ - extern PNG_EXPORT(png_voidp, png_get_io_ptr) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(void, png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr - read_row_fn)); +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); - extern PNG_EXPORT(void, - png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr - write_row_fn)); +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); #ifdef PNG_USER_MEM_SUPPORTED /* Replace the default memory allocation functions with user supplied one(s). */ - extern PNG_EXPORT(void, png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, - png_malloc_ptr malloc_fn, - png_free_ptr free_fn)); +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); /* Return the user pointer associated with the memory functions */ - extern PNG_EXPORT(png_voidp, png_get_mem_ptr) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_LEGACY_SUPPORTED) - extern PNG_EXPORT(void, png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, - png_user_transform_ptr - read_user_transform_fn)); +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_LEGACY_SUPPORTED) - extern PNG_EXPORT(void, png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, - png_user_transform_ptr - write_user_transform_fn)); +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_LEGACY_SUPPORTED) - extern PNG_EXPORT(void, png_set_user_transform_info) PNGARG((png_structp - png_ptr, - png_voidp - user_transform_ptr, - int - user_transform_depth, - int - user_transform_channels)); +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); /* Return the user pointer associated with the user transform functions */ - extern PNG_EXPORT(png_voidp, png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); #endif #ifdef PNG_USER_CHUNKS_SUPPORTED - extern PNG_EXPORT(void, - png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp - user_chunk_ptr, - png_user_chunk_ptr - read_user_chunk_fn)); - extern PNG_EXPORT(png_voidp, - png_get_user_chunk_ptr) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); #endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED /* Sets the function callbacks for the push reader, and a pointer to a * user-defined structure available to the callback functions. */ - extern PNG_EXPORT(void, - png_set_progressive_read_fn) PNGARG((png_structp png_ptr, - png_voidp - progressive_ptr, - png_progressive_info_ptr - info_fn, - png_progressive_row_ptr - row_fn, - png_progressive_end_ptr - end_fn)); +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); /* returns the user pointer associated with the push read functions */ - extern PNG_EXPORT(png_voidp, png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); /* function to be called when data becomes available */ - extern PNG_EXPORT(void, png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_bytep buffer, - png_size_t buffer_size)); +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); /* function that combines rows. Not very much different than the * png_combine_row() call. Is this even used????? */ - extern PNG_EXPORT(void, - png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, - png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - extern PNG_EXPORT(png_voidp, png_malloc) PNGARG((png_structp png_ptr, - png_uint_32 size)); +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); #if defined(PNG_1_0_X) # define png_malloc_warn png_malloc #else /* Added at libpng version 1.2.4 */ - extern PNG_EXPORT(png_voidp, png_malloc_warn) PNGARG((png_structp png_ptr, - png_uint_32 size)); +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)); #endif /* frees a pointer allocated by png_malloc() */ - extern PNG_EXPORT(void, - png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); #if defined(PNG_1_0_X) /* Function to allocate memory for zlib. */ - extern PNG_EXPORT(voidpf, png_zalloc) PNGARG((voidpf png_ptr, uInt items, - uInt size)); +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); /* Function to free memory for zlib */ - extern PNG_EXPORT(void, png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); #endif /* Free data that was allocated internally */ - extern PNG_EXPORT(void, png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 free_me, - int num)); +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); #ifdef PNG_FREE_ME_SUPPORTED /* Reassign responsibility for freeing existing data, whether allocated * by libpng or by the application */ - extern PNG_EXPORT(void, png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int freer, - png_uint_32 mask)); +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); #endif /* assignments for png_data_freer */ #define PNG_DESTROY_WILL_FREE_DATA 1 @@ -2059,50 +1972,41 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #define PNG_FREE_TRNS 0x2000 #define PNG_FREE_TEXT 0x4000 #define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED - extern PNG_EXPORT(png_voidp, - png_malloc_default) PNGARG((png_structp png_ptr, - png_uint_32 size)); - extern PNG_EXPORT(void, - png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); #endif - extern PNG_EXPORT(png_voidp, png_memcpy_check) PNGARG((png_structp png_ptr, - png_voidp s1, - png_voidp s2, - png_uint_32 size)); +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); - extern PNG_EXPORT(png_voidp, png_memset_check) PNGARG((png_structp png_ptr, - png_voidp s1, - int value, - png_uint_32 size)); +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); -#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ - extern void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ /* Fatal error in PNG image of libpng - can't continue */ - extern PNG_EXPORT(void, png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); /* The same, but the chunk name is prepended to the error string. */ - extern PNG_EXPORT(void, png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp - error_message)); +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); /* Non-fatal error in libpng. Can continue, but may have a problem. */ - extern PNG_EXPORT(void, png_warning) PNGARG((png_structp png_ptr, - png_const_charp - warning_message)); +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); /* Non-fatal error in libpng, chunk name is prepended to message. */ - extern PNG_EXPORT(void, png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp - warning_message)); +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); /* The png_set_ functions are for storing values in the png_info_struct. * Similarly, the png_get_ calls are used to read values from the @@ -2117,379 +2021,256 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * png_info_struct. */ /* Returns "flag" if chunk data is valid in info_ptr. */ - extern PNG_EXPORT(png_uint_32, png_get_valid) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 flag)); +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ - extern PNG_EXPORT(png_uint_32, - png_get_rowbytes) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); #if defined(PNG_INFO_IMAGE_SUPPORTED) /* Returns row_pointers, which is an array of pointers to scanlines that was returned from png_read_png(). */ - extern PNG_EXPORT(png_bytepp, png_get_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); /* Set row_pointers, which is an array of pointers to scanlines for use by png_write_png(). */ - extern PNG_EXPORT(void, png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_bytepp row_pointers)); +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); #endif /* Returns number of color channels in image. */ - extern PNG_EXPORT(png_byte, png_get_channels) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); #ifdef PNG_EASY_ACCESS_SUPPORTED /* Returns image width in pixels. */ - extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image height in pixels. */ - extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image bit_depth. */ - extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp - png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image color_type. */ - extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image filter_type. */ - extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image interlace_type. */ - extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image compression_type. */ - extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns image resolution in pixels per meter, from pHYs chunk data. */ - extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); - extern PNG_EXPORT(png_uint_32, - png_get_x_pixels_per_meter) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - extern PNG_EXPORT(png_uint_32, - png_get_y_pixels_per_meter) PNGARG((png_structp png_ptr, - png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); /* Returns pixel aspect ratio, computed from pHYs chunk data. */ #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); #endif /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ - extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp - png_ptr, - png_infop - info_ptr)); - extern PNG_EXPORT(png_int_32, - png_get_y_offset_pixels) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - extern PNG_EXPORT(png_int_32, - png_get_x_offset_microns) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - extern PNG_EXPORT(png_int_32, - png_get_y_offset_microns) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ /* Returns pointer to signature string read from PNG header */ - extern PNG_EXPORT(png_bytep, png_get_signature) PNGARG((png_structp png_ptr, - png_infop - info_ptr)); +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); #if defined(PNG_bKGD_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_color_16p * - background)); +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); #endif #if defined(PNG_bKGD_SUPPORTED) - extern PNG_EXPORT(void, png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_color_16p background)); +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); #endif #if defined(PNG_cHRM_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_get_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, - double *white_x, - double *white_y, - double *red_x, - double *red_y, - double *green_x, - double *green_y, - double *blue_x, - double *blue_y)); +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED - extern PNG_EXPORT(png_uint_32, - png_get_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_fixed_point * int_white_x, - png_fixed_point * int_white_y, - png_fixed_point * int_red_x, - png_fixed_point * int_red_y, - png_fixed_point * int_green_x, - png_fixed_point * int_green_y, - png_fixed_point * int_blue_x, - png_fixed_point * - int_blue_y)); +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); #endif #endif #if defined(PNG_cHRM_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, - double white_x, - double white_y, double red_x, - double red_y, double green_x, - double green_y, double blue_x, - double blue_y)); +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_fixed_point - int_white_x, - png_fixed_point - int_white_y, - png_fixed_point - int_red_x, - png_fixed_point - int_red_y, - png_fixed_point - int_green_x, - png_fixed_point - int_green_y, - png_fixed_point - int_blue_x, - png_fixed_point - int_blue_y)); +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); #endif #endif #if defined(PNG_gAMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, - double *file_gamma)); +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); #endif - extern PNG_EXPORT(png_uint_32, - png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_fixed_point * - int_file_gamma)); +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); #endif #if defined(PNG_gAMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, - double file_gamma)); +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); #endif - extern PNG_EXPORT(void, png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_fixed_point - int_file_gamma)); +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); #endif #if defined(PNG_hIST_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_16p * hist)); +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); #endif #if defined(PNG_hIST_SUPPORTED) - extern PNG_EXPORT(void, png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_16p hist)); -#endif - - extern PNG_EXPORT(png_uint_32, png_get_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 * width, - png_uint_32 * height, - int *bit_depth, - int *color_type, - int *interlace_method, - int - *compression_method, - int *filter_method)); - - extern PNG_EXPORT(void, png_set_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 width, - png_uint_32 height, - int bit_depth, int color_type, - int interlace_method, - int compression_method, - int filter_method)); +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); #if defined(PNG_oFFs_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_int_32 * offset_x, - png_int_32 * offset_y, - int *unit_type)); +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); #endif #if defined(PNG_oFFs_SUPPORTED) - extern PNG_EXPORT(void, png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_int_32 offset_x, - png_int_32 offset_y, - int unit_type)); +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); #endif #if defined(PNG_pCAL_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_charp * purpose, - png_int_32 * X0, - png_int_32 * X1, - int *type, - int *nparams, - png_charp * units, - png_charpp * params)); +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); #endif #if defined(PNG_pCAL_SUPPORTED) - extern PNG_EXPORT(void, png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_charp purpose, - png_int_32 X0, png_int_32 X1, - int type, int nparams, - png_charp units, - png_charpp params)); +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); #endif #if defined(PNG_pHYs_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 * res_x, - png_uint_32 * res_y, - int *unit_type)); +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); #endif #if defined(PNG_pHYs_SUPPORTED) - extern PNG_EXPORT(void, png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 res_x, - png_uint_32 res_y, - int unit_type)); +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); #endif - extern PNG_EXPORT(png_uint_32, png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_colorp * palette, - int *num_palette)); +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); - extern PNG_EXPORT(void, png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_colorp palette, - int num_palette)); +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); #if defined(PNG_sBIT_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_color_8p * - sig_bit)); +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); #endif #if defined(PNG_sBIT_SUPPORTED) - extern PNG_EXPORT(void, png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_color_8p sig_bit)); +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); #endif #if defined(PNG_sRGB_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int *intent)); +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); #endif #if defined(PNG_sRGB_SUPPORTED) - extern PNG_EXPORT(void, png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int intent)); - extern PNG_EXPORT(void, - png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int intent)); +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); #endif #if defined(PNG_iCCP_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_charpp name, - int *compression_type, - png_charpp profile, - png_uint_32 * - proflen)); - /* Note to maintainer: profile should be png_bytepp */ +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ #endif #if defined(PNG_iCCP_SUPPORTED) - extern PNG_EXPORT(void, png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_charp name, - int compression_type, - png_charp profile, - png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ #endif #if defined(PNG_sPLT_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_sPLT_tpp entries)); +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); #endif #if defined(PNG_sPLT_SUPPORTED) - extern PNG_EXPORT(void, png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_sPLT_tp entries, - int nentries)); +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); #endif #if defined(PNG_TEXT_SUPPORTED) /* png_get_text also returns the number of text chunks in *num_text */ - extern PNG_EXPORT(png_uint_32, png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_textp * text_ptr, - int *num_text)); +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); #endif /* @@ -2501,39 +2282,30 @@ by png_write_png(). */ */ #if defined(PNG_TEXT_SUPPORTED) - extern PNG_EXPORT(void, png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_textp text_ptr, - int num_text)); +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); #endif #if defined(PNG_tIME_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_timep * mod_time)); +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); #endif #if defined(PNG_tIME_SUPPORTED) - extern PNG_EXPORT(void, png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_timep mod_time)); +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); #endif #if defined(PNG_tRNS_SUPPORTED) - extern PNG_EXPORT(png_uint_32, png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_bytep * trans, - int *num_trans, - png_color_16p * - trans_values)); +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); #endif #if defined(PNG_tRNS_SUPPORTED) - extern PNG_EXPORT(void, png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_bytep trans, - int num_trans, - png_color_16p trans_values)); +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); #endif #if defined(PNG_tRNS_SUPPORTED) @@ -2541,35 +2313,26 @@ by png_write_png(). */ #if defined(PNG_sCAL_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int *unit, - double *width, - double *height)); +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); #else #ifdef PNG_FIXED_POINT_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int *unit, - png_charpp swidth, - png_charpp sheight)); +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); #endif #endif -#endif /* PNG_sCAL_SUPPORTED */ +#endif /* PNG_sCAL_SUPPORTED */ #if defined(PNG_sCAL_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, - double width, double height)); +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED - extern PNG_EXPORT(void, png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int unit, png_charp swidth, - png_charp sheight)); +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); #endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) /* provide a list of chunks and how they are to be handled, if the built-in @@ -2581,51 +2344,36 @@ by png_write_png(). */ = 2: keep only if safe-to-copy = 3: keep even if unsafe-to-copy */ - extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, - int keep, - png_bytep - chunk_list, - int - num_chunks)); - extern PNG_EXPORT(void, - png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_unknown_chunkp - unknowns, - int num_unknowns)); - extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); - extern PNG_EXPORT(png_uint_32, png_get_unknown_chunks) PNGARG((png_structp - png_ptr, - png_infop - info_ptr, - png_unknown_chunkpp - entries)); +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); #endif #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - PNG_EXPORT(int, - png_handle_as_unknown) PNGARG((png_structp png_ptr, - png_bytep chunk_name)); +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); #endif /* Png_free_data() will turn off the "valid" flag for anything it frees. If you need to turn it off for a chunk that your application has freed, you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ - extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int mask)); +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); #if defined(PNG_INFO_IMAGE_SUPPORTED) /* The "params" pointer is currently not used and is for future expansion. */ - extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); - extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); #endif /* Define PNG_DEBUG at compile time for debugging information. Higher @@ -2642,10 +2390,10 @@ by png_write_png(). */ #define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) #define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) #endif -#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#else /* PNG_DEBUG_FILE || !_MSC_VER */ #ifndef PNG_DEBUG_FILE #define PNG_DEBUG_FILE stderr -#endif /* PNG_DEBUG_FILE */ +#endif /* PNG_DEBUG_FILE */ #if (PNG_DEBUG > 1) #define png_debug(l,m) \ { \ @@ -2665,10 +2413,10 @@ by png_write_png(). */ fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ } -#endif /* (PNG_DEBUG > 1) */ -#endif /* _MSC_VER */ -#endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ +#endif /* (PNG_DEBUG > 1) */ +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ #ifndef png_debug #define png_debug(l, m) #endif @@ -2679,22 +2427,16 @@ by png_write_png(). */ #define png_debug2(l, m, p1, p2) #endif - extern PNG_EXPORT(png_bytep, png_sig_bytes) PNGARG((void)); +extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void)); - extern PNG_EXPORT(png_charp, - png_get_copyright) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(png_charp, - png_get_header_ver) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(png_charp, - png_get_header_version) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(png_charp, - png_get_libpng_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); #ifdef PNG_MNG_FEATURES_SUPPORTED - extern PNG_EXPORT(png_uint_32, png_permit_mng_features) PNGARG((png_structp - png_ptr, - png_uint_32 - mng_features_permitted)); +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); #endif /* For use in png_set_keep_unknown, added to version 1.2.6 */ @@ -2705,15 +2447,15 @@ by png_write_png(). */ /* Added to version 1.2.0 */ #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ #define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 #define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 #define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 #define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 #define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 #define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 -#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ #define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ | PNG_ASM_FLAG_MMX_READ_INTERLACE \ @@ -2733,64 +2475,58 @@ by png_write_png(). */ #if !defined(PNG_1_0_X) /* pngget.c */ - extern PNG_EXPORT(png_uint_32, png_get_mmx_flagmask) - PNGARG((int flag_select, int *compilerID)); +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); /* pngget.c */ - extern PNG_EXPORT(png_uint_32, png_get_asm_flagmask) - PNGARG((int flag_select)); +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); /* pngget.c */ - extern PNG_EXPORT(png_uint_32, png_get_asm_flags) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); /* pngget.c */ - extern PNG_EXPORT(png_byte, png_get_mmx_bitdepth_threshold) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); /* pngget.c */ - extern PNG_EXPORT(png_uint_32, png_get_mmx_rowbytes_threshold) - PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); /* pngset.c */ - extern PNG_EXPORT(void, png_set_asm_flags) - PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); /* pngset.c */ - extern PNG_EXPORT(void, png_set_mmx_thresholds) - PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold)); +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); -#endif /* PNG_1_0_X */ -#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ +#endif /* PNG_1_0_X */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ #if !defined(PNG_1_0_X) /* png.c, pnggccrd.c, or pngvcrd.c */ - extern PNG_EXPORT(int, png_mmx_support) PNGARG((void)); +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); /* Strip the prepended error numbers ("#nnn ") from error and warning * messages before passing them to the error or warning handler. */ #ifdef PNG_ERROR_NUMBERS_SUPPORTED - extern PNG_EXPORT(void, png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, - png_uint_32 - strip_mode)); +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); #endif -#endif /* PNG_1_0_X */ +#endif /* PNG_1_0_X */ /* Added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED - extern PNG_EXPORT(void, png_set_user_limits) PNGARG((png_structp - png_ptr, - png_uint_32 - user_width_max, - png_uint_32 - user_height_max)); - extern PNG_EXPORT(png_uint_32, - png_get_user_width_max) PNGARG((png_structp png_ptr)); - extern PNG_EXPORT(png_uint_32, - png_get_user_height_max) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); #endif /* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ @@ -2808,7 +2544,7 @@ by png_write_png(). */ * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] */ - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ # define png_composite(composite, fg, alpha, bg) \ { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ @@ -2822,7 +2558,7 @@ by png_write_png(). */ (png_uint_32)(alpha)) + (png_uint_32)32768L); \ (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } -#else /* standard method using integer division */ +#else /* standard method using integer division */ # define png_composite(composite, fg, alpha, bg) \ (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ @@ -2834,7 +2570,7 @@ by png_write_png(). */ (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ (png_uint_32)32767) / (png_uint_32)65535L) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ /* These next functions are used internally in the code. They generally * shouldn't be used unless you are writing code to add or replace some @@ -2871,7 +2607,7 @@ by png_write_png(). */ #define PNG_DITHER 0x0040 #define PNG_BACKGROUND 0x0080 #define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ + /* 0x0200 unused */ #define PNG_16_TO_8 0x0400 #define PNG_RGBA 0x0800 #define PNG_EXPAND 0x1000 @@ -2885,15 +2621,15 @@ by png_write_png(). */ #define PNG_USER_TRANSFORM 0x100000L #define PNG_RGB_TO_GRAY_ERR 0x200000L #define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ /* flags for png_create_struct */ #define PNG_STRUCT_PNG 0x0001 @@ -2927,16 +2663,16 @@ by png_write_png(). */ #define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L #define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L #define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ - /* 0x800000L unused */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x800000L unused */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) @@ -2970,11 +2706,11 @@ by png_write_png(). */ #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) /* place to hold the signature string for a PNG file. */ #ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR(const png_byte FARDATA) png_sig[8]; + PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8]; #else #define png_sig png_sig_bytes(NULL) #endif -#endif /* PNG_NO_EXTERN */ +#endif /* PNG_NO_EXTERN */ /* Constant strings for known chunk types. If you need to add a chunk, * define the name here, and add an invocation of the macro in png.c and @@ -3003,28 +2739,29 @@ by png_write_png(). */ #define PNG_zTXt const png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} #ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR(const png_byte FARDATA) png_IHDR[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_IDAT[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_IEND[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_PLTE[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_bKGD[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_cHRM[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_gAMA[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_hIST[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_iCCP[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_iTXt[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_oFFs[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_pCAL[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_sCAL[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_pHYs[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_sBIT[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_sPLT[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_sRGB[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_tEXt[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_tIME[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_tRNS[5]; - PNG_EXPORT_VAR(const png_byte FARDATA) png_zTXt[5]; -#endif /* PNG_USE_GLOBAL_ARRAYS */ +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + /* Inline macros to do direct reads of bytes from the input buffer. These * require that you are using an architecture that uses PNG byte ordering @@ -3042,345 +2779,308 @@ by png_write_png(). */ # define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) #else # if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) - PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf)); +PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf)); # endif - PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf)); - PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf)); -#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ - PNG_EXTERN png_uint_32 png_get_uint_31 PNGARG((png_structp png_ptr, - png_bytep buf)); +PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf)); +PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +PNG_EXTERN png_uint_32 png_get_uint_31 PNGARG((png_structp png_ptr, + png_bytep buf)); /* Initialize png_ptr struct for reading, and allocate any other memory. * (old interface - DEPRECATED - use png_create_read_struct instead). */ - extern PNG_EXPORT(void, png_read_init) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); #undef png_read_init #define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); - extern PNG_EXPORT(void, png_read_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp - user_png_ver, - png_size_t - png_struct_size)); - extern PNG_EXPORT(void, - png_read_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, - png_size_t png_struct_size, - png_size_t png_info_size)); +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); /* Initialize png_ptr struct for writing, and allocate any other memory. * (old interface - DEPRECATED - use png_create_write_struct instead). */ - extern PNG_EXPORT(void, png_write_init) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); #undef png_write_init #define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); - extern PNG_EXPORT(void, png_write_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp - user_png_ver, - png_size_t - png_struct_size)); - extern PNG_EXPORT(void, - png_write_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, - png_size_t png_struct_size, - png_size_t png_info_size)); +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); /* Allocate memory for an internal libpng struct */ - PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); /* Free memory from internal libpng struct */ - PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr - malloc_fn, - png_voidp mem_ptr)); - PNG_EXTERN void png_destroy_struct_2 - PNGARG((png_voidp struct_ptr, png_free_ptr free_fn, png_voidp mem_ptr)); +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); /* Free any memory that info_ptr points to and reset struct. */ - PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); #ifndef PNG_1_0_X /* Function to allocate memory for zlib. */ - PNG_EXTERN voidpf png_zalloc - PNGARG((voidpf png_ptr, uInt items, uInt size)); +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); /* Function to free memory for zlib */ - PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); #ifdef PNG_SIZE_T /* Function to convert a sizeof an item to png_sizeof item */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); #endif /* Next four functions are used internally as callbacks. PNGAPI is required * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, - png_size_t length)); +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED - PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, - png_size_t length)); +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); #endif - PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, - png_size_t length)); +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); #if defined(PNG_WRITE_FLUSH_SUPPORTED) #if !defined(PNG_NO_STDIO) - PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); #endif #endif -#else /* PNG_1_0_X */ +#else /* PNG_1_0_X */ #ifdef PNG_PROGRESSIVE_READ_SUPPORTED - PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, - png_size_t length)); +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); #endif -#endif /* PNG_1_0_X */ +#endif /* PNG_1_0_X */ /* Reset the CRC variable */ - PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); /* Write the "data" buffer to whatever output you are using. */ - PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); /* Read data from whatever input you are using into the "data" buffer */ - PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); /* Read bytes into buf, and update png_ptr->crc */ - PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, - png_size_t length)); +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); /* Decompress data in a chunk that uses compression */ #if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) - PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, - int comp_type, - png_charp chunkdata, - png_size_t chunklength, - png_size_t prefix_length, - png_size_t * - data_length)); +PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); #endif /* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ - PNG_EXTERN int png_crc_finish - PNGARG((png_structp png_ptr, png_uint_32 skip)); +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); /* Read the CRC from the file and compare it to the libpng calculated CRC */ - PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); /* Calculate the CRC over a section of data. Note that we are only * passing a maximum of 64K on systems that have this as a memory limit, * since this is the maximum buffer size we can specify. */ - PNG_EXTERN void png_calculate_crc - PNGARG((png_structp png_ptr, png_bytep ptr, png_size_t length)); +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); #if defined(PNG_WRITE_FLUSH_SUPPORTED) - PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); #endif + /* Place a 32-bit number into a buffer in PNG byte order (big-endian). * The only currently known PNG chunks that use signed numbers are * the ancillary extension chunks, oFFs and pCAL. */ - PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i)); +PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i)); #if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED) - PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i)); +PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i)); #endif /* Place a 16-bit number into a buffer in PNG byte order. * The parameter is declared unsigned int, not png_uint_16, * just to avoid potential problems on pre-ANSI C compilers. */ - PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i)); +PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i)); /* simple function to write the signature */ - PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); /* write various chunks */ /* Write the IHDR chunk, and update the png_struct with the necessary * information. */ - PNG_EXTERN void png_write_IHDR - PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, - int bit_depth, int color_type, int compression_method, - int filter_method, int interlace_method)); +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); - PNG_EXTERN void png_write_PLTE - PNGARG((png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)); +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); - PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); - PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); #if defined(PNG_WRITE_gAMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - PNG_EXTERN void png_write_gAMA - PNGARG((png_structp png_ptr, double file_gamma)); +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED - PNG_EXTERN void png_write_gAMA_fixed - PNGARG((png_structp png_ptr, png_fixed_point file_gamma)); +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); #endif #endif #if defined(PNG_WRITE_sBIT_SUPPORTED) - PNG_EXTERN void png_write_sBIT - PNGARG((png_structp png_ptr, png_color_8p sbit, int color_type)); +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); #endif #if defined(PNG_WRITE_cHRM_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED - PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, - double white_x, double white_y, - double red_x, double red_y, - double green_x, double green_y, - double blue_x, double blue_y)); +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED - PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, - png_fixed_point int_white_x, - png_fixed_point int_white_y, - png_fixed_point int_red_x, - png_fixed_point int_red_y, - png_fixed_point int_green_x, - png_fixed_point int_green_y, - png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); #endif #endif #if defined(PNG_WRITE_sRGB_SUPPORTED) - PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, int intent)); +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); #endif #if defined(PNG_WRITE_iCCP_SUPPORTED) - PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_charp name, int compression_type, - png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ #endif #if defined(PNG_WRITE_sPLT_SUPPORTED) - PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, - png_sPLT_tp palette)); +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); #endif #if defined(PNG_WRITE_tRNS_SUPPORTED) - PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, - png_color_16p values, int number, - int color_type)); +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); #endif #if defined(PNG_WRITE_bKGD_SUPPORTED) - PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_color_16p values, - int color_type)); +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); #endif #if defined(PNG_WRITE_hIST_SUPPORTED) - PNG_EXTERN void png_write_hIST - PNGARG((png_structp png_ptr, png_uint_16p hist, int num_hist)); +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); #endif #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) - PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, - png_charp key, - png_charpp new_key)); +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); #endif #if defined(PNG_WRITE_tEXt_SUPPORTED) - PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, - png_size_t text_len)); +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); #endif #if defined(PNG_WRITE_zTXt_SUPPORTED) - PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len, - int compression)); +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); #endif #if defined(PNG_WRITE_iTXt_SUPPORTED) - PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_charp key, - png_charp lang, png_charp lang_key, - png_charp text)); +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); #endif -#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ - PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_textp text_ptr, int num_text)); +#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); #endif #if defined(PNG_WRITE_oFFs_SUPPORTED) - PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, - png_int_32 x_offset, - png_int_32 y_offset, int unit_type)); +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); #endif #if defined(PNG_WRITE_pCAL_SUPPORTED) - PNG_EXTERN void png_write_pCAL - PNGARG((png_structp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_charp units, - png_charpp params)); +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); #endif #if defined(PNG_WRITE_pHYs_SUPPORTED) - PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, - png_uint_32 x_pixels_per_unit, - png_uint_32 y_pixels_per_unit, - int unit_type)); +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); #endif #if defined(PNG_WRITE_tIME_SUPPORTED) - PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_timep mod_time)); +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); #endif #if defined(PNG_WRITE_sCAL_SUPPORTED) #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) - PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, - int unit, double width, - double height)); +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); #else #ifdef PNG_FIXED_POINT_SUPPORTED - PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_charp width, - png_charp height)); +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); #endif #endif #endif /* Called when finished processing a row of data */ - PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); /* Internal use only. Called before first row of data */ - PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); #if defined(PNG_READ_GAMMA_SUPPORTED) - PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); #endif /* combine a row of data, dealing with alpha, etc. if requested */ - PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int mask)); +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); #if defined(PNG_READ_INTERLACING_SUPPORTED) /* expand an interlaced row */ @@ -3388,172 +3088,153 @@ by png_write_png(). */ PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, png_bytep row, int pass, png_uint_32 transformations)); */ - PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); #endif /* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ #if defined(PNG_WRITE_INTERLACING_SUPPORTED) /* grab pixels out of a row for an interlaced pass */ - PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass)); +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); #endif /* unfilter a row */ - PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, - png_row_infop row_info, - png_bytep row, - png_bytep prev_row, - int filter)); +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); /* Choose the best filter to use and filter the row data */ - PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, - png_row_infop row_info)); +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); /* Write out the filtered row. */ - PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, - png_bytep filtered_row)); +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); /* finish a row while reading, dealing with interlacing passes, etc. */ - PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); /* initialize the row buffers, etc. */ - PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); /* optional call to update the users info structure */ - PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); /* these are the functions that do the transformations */ #if defined(PNG_READ_FILLER_SUPPORTED) - PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, - png_bytep row, - png_uint_32 filler, - png_uint_32 flags)); +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, - png_bytep row, - png_uint_32 flags)); +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); #endif #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) - PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) - PNG_EXTERN void png_do_packswap - PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop - row_info, png_bytep row)); +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_READ_PACK_SUPPORTED) - PNG_EXTERN void png_do_unpack - PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) - PNG_EXTERN void png_do_unshift - PNGARG((png_row_infop row_info, png_bytep row, png_color_8p sig_bits)); +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) - PNG_EXTERN void png_do_invert - PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) - PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_READ_DITHER_SUPPORTED) - PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, - png_bytep row, - png_bytep palette_lookup, - png_bytep dither_lookup)); +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); # if defined(PNG_CORRECT_PALETTE_SUPPORTED) - PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, - int num_palette)); +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); # endif #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) - PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); #endif #if defined(PNG_WRITE_PACK_SUPPORTED) - PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth)); +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) - PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p bit_depth)); +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED) - PNG_EXTERN void png_do_background - PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background, - png_color_16p background_1, png_bytep gamma_table, - png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift)); +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); #else - PNG_EXTERN void png_do_background - PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background)); +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)); #endif #endif #if defined(PNG_READ_GAMMA_SUPPORTED) - PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, - png_bytep gamma_table, - png_uint_16pp gamma_16_table, - int gamma_shift)); +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); #endif #if defined(PNG_READ_EXPAND_SUPPORTED) - PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, - png_colorp palette, - png_bytep trans, - int num_trans)); - PNG_EXTERN void png_do_expand - PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_value)); +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); #endif /* The following decodes the appropriate chunks, and does error correction, @@ -3561,185 +3242,178 @@ PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, */ /* decode the IHDR chunk */ - PNG_EXTERN void png_handle_IHDR - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); - PNG_EXTERN void png_handle_PLTE - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); - PNG_EXTERN void png_handle_IEND - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #if defined(PNG_READ_bKGD_SUPPORTED) - PNG_EXTERN void png_handle_bKGD - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_cHRM_SUPPORTED) - PNG_EXTERN void png_handle_cHRM - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_gAMA_SUPPORTED) - PNG_EXTERN void png_handle_gAMA - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_hIST_SUPPORTED) - PNG_EXTERN void png_handle_hIST - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_iCCP_SUPPORTED) - extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_iCCP_SUPPORTED */ +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_EXTERN void png_handle_iTXt - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_oFFs_SUPPORTED) - PNG_EXTERN void png_handle_oFFs - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_pCAL_SUPPORTED) - PNG_EXTERN void png_handle_pCAL - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_pHYs_SUPPORTED) - PNG_EXTERN void png_handle_pHYs - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_sBIT_SUPPORTED) - PNG_EXTERN void png_handle_sBIT - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_sCAL_SUPPORTED) - PNG_EXTERN void png_handle_sCAL - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_sPLT_SUPPORTED) - extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_sPLT_SUPPORTED */ +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ #if defined(PNG_READ_sRGB_SUPPORTED) - PNG_EXTERN void png_handle_sRGB - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_EXTERN void png_handle_tEXt - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_tIME_SUPPORTED) - PNG_EXTERN void png_handle_tIME - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_tRNS_SUPPORTED) - PNG_EXTERN void png_handle_tRNS - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_EXTERN void png_handle_zTXt - PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); #endif - PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 length)); +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); - PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_bytep chunk_name)); +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); /* handle the transformations for reading and writing */ - PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED - PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); - PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); - PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); - PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, - png_size_t buffer_length)); - PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, - png_size_t buffer_length)); - PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); - PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 length)); - PNG_EXTERN void png_push_have_info - PNGARG((png_structp png_ptr, png_infop info_ptr)); - PNG_EXTERN void png_push_have_end - PNGARG((png_structp png_ptr, png_infop info_ptr)); - PNG_EXTERN void png_push_have_row - PNGARG((png_structp png_ptr, png_bytep row)); - PNG_EXTERN void png_push_read_end - PNGARG((png_structp png_ptr, png_infop info_ptr)); - PNG_EXTERN void png_process_some_data - PNGARG((png_structp png_ptr, png_infop info_ptr)); - PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 length)); - PNG_EXTERN void png_push_read_tEXt - PNGARG((png_structp png_ptr, png_infop info_ptr)); +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 length)); - PNG_EXTERN void png_push_read_zTXt - PNGARG((png_structp png_ptr, png_infop info_ptr)); +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); #endif #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, - png_uint_32 length)); - PNG_EXTERN void png_push_read_iTXt - PNGARG((png_structp png_ptr, png_infop info_ptr)); +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); #endif -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED - PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); - PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); #endif #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) - /* png.c *//* PRIVATE */ - PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); #endif /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ -#endif /* PNG_INTERNAL */ +#endif /* PNG_INTERNAL */ #ifdef __cplusplus } #endif -#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNG_VERSION_INFO_ONLY */ /* do not put anything past this line */ -#endif /* PNG_H */ +#endif /* PNG_H */ -- cgit v1.2.1 From 8ec91911584632c66e24a338a26905aa5ef378bd Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Aug 2009 15:27:46 -0700 Subject: Revert "Run Nindent on com32/include/pngconf.h" This reverts commit 6361b71f87466877f8fd1273240e8fa4460f8d05. is part of libpng, it should never have been Nindented. Signed-off-by: H. Peter Anvin --- com32/include/pngconf.h | 121 ++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/com32/include/pngconf.h b/com32/include/pngconf.h index bc28b9ed..3ac628c4 100644 --- a/com32/include/pngconf.h +++ b/com32/include/pngconf.h @@ -253,7 +253,7 @@ */ #ifndef PNGARG -#ifdef OF /* zlib prototype munger */ +#ifdef OF /* zlib prototype munger */ # define PNGARG(arglist) OF(arglist) #else @@ -304,8 +304,8 @@ /* If you encounter a compiler error here, see the explanation * near the end of INSTALL. */ -__png.h__ already includes setjmp.h; -__dont__ include it again.; + __png.h__ already includes setjmp.h; + __dont__ include it again.; # endif # endif /* __linux__ */ @@ -572,16 +572,16 @@ __dont__ include it again.; #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ #if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following line: */ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ -#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ #ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ # endif #endif @@ -620,7 +620,7 @@ __dont__ include it again.; # define PNG_WRITE_INVERT_SUPPORTED # endif # ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ # endif # ifndef PNG_NO_WRITE_SWAP_ALPHA # define PNG_WRITE_SWAP_ALPHA_SUPPORTED @@ -633,9 +633,9 @@ __dont__ include it again.; # endif #endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ -#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant - encoders, but can cause trouble - if left undefined */ +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ #if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ defined(PNG_FLOATING_POINT_SUPPORTED) @@ -880,8 +880,8 @@ __dont__ include it again.; # endif #endif #ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ #if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ defined(PNG_READ_zTXt_SUPPORTED) # define PNG_READ_TEXT_SUPPORTED @@ -1056,10 +1056,10 @@ typedef unsigned char png_byte; /* This is usually size_t. It is typedef'ed just in case you need it to change (I'm not sure if you will or not, so I thought I'd be safe) */ #ifdef PNG_SIZE_T -typedef PNG_SIZE_T png_size_t; + typedef PNG_SIZE_T png_size_t; # define png_sizeof(x) png_convert_size(sizeof (x)) #else -typedef size_t png_size_t; + typedef size_t png_size_t; # define png_sizeof(x) sizeof (x) #endif @@ -1088,14 +1088,15 @@ typedef size_t png_size_t; # define FAR __far # endif # define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ +# endif /* LDATA != 1 */ /* Possibly useful for moving data out of default segment. * Uncomment it if you want. Could also define FARDATA as * const if your compiler supports it. (SJT) - # define FARDATA FAR +# define FARDATA FAR */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + /* Suggest testing for specific compiler first before testing for * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, @@ -1126,43 +1127,43 @@ typedef size_t png_size_t; typedef png_int_32 png_fixed_point; /* Add typedefs for pointers */ -typedef void FAR *png_voidp; -typedef png_byte FAR *png_bytep; -typedef png_uint_32 FAR *png_uint_32p; -typedef png_int_32 FAR *png_int_32p; -typedef png_uint_16 FAR *png_uint_16p; -typedef png_int_16 FAR *png_int_16p; -typedef PNG_CONST char FAR *png_const_charp; -typedef char FAR *png_charp; -typedef png_fixed_point FAR *png_fixed_point_p; +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; #ifndef PNG_NO_STDIO #if defined(_WIN32_WCE) -typedef HANDLE png_FILE_p; +typedef HANDLE png_FILE_p; #else -typedef FILE *png_FILE_p; +typedef FILE * png_FILE_p; #endif #endif #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR *png_doublep; +typedef double FAR * png_doublep; #endif /* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR *FAR * png_bytepp; -typedef png_uint_32 FAR *FAR * png_uint_32pp; -typedef png_int_32 FAR *FAR * png_int_32pp; -typedef png_uint_16 FAR *FAR * png_uint_16pp; -typedef png_int_16 FAR *FAR * png_int_16pp; -typedef PNG_CONST char FAR *FAR * png_const_charpp; -typedef char FAR *FAR * png_charpp; -typedef png_fixed_point FAR *FAR * png_fixed_point_pp; +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR *FAR * png_doublepp; +typedef double FAR * FAR * png_doublepp; #endif /* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR *FAR * FAR * png_charppp; +typedef char FAR * FAR * FAR * png_charppp; #if defined(PNG_1_0_X) || defined(PNG_1_2_X) /* SPC - Is this stuff deprecated? */ @@ -1171,9 +1172,9 @@ typedef char FAR *FAR * FAR * png_charppp; * or another compression library is used, then change these. * Eliminates need to change all the source files. */ -typedef charf *png_zcharp; -typedef charf *FAR * png_zcharpp; -typedef z_stream FAR *png_zstreamp; +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; #endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ /* @@ -1288,10 +1289,10 @@ typedef z_stream FAR *png_zstreamp; # if defined(PNG_BUILD_DLL) # define PNG_IMPEXP __export # else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in - VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ # endif # endif @@ -1302,14 +1303,14 @@ typedef z_stream FAR *png_zstreamp; # define PNG_IMPEXP __declspec(dllimport) # endif # endif -# endif /* PNG_IMPEXP */ +# endif /* PNG_IMPEXP */ #else /* !(DLL || non-cygwin WINDOWS) */ # if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) # ifndef PNGAPI # define PNGAPI _System # endif # else -# if 0 /* ... other platforms, with other meanings */ +# if 0 /* ... other platforms, with other meanings */ # endif # endif #endif @@ -1357,25 +1358,25 @@ typedef z_stream FAR *png_zstreamp; (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) #endif -#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ /* use this to make far-to-near assignments */ # define CHECK 1 # define NOCHECK 0 # define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) # define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) # define png_strcpy _fstrcpy -# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ # define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcmp _fmemcmp /* SJT: added */ # define png_memcpy _fmemcpy # define png_memset _fmemset #else /* use the usual functions */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) # define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strncpy strncpy /* Added to v 1.2.6 */ # define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ +# define png_memcmp memcmp /* SJT: added */ # define png_memcpy memcpy # define png_memset memset #endif @@ -1400,10 +1401,10 @@ typedef z_stream FAR *png_zstreamp; */ #ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT -# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ +# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ #endif #ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT -# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ +# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ #endif /* Set this in the makefile for VC++ on Pentium, not here. */ -- cgit v1.2.1 From 89564000aceb909fd38893681d82a2647f6b1bc4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Aug 2009 22:31:13 -0700 Subject: menu: fix Ctrl-W (word erase) when editing a command line The Ctrl-W (word erase) key was broken: it would think the command line got longer, not shorter, resulting in havoc. Signed-off-by: H. Peter Anvin --- com32/menu/menumain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index 82f0018c..5b568feb 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -527,7 +527,7 @@ static const char *edit_cmdline(const char *input, int top) memmove(cmdline + cursor, cmdline + prevcursor, len - prevcursor + 1); - len -= (cursor - prevcursor); + len -= (prevcursor - cursor); redraw = 1; } break; -- cgit v1.2.1 From 8abec8d70f99c890beb281ec3f2669990345bcf1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 13 Aug 2009 22:32:08 -0700 Subject: core: kaboom.c: file missing from previous checkin kaboom.c; necessary file missing from previous checkin. Signed-off-by: H. Peter Anvin --- core/kaboom.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 core/kaboom.c diff --git a/core/kaboom.c b/core/kaboom.c new file mode 100644 index 00000000..d639915a --- /dev/null +++ b/core/kaboom.c @@ -0,0 +1,16 @@ +/* + * kaboom.c + */ + +#include "core.h" + +#undef kaboom + +__noreturn _kaboom(void) +{ + extern void kaboom(void); + call16(kaboom, &zero_regs, NULL); + /* Do this if kaboom somehow returns... */ + for (;;) + asm volatile("hlt"); +} -- cgit v1.2.1 From 7c74cc5a7bd4ee6e61f2baf686f5c6a94af20a65 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 16 Aug 2009 16:41:40 +0800 Subject: Core: code clean Signed-off-by: Liu Aleaxander --- core/fs/ext2/ext2.c | 77 ++++++---------- core/fs/fat/fat.c | 230 +++++++++++++++++++--------------------------- core/fs/iso9660/iso9660.c | 47 ++++------ core/fs/pxe/pxe.c | 197 +++++++++++++-------------------------- core/isolinux.asm | 33 ------- core/pxelinux.asm | 170 ++-------------------------------- 6 files changed, 210 insertions(+), 544 deletions(-) diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c index 34aba24f..dcd4a49b 100644 --- a/core/fs/ext2/ext2.c +++ b/core/fs/ext2/ext2.c @@ -1,13 +1,14 @@ #include #include -#include "cache.h" -#include "core.h" -#include "disk.h" +#include +#include +#include +#include #include "ext2_fs.h" -#include "fs.h" #define MAX_SYMLINKS 64 #define SYMLINK_SECTORS 2 +static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; /* * File structure, This holds the information for each currently open file @@ -20,11 +21,8 @@ struct open_file_t { uint16_t file_mode; uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */ }; - static struct open_file_t Files[MAX_OPEN]; -static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64]; - static struct ext2_inode this_inode; static struct ext2_super_block sb; @@ -33,13 +31,8 @@ static uint32_t SecPerClust, ClustSize, ClustMask; static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3; static int DescPerBlock, InodePerBlock; - -/** - * strecpy: - * +/* * just like the function strcpy(), except it returns non-zero if overflow. - * - * well, in Syslinux, strcpy() will advance both the dst and src string pointer. * */ static int strecpy(char *dst, char *src, char *end) @@ -55,12 +48,8 @@ static int strecpy(char *dst, char *src, char *end) } -/** - * allocate_file: - * - * Allocate a file structure - * - * @return: if successful return the file pointer, or return NULL +/* + * Allocate a file structure, if successful return the file pointer, or NULL. * */ static struct open_file_t *allocate_file(void) @@ -97,8 +86,6 @@ static void ext2_close_file(struct file *file) } /** - * get_group_desc: - * * get the group's descriptor of group_num * * @param: group_num, the group number; @@ -106,7 +93,8 @@ static void ext2_close_file(struct file *file) * @return: the pointer of the group's descriptor * */ -static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group_num) +static struct ext2_group_desc * +get_group_desc(struct fs_info *fs, uint32_t group_num) { block_t block_num; uint32_t offset; @@ -118,7 +106,6 @@ static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group block_num += sb.s_first_data_block + 1; cs = get_cache_block(fs->fs_dev, block_num); - desc = (struct ext2_group_desc *)cs->data + offset; return desc; @@ -126,8 +113,6 @@ static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group /** - * read_inode: - * * read the right inode structure to _dst_. * * @param: inode_offset, the inode offset within a group; @@ -138,8 +123,8 @@ static struct ext2_group_desc *get_group_desc(struct fs_info *fs, uint32_t group * */ static void read_inode(struct fs_info *fs, uint32_t inode_offset, - struct ext2_inode *dst, struct ext2_group_desc *desc, - block_t *block, uint32_t *offset) + struct ext2_inode *dst, struct ext2_group_desc *desc, + block_t *block, uint32_t *offset) { struct cache_struct *cs; struct ext2_inode *inode; @@ -159,8 +144,6 @@ static void read_inode(struct fs_info *fs, uint32_t inode_offset, /** - * open_inode: - * * open a file indicated by an inode number in INR * * @param : inr, the inode number @@ -169,7 +152,8 @@ static void read_inode(struct fs_info *fs, uint32_t inode_offset, * the first 128 bytes of the inode, stores in ThisInode * */ -static struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) +static struct open_file_t * +open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len) { struct open_file_t *file; struct ext2_group_desc *desc; @@ -208,7 +192,7 @@ static struct open_file_t * open_inode(struct fs_info *fs, uint32_t inr, uint32_ static struct ext4_extent_header * -ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block) +ext4_find_leaf(struct fs_info *fs, struct ext4_extent_header *eh, block_t block) { struct ext4_extent_idx *index; struct cache_struct *cs; @@ -241,7 +225,8 @@ ext4_find_leaf (struct fs_info *fs, struct ext4_extent_header *eh, block_t block } /* handle the ext4 extents to get the phsical block number */ -static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_inode *inode) +static block_t linsector_extent(struct fs_info *fs, block_t block, + struct ext2_inode *inode) { struct ext4_extent_header *leaf; struct ext4_extent *ext; @@ -249,7 +234,7 @@ static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_i block_t start; leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block); - if (! leaf) { + if (!leaf) { printf("ERROR, extent leaf not found\n"); return 0; } @@ -262,8 +247,7 @@ static block_t linsector_extent(struct fs_info *fs, block_t block, struct ext2_i if (--i < 0) { printf("ERROR, not find the right block\n"); return 0; - } - + } /* got it */ block -= ext[i].ee_block; @@ -503,9 +487,8 @@ static uint32_t ext2_getfssec(struct file *gfile, char *buf, * find a dir entry, if find return it or return NULL * */ -static struct ext2_dir_entry* find_dir_entry(struct fs_info *fs, - struct open_file_t *file, - char *filename) +static struct ext2_dir_entry* +find_dir_entry(struct fs_info *fs, struct open_file_t *file, char *filename) { bool have_more; char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);; @@ -595,14 +578,12 @@ static char *do_symlink(struct fs_info *fs, struct open_file_t *file, /** - * searchdir: - * * Search the root directory for a pre-mangle filename in FILENAME. * * @param: filename, the filename we want to search. * - * @out : a file pointer, stores in DS:SI (NOTE, DS == 0) - * @out : file lenght in bytes, stores in eax + * @out : a open_file_t structure pointer, stores in file->open_file + * @out : file lenght in bytes, stores in file->file_len * */ static void ext2_searchdir(char *filename, struct file *file) @@ -701,16 +682,12 @@ static void ext2_searchdir(char *filename, struct file *file) static void ext2_load_config(com32sys_t *regs) { char *config_name = "extlinux.conf"; - com32sys_t out_regs; strcpy(ConfigName, config_name); *(uint32_t *)CurrentDirName = 0x00002f2e; regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); - - regs->eax.w[0] = out_regs.eax.w[0]; + call16(core_open, regs, regs); #if 0 printf("the zero flag is %s\n", regs->eax.w[0] ? \ @@ -720,15 +697,13 @@ static void ext2_load_config(com32sys_t *regs) } -/** +/* * init. the fs meta data, return the block size bits. */ static int ext2_fs_init(struct fs_info *fs) { struct disk *disk = fs->fs_dev->disk; -#if 0 - printf("super block@: %p\n", &sb); -#endif + /* read the super block */ disk->rdwr_sectors(disk, &sb, 2, 2, 0); diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 0611caec..4ba43fef 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -1,16 +1,16 @@ #include #include -#include "cache.h" -#include "core.h" -#include "disk.h" +#include +#include +#include +#include #include "fat_fs.h" -#include "fs.h" #define ROOT_DIR_WORD 0x002f /* file structure. This holds the information for each currently open file */ struct open_file_t { - sector_t file_sector; /* sector pointer ( 0 = structure free ) */ + sector_t file_sector; /* sector pointer (0 = structure free) */ uint32_t file_bytesleft; /* number of bytes left */ uint32_t file_left; /* number of sectors left */ }; @@ -19,7 +19,6 @@ static struct open_file_t Files[MAX_OPEN]; extern uint8_t SecPerClust; - /* the fat bpb data */ static struct fat_bpb fat; static int FATType = 0; @@ -51,23 +50,17 @@ static int NameLen; static struct fs_info *this_fs = NULL; -/** - * allocate_file: - * - * Allocate a file structure - * - * @return: if successful return the file pointer, or return NULL +/* + * Allocate a file structure, if successful return the file pointer, or NULL. * */ static struct open_file_t *allocate_file(void) { - struct open_file_t *file; + struct open_file_t *file = Files; int i = 0; - - file = Files; - for (; i < MAX_OPEN; i ++ ) { - if ( file->file_sector == 0 ) /* found it */ + for (; i < MAX_OPEN; i ++) { + if (file->file_sector == 0) /* found it */ return file; file ++; } @@ -76,9 +69,7 @@ static struct open_file_t *allocate_file(void) } -/** - * alloc_fill_dir: - * +/* * Allocate then fill a file structure for a directory starting in * sector SECTOR. if successful, return the pointer of filled file * structure, or return NULL. @@ -89,7 +80,7 @@ static struct open_file_t *alloc_fill_dir(sector_t sector) struct open_file_t *file; file = allocate_file(); - if ( !file ) + if (!file) return NULL; file->file_sector = sector; /* current sector */ @@ -111,19 +102,7 @@ static void vfat_close_file(struct file *file) } -/* Deallocates a directory structure */ -/*********** -void close_dir(struct fat_dir_entry *dir) -{ - if ( dir ) - *(uint32_t*)dir = 0; -} -***********/ - - -/** - * getfatsector: - * +/* * check for a particular sector in the FAT cache. * */ @@ -134,14 +113,9 @@ static struct cache_struct *getfatsector(struct fs_info *fs, sector_t sector) /** - * nextcluster: - * * Advance a cluster pointer in clust_num to the next cluster - * pointer at in the FAT tables. CF = 0 on return if end of file. - * - * @param: clust_num; - * - * @return: the next cluster number + * pointer at in the FAT tables. return the next cluster number + * if success, or return 0 if end of file. * */ static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) @@ -156,8 +130,8 @@ static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) case FAT12: fat_sector = (clust_num + clust_num / 2) >> SECTOR_SHIFT; cs = getfatsector(fs, fat_sector); - offset = (clust_num * 3 / 2) & ( SECTOR_SIZE -1 ); - if ( offset == 0x1ff ) { + offset = (clust_num * 3 / 2) & (SECTOR_SIZE -1); + if (offset == 0x1ff) { /* * we got the end of the one fat sector, * but we don't got we have(just one byte, we need two), @@ -171,29 +145,29 @@ static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) } else next_cluster = *(uint16_t *)(cs->data + offset); - if ( clust_num & 0x0001 ) + if (clust_num & 0x0001) next_cluster >>= 4; /* cluster number is ODD */ else next_cluster &= 0x0fff; /* cluster number is EVEN */ - if ( next_cluster > 0x0ff0 ) + if (next_cluster > 0x0ff0) goto fail; break; case FAT16: fat_sector = clust_num >> (SECTOR_SHIFT - 1); - offset = clust_num & ( (1 << (SECTOR_SHIFT-1)) -1); + offset = clust_num & ((1 << (SECTOR_SHIFT-1)) -1); cs = getfatsector(fs, fat_sector); next_cluster = ((uint16_t *)cs->data)[offset]; - if ( next_cluster > 0xfff0 ) + if (next_cluster > 0xfff0) goto fail; break; case FAT32: fat_sector = clust_num >> (SECTOR_SHIFT - 2); - offset = clust_num & ( (1 << (SECTOR_SHIFT-2)) -1); + offset = clust_num & ((1 << (SECTOR_SHIFT-2)) -1); cs = getfatsector(fs, fat_sector); next_cluster = ((uint32_t *)cs->data)[offset] & 0x0fffffff; - if ( next_cluster > 0x0ffffff0 ) + if (next_cluster > 0x0ffffff0) goto fail; break; } @@ -207,9 +181,7 @@ static uint32_t nextcluster(struct fs_info *fs, uint32_t clust_num) -/** - * nextsector: - * +/* * given a sector on input, return the next sector of the * same filesystem object, which may be the root directory or a * cluster chain. Returns EOF. @@ -220,25 +192,25 @@ static sector_t nextsector(struct fs_info *fs, sector_t sector) sector_t data_sector; uint32_t cluster; - if ( sector < DataArea ) { + if (sector < DataArea) { sector ++; /* if we reached the end of root area */ - if ( sector == DataArea ) + if (sector == DataArea) sector = 0; /* return 0 */ return sector; } data_sector = sector - DataArea; - if ( (data_sector+1) & ClustMask ) /* in a cluster */ + if ((data_sector+1) & ClustMask) /* in a cluster */ return (++sector); /* got a new cluster */ cluster = nextcluster(fs, (data_sector >> ClustShift) + 2); - if ( !cluster ) + if (!cluster ) return 0; /* return the start of the new cluster */ - sector = ( (cluster - 2) << ClustShift ) + DataArea; + sector = ((cluster - 2) << ClustShift) + DataArea; return sector; } @@ -260,7 +232,8 @@ static sector_t nextsector(struct fs_info *fs, sector_t sector) * @param: sectors * */ -static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, uint32_t sectors) +static void __getfssec(struct fs_info *fs, char *buf, + struct open_file_t *file, uint32_t sectors) { sector_t curr_sector = file->file_sector; sector_t frag_start , next_sector; @@ -276,13 +249,13 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, /* get consective sector count */ con_sec_cnt ++; sectors --; - if ( sectors == 0 ) + if (sectors == 0) break; next_sector = nextsector(fs, curr_sector); - if ( !next_sector ) + if (!next_sector) break; - }while( next_sector == (++curr_sector) ); + }while(next_sector == (++curr_sector)); #if 0 printf("You are reading data stored at sector --0x%x--0x%x\n", @@ -293,7 +266,7 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, disk->rdwr_sectors(disk, buf, frag_start, con_sec_cnt, 0); buf += con_sec_cnt << 9;/* adjust buffer pointer */ - if ( !sectors ) + if (!sectors) break; //curr_sector --; /* this is the last sector actually read */ curr_sector = next_sector; @@ -306,15 +279,12 @@ static void __getfssec(struct fs_info *fs, char *buf, struct open_file_t *file, /** - * getfssec: - * * get multiple sectors from a file * - * - * @param: buf - * @param: file - * @param: sectors - * @param: have_more + * @param: buf, the buffer to store the read data + * @param: gfile, the file structure pointer + * @param: sectors, number of sectors wanna read + * @param: have_more, set one if has more * * @return: number of bytes read * @@ -326,12 +296,12 @@ static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, struct open_file_t *file = gfile->open_file; struct fs_info *fs = gfile->fs; - if ( sectors > file->file_left ) + if (sectors > file->file_left) sectors = file->file_left; __getfssec(fs, buf, file, sectors); - if ( bytes_read >= file->file_bytesleft ) { + if (bytes_read >= file->file_bytesleft) { bytes_read = file->file_bytesleft; *have_more = 0; } else @@ -342,9 +312,7 @@ static uint32_t vfat_getfssec(struct file *gfile, char *buf, int sectors, return bytes_read; } -/** - * mangle_name: - * +/* * Mangle a filename pointed to by src into a buffer pointed to by dst; * ends on encountering any whitespace. * @@ -390,18 +358,12 @@ static void vfat_mangle_name(char *dst, const char *src) *dst++ = '\0'; } -/** - * mangle_dos_name: - * +/* * Mangle a dos filename component pointed to by FILENAME * into MangleBuf; ends on encountering any whitespace or * slash. * * WARNING: saves pointers into the buffer for longname matchs! - * - * @param: filename - * @param: MangleBuf - * */ /** * for now, it can't handle this case: @@ -427,10 +389,10 @@ static void mangle_dos_name(char *MangleBuf, char *filename) for (i = 0; i < 11; i++) { c = *src ++; - if ( (c <= ' ') || (c == '/') ) + if ((c <= ' ') || (c == '/')) break; - if ( c == '.' ) { + if (c == '.') { dst = &MangleBuf[8]; i = 7; continue; @@ -438,27 +400,25 @@ static void mangle_dos_name(char *MangleBuf, char *filename) if (c >= 'a' && c <= 'z') c -= 32; - if ( (c == 0xe5) && (i == 11) ) + if ((c == 0xe5) && (i == 11)) c = 0x05; *dst++ = c; } MangleBuf[12] = '\0'; - while( (*src != '/') && (*src > ' ') ) + while((*src != '/') && (*src > ' ')) src ++; NameLen = src - filename; } - - static void unicode_to_ascii(char *entry_name, uint16_t *unicode_buf) { int i = 0; for (; i < 13; i++) { - if ( unicode_buf[i] == 0xffff ) { + if (unicode_buf[i] == 0xffff) { entry_name[i] = '\0'; return; } @@ -466,9 +426,7 @@ static void unicode_to_ascii(char *entry_name, uint16_t *unicode_buf) } } -/** - * long_entry_name: - * +/* * get the long entry name * */ @@ -508,8 +466,6 @@ static inline sector_t first_sector(struct fat_dir_entry *dir) /** - * search_dos_dir: - * * search a specific directory for a pre-mangled filename in * MangleBuf, in the directory starting in sector SECTOR * @@ -524,11 +480,11 @@ static inline sector_t first_sector(struct fat_dir_entry *dir) * @out: file pointer * @out: file length (MAY BE ZERO!) * @out: file attribute - * @out: dh, clobbered. * */ -static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, - uint32_t dir_sector, uint32_t *file_len, uint8_t *attr) +static struct open_file_t* +search_dos_dir(struct fs_info *fs, char *MangleBuf, + uint32_t dir_sector, uint32_t *file_len, uint8_t *attr) { struct open_file_t* file; struct cache_struct* cs; @@ -542,8 +498,8 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, int checksum; file = allocate_file(); - if ( !file ) - return NULL; + if (!file) + return NULL; /* * Compute the value of a possible VFAT longname @@ -561,21 +517,21 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, /* scan all the entries in a sector */ do { - if ( dir->name[0] == 0 ) + if (dir->name[0] == 0) return NULL; /* Hit directory high water mark */ - if ( dir->attr == 0x0f ) { + if (dir->attr == 0x0f) { /* it's a long name entry */ long_dir = (struct fat_long_name_entry *)dir; id = long_dir->id; - if ( id !=VFATNext ) + if (id !=VFATNext) goto not_match; - if ( id & 0x40 ) { + if (id & 0x40) { /*get the initial checksum value*/ VFATCsum = long_dir->checksum; } else { - if ( long_dir->checksum != VFATCsum ) + if (long_dir->checksum != VFATCsum) goto not_match; } @@ -590,8 +546,8 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, * if we got the last entry? * if so, check it, or go on with the next entry */ - if ( id == 0 ) { - if ( strcmp(long_name, NameStart) ) + if (id == 0) { + if (strcmp(long_name, NameStart)) goto not_match; } @@ -599,22 +555,22 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, } else { /* it's a short entry */ - if ( dir->attr & 0x08 ) /* ingore volume labels */ + if (dir->attr & 0x08) /* ingore volume labels */ goto not_match; /* If we have a long name match, then VFATNext must be 0 */ - if ( !VFATNext ) { + if (!VFATNext) { /* * we already have a VFAT long name match, however, * the match is only valid if the checksum matchs. */ checksum = get_checksum(dir->name); - if ( checksum == VFATCsum ) + if (checksum == VFATCsum) goto found; /* got a match on long name */ } else { - if ( strncmp(MangleBuf, dir->name, 11) == 0 ) + if (strncmp(MangleBuf, dir->name, 11) == 0) goto found; } } @@ -625,11 +581,11 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, next_entry: dir ++; - }while ( --entries ); + }while (--entries); dir_sector = nextsector(fs, dir_sector); - }while ( dir_sector ); /* scan another secotr */ + }while (dir_sector); /* scan another secotr */ found: *file_len = file->file_bytesleft = dir->file_size; @@ -642,8 +598,6 @@ static struct open_file_t* search_dos_dir(struct fs_info *fs, char *MangleBuf, /** - * searchdir: - * * open a file * * @param: filename, the file we wanna open @@ -663,13 +617,13 @@ static void vfat_searchdir(char *filename, struct file *file) this_fs = file->fs; dir_sector = CurrentDir; - if ( *filename == '/' ) { + if (*filename == '/') { dir_sector = RootDir; if (*(filename + 1) == 0) /* root dir is what we need */ goto found_dir; } - while ( *filename ) { + while (*filename) { if (*filename == '/') filename++; /* skip '/' */ p = filename; @@ -678,7 +632,7 @@ static void vfat_searchdir(char *filename, struct file *file) PrevDir = dir_sector; /* try to find the end */ - while ( (*p > ' ') && (*p != '/') ) + while ((*p > ' ') && (*p != '/')) p ++; if (filename == p) { @@ -703,13 +657,13 @@ static void vfat_searchdir(char *filename, struct file *file) dir_sector = PrevDir; found_dir: open_file = alloc_fill_dir(dir_sector); - } else if ( (attr & 0x18) || (file_len == 0) ) { + } else if ((attr & 0x18) || (file_len == 0)) { fail: file_len = 0; open_file = NULL; } else { open_file->file_bytesleft = file_len; - open_file->file_left = ( file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT; + open_file->file_left = (file_len + SECTOR_SIZE -1) >> SECTOR_SHIFT; } file->file_len = file_len; @@ -759,21 +713,21 @@ void vfat_readdir(com32sys_t *regs)/* cs = get_cache_block(this_fs->fs_dev, sector); dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ - while ( 1 ) { - if ( dir->name[0] == 0 ) + while (1) { + if (dir->name[0] == 0) goto fail; - if ( dir->attr == FAT_ATTR_LONG_NAME ) { + if (dir->attr == FAT_ATTR_LONG_NAME) { /* it's a long name */ long_dir = (struct fat_long_name_entry *)dir; - if ( long_dir->id & 0x40 ) { + if (long_dir->id & 0x40) { init_id = id = long_dir->id & 0x3f; id--; } else { next_id = (long_dir->id & 0x3f) - 1; id--; - if ( id != next_id ) + if (id != next_id) goto next_entry; } @@ -789,22 +743,22 @@ void vfat_readdir(com32sys_t *regs)/* } else { /* it's a short entry */ - if ( !id ) /* we got a long name match */ + if (!id) /* we got a long name match */ break; - if ( dir->attr & FAT_ATTR_VOLUME_ID ) + if (dir->attr & FAT_ATTR_VOLUME_ID) goto next_entry; - for( i = 0; i < 8; i ++) { - if ( dir->name[i] == ' ' ) + for(i = 0; i < 8; i ++) { + if (dir->name[i] == ' ') break; *filename++ = dir->name[i]; } *filename++ = '.'; - for ( i = 8; i < 11; i ++) { - if ( dir->name[i] == ' ' ) + for (i = 8; i < 11; i ++) { + if (dir->name[i] == ' ') break; *filename ++ = dir->name[i]; } @@ -822,20 +776,20 @@ void vfat_readdir(com32sys_t *regs)/* dir ++; entries_left --; - if ( !entries_left ) { + if (!entries_left) { sector = nextsector(this_fs, sector); - if ( !sector ) + if (!sector) goto fail; cs = get_cache_block(this_fs->fs_dev, sector); dir = (struct fat_dir_entry *)cs->data; } } - /* finally , we get what we want */ + /* finally , we get what we want */ entries_left --; - if ( !entries_left ) { + if (!entries_left) { sector = nextsector(this_fs, sector); - if ( !sector ) + if (!sector) goto fail; dir_file->file_bytesleft = 0; } else @@ -843,7 +797,7 @@ void vfat_readdir(com32sys_t *regs)/* dir_file->file_sector = sector; file.file_sector = sector; - file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT) ) & 0xffff; + file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT)) & 0xffff; regs->eax.l = dir->file_size; regs->ebx.l = first_sector(dir); @@ -887,7 +841,7 @@ static void vfat_load_config(com32sys_t *regs) if (! (oregs.eflags.l & EFLAGS_ZF)) break; } - if ( i == 3 ) { + if (i == 3) { printf("no config file found\n"); return; /* no config file */ } @@ -929,9 +883,9 @@ static int vfat_fs_init(struct fs_info *fs) ClustSize = fat.bxSecPerClust << SECTOR_SHIFT; clust_num = (TotalSectors - DataArea) >> ClustShift; - if ( clust_num < 4085 ) + if (clust_num < 4085) FATType = FAT12; - else if ( clust_num < 65525 ) + else if (clust_num < 65525) FATType = FAT16; else FATType = FAT32; diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 1d08805b..68d57363 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -1,10 +1,9 @@ #include #include -//#include "cache.h" -#include "core.h" -#include "disk.h" +#include +#include +#include #include "iso9660_fs.h" -#include "fs.h" #define DEBUG 1 @@ -18,7 +17,6 @@ struct open_file_t { uint32_t file_bytesleft; uint32_t file_left; }; - static struct open_file_t Files[MAX_OPEN]; struct dir_t { @@ -41,9 +39,7 @@ static char *ISOFileNameEnd = &ISOFileName[64]; */ static int block_shift; -/** - * allocate_file: - * +/* * allocate a file structure * */ @@ -78,9 +74,7 @@ static void iso_close_file(struct file *file) close_pvt(file->open_file); } -/** - * mangle_name: - * +/* * Mangle a filename pointed to by src into a buffer pointed * to by dst; ends on encountering any whitespace. * dst is preserved. @@ -127,7 +121,7 @@ static void iso_mangle_name(char *dst, const char *src) } /** - * compare the names si and di and report if they are + * compare the names de_name and file_name and report if they are * equal from an ISO 9600 perspective. * * @param: de_name, the name from the file system. @@ -201,8 +195,6 @@ static inline int cdrom_read_sectors(struct disk *disk, void *buf, int block, in } /** - * iso_getfssec: - * * Get multiple clusters from a file, given the file pointer. * * @param: buf @@ -238,15 +230,11 @@ static uint32_t iso_getfssec(struct file *gfile, char *buf, -/** - * do_search_dir: - * +/* * find a file or directory with name within the _dir_ directory. * * the return value will tell us what we find, it's a file or dir? - * on 1 be dir, 2 be file, 0 be error. - * - * res will return the result. + * on 1 be dir, 2 be file, 0 be error. res will return the result. * */ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, @@ -381,9 +369,7 @@ static int do_search_dir(struct fs_info *fs, struct dir_t *dir, } -/** - * iso_searchdir: - * +/* * open a file * * searchdir_iso is a special entry point for ISOLINUX only. In addition @@ -462,13 +448,20 @@ static void iso_searchdir(char *filename, struct file *file) static void iso_load_config(com32sys_t *regs) { char *config_name = "isolinux.cfg"; - com32sys_t out_regs; + +#if DEBUG + printf("About to load config file...\n"); +#endif strcpy(ConfigName, config_name); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - memset(&out_regs, 0, sizeof out_regs); - call16(core_open, regs, &out_regs); + call16(core_open, regs, regs); + +#if DEBUG + printf("the zero flag is %s\n", regs->eax.w[0] ? + "CLEAR, means we found the config file" : + "SET, menas we didn't find the config file"); +#endif } diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index d03847d3..8ac5b06b 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -9,14 +9,6 @@ #define GPXE 1 static struct open_file_t Files[MAX_OPEN]; - -static char *err_nopxe = "No !PXE or PXENV+ API found; we're dead...\n"; -static char *err_pxefailed = "PXE API call failed, error "; -static char *err_udpinit = "Failed to initialize UDP stack\n"; - -static char *tftpprefix_msg = "TFTP prefix: "; -static char *get_packet_msg = "Getting cached packet "; - static int has_gpxe; static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; int HaveUUID = 0; @@ -89,7 +81,7 @@ static struct open_file_t *allocate_socket(void) } /* - * free socket, socket in SI; return SI = 0, ZF = 1 for convenience + * free socket in _file_. */ static void free_socket(struct open_file_t *file) { @@ -131,7 +123,7 @@ static void lchexbytes(char *dst, const void *src, int count) } } -/** +/* * just like the lchexbytes, except to upper-case * */ @@ -151,50 +143,31 @@ static void uchexbytes(char *dst, const void *src, int count) } } - - - /* - * - * Tests an IP address in EAX for validity; return with 0 for bad, 1 for good. + * Tests an IP address in _ip_ for validity; return with 0 for bad, 1 for good. * We used to refuse class E, but class E addresses are likely to become * assignable unicast addresses in the near future. * */ int ip_ok(uint32_t ip) { - if (ip == -1) /* Refuse the all-one address */ - goto bad; - if ((ip & 0xff) == 0) /* Refuse network zero */ - goto bad; - if ((ip & 0xff) == 0xff) /* Refuse loopback */ - goto bad; - if ((ip & 0xf0) == 0xe0) /* Refuse class D */ - goto bad; - - return 1; + if (ip == -1 || /* Refuse the all-one address */ + (ip & 0xff) == 0 || /* Refuse network zero */ + (ip & 0xff) == 0xff || /* Refuse loopback */ + (ip & 0xf0) == 0xe0 ) /* Refuse class D */ + return 0; - bad: - return 0; + return 1; } -/********************************************************************* -; -; gendotquad -; -; Take an IP address (in network byte order) in EAX and -; output a dotted quad string to ES:DI. -; DI points to terminal null at end of string on exit. -; - *********************************************************************/ -/** - * @param: dst, to store the converted ip string - * @param: ip, the ip address that needed convert. - * - * @return: the ip string length +/* + * Take an IP address (in network byte order) in _ip_ and + * output a dotted quad string to _dst_, returns the length + * of the dotted quad ip string. + * */ -int gendotquad(char *dst, uint32_t ip) +static int gendotquad(char *dst, uint32_t ip) { int part; int i = 0, j; @@ -273,7 +246,6 @@ static int pxe_call(int opcode, void *data) } /** - * * Send ACK packet. This is a common operation and so is worth canning. * * @param: file, TFTP block pointer @@ -319,11 +291,10 @@ static int pxe_get_cached_info(int type) bq_pkt.packettype = type; bq_pkt.buffersize = 8192; bq_pkt.buffer[0] = OFFS_WRT(trackbuf, 0); - bq_pkt.buffer[1] = 0; - + bq_pkt.buffer[1] = 0; err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); if (err) { - printf("%s %04x\n", err_pxefailed, err); + printf("PXE API call failed, error %04x\n", err); kaboom(); } @@ -360,7 +331,8 @@ static int is_gpxe(char *url) { int err; static __lowmem struct gpxe_file_api_check ac; - char *gpxe_warning_msg = "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; + char *gpxe_warning_msg = + "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; if (! is_url(url)) return 0; @@ -378,11 +350,8 @@ static int is_gpxe(char *url) if (!has_gpxe) printf("%s\n", gpxe_warning_msg); } - - if (has_gpxe == 1) - return 1; - else - return 0; + + return has_gpxe == 1; } /** @@ -496,14 +465,7 @@ static void pxe_mangle_name(char *dst, const char *src) while (i) { *dst++ = 0; i--; - } - -#if 0 - printf("the name before mangling: "); - dump16(src); - printf("the name after mangling: "); - dump16((char *)MK_PTR(regs->ds, regs->edi.w[0])); -#endif + } } @@ -526,14 +488,9 @@ static char *pxe_unmangle_name(char *dst, const char *src) } /* - * - ; - ; Get a fresh packet if the buffer is drained, and we haven't hit - ; EOF yet. The buffer should be filled immediately after draining! - ; - ; expects fs -> pktbuf_seg and ds:si -> socket structure - ; -*/ + * Get a fresh packet if the buffer is drained, and we haven't hit + * EOF yet. The buffer should be filled immediately after draining! + */ static void fill_buffer(struct open_file_t *file) { int err; @@ -615,14 +572,15 @@ static void fill_buffer(struct open_file_t *file) * so the server just resent the previous packet. */ #if 0 - printf("Wrong packet, wanted %04x, got %04x\n", htons(last_pkt), htons(*(uint16_t *)(data+2))); + printf("Wrong packet, wanted %04x, got %04x\n", \ + htons(last_pkt), htons(*(uint16_t *)(data+2))); #endif goto ack_again; } /* It's the packet we want. We're also EOF if the size < blocksize */ file->tftp_lastpkt = last_pkt; /* Update last packet number */ - buffersize = pkt.buffersize - 4; /* Skip TFTP header */ + buffersize = pkt.buffersize - 4; /* Skip TFTP header */ file->tftp_dataptr = file->tftp_pktbuf + 4; file->tftp_filepos += buffersize; file->tftp_bytesleft = buffersize; @@ -659,8 +617,8 @@ static uint32_t pxe_getfssec(struct file *gfile, char *buf, count <<= TFTP_BLOCKSIZE_LG2; while (count) { - fill_buffer(file); /* If we have no 'fresh' buffer, get it */ - if (! file->tftp_bytesleft) + fill_buffer(file); /* If we have no 'fresh' buffer, get it */ + if (!file->tftp_bytesleft) break; chunk = count; @@ -703,21 +661,13 @@ static int fill_tail(char *dst) } -/* - * - * - * searchdir: +/** + * Open a TFTP connection to the server * - * Open a TFTP connection to the server + * @param:filename, the file we wanna open * - * On entry: - * DS:DI = mangled filename - * If successful: - * ZF clear - * SI = socket pointer - * EAX = file length in bytes, or -1 if unknown - * If unsuccessful - * ZF set + * @out: open_file_t structure, stores in file->open_file + * @ouT: the lenght of this file, stores in file->file_len * */ static void pxe_searchdir(char *filename, struct file *file) @@ -1037,11 +987,11 @@ static void get_prefix(void) *(p + 2) = 0; /* Zero-terminate after delimiter */ got_prefix: - printf("%s%s\n", tftpprefix_msg, PathPrefix); + printf("TFTP prefix: %s\n", PathPrefix); strcpy(CurrentDirName, PathPrefix); } - /** + /* * try to load a config file, if found, return 1, or return 0 * */ @@ -1071,7 +1021,6 @@ static int try_load(com32sys_t *regs) */ static void pxe_load_config(com32sys_t *regs) { - extern void no_config(void); char *cfgprefix = "pxelinux.cfg/"; char *default_str = "default"; char *config_file; /* Pointer to the variable suffix */ @@ -1175,14 +1124,10 @@ static void make_bootif_string(void) #endif } /* - ; - ; genipopt - ; - ; Generate an ip=::: - ; option into IPOption based on a DHCP packet in trackbuf. - ; Assumes CS == DS == ES. - ; -*/ + * Generate an ip=::: + * option into IPOption based on a DHCP packet in trackbuf. + * + */ static void genipopt(void) { char *p = IPOption; @@ -1245,7 +1190,7 @@ static int is_pxe(const void *buf) return sum == 0; } -/** +/* * Just like is_pxe, it checks PXENV+ structure * */ @@ -1269,24 +1214,15 @@ static int is_pxenv(const void *buf) -/********************************************************************* -; -; memory_scan_for_pxe_struct: -; memory_scan_for_pxenv_struct: -; -; If none of the standard methods find the !PXE/PXENV+ structure, -; look for it by scanning memory. -; -; On exit, if found: -; ZF = 1, ES:BX -> !PXE structure -; Otherwise: -; ZF = 0 -; -; Assumes DS == CS -; Clobbers AX, BX, CX, DX, SI, ES -; - ********************************************************************/ - +/* + * memory_scan_for_pxe_struct: + * memory_scan_for_pxenv_struct: + * + * If none of the standard methods find the !PXE/PXENV+ structure, + * look for it by scanning memory. + * + * return the corresponding pxe structure if found, or NULL; + */ static const void *memory_scan(uintptr_t start, int (*func)(const void *)) { const char *ptr; @@ -1380,7 +1316,7 @@ static void pxe_init(void) goto have_pxenv; /* Found nothing at all !! */ - printf("%s\n", err_nopxe); + printf("No !PXE or PXENV+ API found; we're dead...\n"); kaboom(); have_pxenv: @@ -1442,7 +1378,7 @@ static void udp_init(void) uo_pkt.sip = MyIP; err = pxe_call(PXENV_UDP_OPEN, &uo_pkt); if (err || uo_pkt.status) { - printf("%s", err_udpinit); + printf("Failed to initialize UDP stack "); printf("%d\n", uo_pkt.status); kaboom(); } @@ -1462,20 +1398,19 @@ static void network_init(void) /* * Get the DHCP client identifiers (query info 1) */ - printf("%s", get_packet_msg); + printf("Getting cached packet "); pkt_len = pxe_get_cached_info(1); parse_dhcp(pkt_len); /* - ; We don't use flags from the request packet, so - ; this is a good time to initialize DHCPMagic... - ; Initialize it to 1 meaning we will accept options found; - ; in earlier versions of PXELINUX bit 0 was used to indicate - ; we have found option 208 with the appropriate magic number; - ; we no longer require that, but MAY want to re-introduce - ; it in the future for vendor encapsulated options. - */ + * We don't use flags from the request packet, so + * this is a good time to initialize DHCPMagic... + * Initialize it to 1 meaning we will accept options found; + * in earlier versions of PXELINUX bit 0 was used to indicate + * we have found option 208 with the appropriate magic number; + * we no longer require that, but MAY want to re-introduce + * it in the future for vendor encapsulated options. + */ *(char *)&DHCPMagic = 1; - /* * Get the BOOTP/DHCP packet that brought us file (and an IP @@ -1490,20 +1425,16 @@ static void network_init(void) */ MACLen = bp->hardlen > 16 ? 0 : bp->hardlen; MACType = bp->hardware; - memcpy(MAC, bp->macaddr, MACLen); - + memcpy(MAC, bp->macaddr, MACLen); /* * Get the boot file and other info. This lives in the CACHED_REPLY * packet (query info 3) */ pkt_len = pxe_get_cached_info(3); - parse_dhcp(pkt_len); - + parse_dhcp(pkt_len); printf("\n"); - - make_bootif_string(); ip_init(); diff --git a/core/isolinux.asm b/core/isolinux.asm index 09844781..b67bdc19 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -68,12 +68,6 @@ file_left resd 1 ; Number of sectors left %endif %endif - struc dir_t -dir_lba resd 1 ; Directory start (LBA) -dir_len resd 1 ; Length in bytes -dir_clust resd 1 ; Length in clusters - endstruc - ; --------------------------------------------------------------------------- ; BEGIN CODE ; --------------------------------------------------------------------------- @@ -91,10 +85,6 @@ trackbuf resb trackbufsize ; Track buffer goes here ; is loaded. DO NOT move this to .bss16/.uibss. section .earlybss alignb 4 -ISOFileName resb 64 ; ISO filename canonicalization buffer -ISOFileNameEnd equ $ -CurrentDir resb dir_t_size ; Current directory -RootDir resb dir_t_size ; Root directory FirstSecSum resd 1 ; Checksum of bytes 64-2048 ImageDwords resd 1 ; isolinux.bin size, dwords InitStack resd 1 ; Initial stack pointer (SS:SP) @@ -1171,18 +1161,8 @@ all_read: ; ; Locate the configuration file ; -%ifdef DEBUG_MESSAGES - mov si,dbg_config_msg - call writemsg -%endif - pm_call load_config -%ifdef DEBUG_MESSAGES - mov si,dbg_configok_msg - call writemsg -%endif - ; ; Now we have the config file open. Parse the config file and ; run the user interface. @@ -1334,21 +1314,8 @@ is_disk_image: ; ----------------------------------------------------------------------------- section .data16 - -default_str db 'default', 0 -default_len equ ($-default_str) -boot_dir db '/boot' ; /boot/isolinux -isolinux_dir db '/isolinux', 0 -config_name db 'isolinux.cfg', 0 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0 -%ifdef DEBUG_MESSAGES -dbg_rootdir_msg db 'Root directory at LBA = ', 0 -dbg_isodir_msg db 'isolinux directory at LBA = ', 0 -dbg_config_msg db 'About to load config file...', CR, LF, 0 -dbg_configok_msg db 'Configuration file opened...', CR, LF, 0 -%endif - ; ; Config file keyword table ; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 49c81f1e..ed67518f 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -48,24 +48,12 @@ SECTOR_SIZE equ TFTP_BLOCKSIZE ; ; TFTP operation codes ; -TFTP_RRQ equ htons(1) ; Read request -TFTP_WRQ equ htons(2) ; Write request -TFTP_DATA equ htons(3) ; Data packet TFTP_ACK equ htons(4) ; ACK packet TFTP_ERROR equ htons(5) ; ERROR packet -TFTP_OACK equ htons(6) ; OACK packet ; ; TFTP error codes ; -TFTP_EUNDEF equ htons(0) ; Unspecified error -TFTP_ENOTFOUND equ htons(1) ; File not found -TFTP_EACCESS equ htons(2) ; Access violation -TFTP_ENOSPACE equ htons(3) ; Disk full -TFTP_EBADOP equ htons(4) ; Invalid TFTP operation -TFTP_EBADID equ htons(5) ; Unknown transfer -TFTP_EEXISTS equ htons(6) ; File exists -TFTP_ENOUSER equ htons(7) ; No such user TFTP_EOPTNEG equ htons(8) ; Option negotiation failure ; @@ -86,60 +74,6 @@ vk_append: resb max_cmd_len+1 ; Command line vk_end: equ $ ; Should be <= vk_size endstruc -; -; BOOTP/DHCP packet pattern -; - struc bootp_t -bootp: -.opcode resb 1 ; BOOTP/DHCP "opcode" -.hardware resb 1 ; ARP hardware type -.hardlen resb 1 ; Hardware address length -.gatehops resb 1 ; Used by forwarders -.ident resd 1 ; Transaction ID -.seconds resw 1 ; Seconds elapsed -.flags resw 1 ; Broadcast flags -.cip resd 1 ; Client IP -.yip resd 1 ; "Your" IP -.sip resd 1 ; Next server IP -.gip resd 1 ; Relay agent IP -.macaddr resb 16 ; Client MAC address -.sname resb 64 ; Server name (optional) -.bootfile resb 128 ; Boot file name -.option_magic resd 1 ; Vendor option magic cookie -.options resb 1260 ; Vendor options - endstruc - -BOOTP_OPTION_MAGIC equ htonl(0x63825363) ; See RFC 2132 - -; -; TFTP connection data structure. Each one of these corresponds to a local -; UDP port. The size of this structure must be a power of 2. -; HBO = host byte order; NBO = network byte order -; (*) = written by options negotiation code, must be dword sized -; -; For a gPXE connection, we set the local port number to -1 and the -; remote port number contains the gPXE file handle. -; - struc open_file_t -tftp_localport resw 1 ; Local port number (0 = not in use) -tftp_remoteport resw 1 ; Remote port number -tftp_remoteip resd 1 ; Remote IP address -tftp_filepos resd 1 ; Bytes downloaded (including buffer) -tftp_filesize resd 1 ; Total file size(*) -tftp_blksize resd 1 ; Block size for this connection(*) -tftp_bytesleft resw 1 ; Unclaimed data bytes -tftp_lastpkt resw 1 ; Sequence number of last packet (NBO) -tftp_dataptr resw 1 ; Pointer to available data -tftp_goteof resb 1 ; 1 if the EOF packet received - resb 3 ; Currently unusued - ; At end since it should not be zeroed on socked close -tftp_pktbuf resw 1 ; Packet buffer offset - endstruc -%ifndef DEPEND -%if (open_file_t_size & (open_file_t_size-1)) -%error "open_file_t is not a power of 2" -%endif -%endif ; --------------------------------------------------------------------------- ; BEGIN CODE @@ -356,11 +290,7 @@ local_boot: ; kaboom: write a message and bail out. Wait for quite a while, ; or a user keypress, then do a hard reboot. ; - global no_config, kaboom -; set the no_config kaboom here -no_config: - mov si, err_noconfig - call writestr_early + global kaboom kaboom: RESET_STACK_AND_SEGS AX .patch: mov si,bailmsg @@ -481,8 +411,6 @@ TimeoutTable: TimeoutTableEnd equ $ section .text16 - - ; ; unload_pxe: ; @@ -605,36 +533,10 @@ copyright_str db ' Copyright (C) 1994-' db ' H. Peter Anvin et al', CR, LF, 0 err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0 bailmsg equ err_bootfailed -err_nopxe db "No !PXE or PXENV+ API found; we're dead...", CR, LF, 0 -err_pxefailed db 'PXE API call failed, error ', 0 -err_udpinit db 'Failed to initialize UDP stack', CR, LF, 0 -err_noconfig db 'Unable to locate configuration file', CR, LF, 0 -err_damage db 'TFTP server sent an incomprehesible reply', CR, LF, 0 -found_pxenv db 'Found PXENV+ structure', CR, LF, 0 -apiver_str db 'PXE API version is ',0 -pxeentry_msg db '!PXE entry point found (we hope) at ', 0 -pxenventry_msg db 'PXENV+ entry point found (we hope) at ', 0 -viaplan_msg db ' via plan ' -plan db 'A', CR, LF, 0 -trymempxe_msg db 'Scanning memory for !PXE structure... ', 0 -trymempxenv_msg db 'Scanning memory for PXENV+ structure... ', 0 -undi_data_msg db 'UNDI data segment at ',0 -undi_code_msg db 'UNDI code segment at ',0 -len_msg db ' len ', 0 cant_free_msg db 'Failed to free base memory, error ', 0 -notfound_msg db 'not found', CR, LF, 0 -myipaddr_msg db 'My IP address seems to be ',0 -tftpprefix_msg db 'TFTP prefix: ', 0 localboot_msg db 'Booting from local disk...', CR, LF, 0 -trying_msg db 'Trying to load: ', 0 -default_str db 'default', 0 syslinux_banner db CR, LF, 'PXELINUX ', VERSION_STR, ' ', DATE_STR, ' ', 0 -cfgprefix db 'pxelinux.cfg/' ; No final null! -cfgprefix_len equ ($-cfgprefix) -; This one we make ourselves -bootif_str db 'BOOTIF=' -bootif_str_len equ $-bootif_str ; ; Config file keyword table ; @@ -672,74 +574,18 @@ old_api_unload: ; PXE query packets partially filled in ; section .bss16 - global pxe_bootp_query_pkt, pxe_udp_write_pkt - global pxe_udp_open_pkt, pxe_udp_read_pkt -pxe_bootp_query_pkt: -.status: resw 1 ; Status -.packettype: resw 1 ; Boot server packet type -.buffersize: resw 1 ; Packet size -.buffer: resw 2 ; seg:off of buffer -.bufferlimit: resw 1 ; Unused - -pxe_udp_open_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Source (our) IP - pxe_udp_close_pkt: .status: resw 1 ; Status -pxe_udp_write_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Server IP -.gip: resd 1 ; Gateway IP -.lport: resw 1 ; Local port -.rport: resw 1 ; Remote port -.buffersize: resw 1 ; Size of packet -.buffer: resw 2 ; seg:off of buffer - pxe_udp_read_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Source IP -.dip: resd 1 ; Destination (our) IP -.rport: resw 1 ; Remote port -.lport: resw 1 ; Local port -.buffersize: resw 1 ; Max packet size -.buffer: resw 2 ; seg:off of buffer - -%if GPXE - - section .data16 - global gpxe_file_api_check -gpxe_file_api_check: -.status: dw 0 ; Status -.size: dw 20 ; Size in bytes -.magic: dd 0x91d447b2 ; Magic number -.provider: dd 0 -.apimask: dd 0 -.flags: dd 0 - - section .bss16 - global gpxe_file_read, gpxe_get_file_size - global gpxe_file_open - -gpxe_file_open: -.status: resw 1 ; Status -.filehandle: resw 1 ; FileHandle -.filename: resd 1 ; seg:off of FileName -.reserved: resd 1 - -gpxe_get_file_size: -.status: resw 1 ; Status -.filehandle: resw 1 ; FileHandle -.filesize: resd 1 ; FileSize - -gpxe_file_read: -.status: resw 1 ; Status -.filehandle: resw 1 ; FileHandle -.buffersize: resw 1 ; BufferSize -.buffer: resd 1 ; seg:off of buffer +.status: resw 1 ; Status +.sip: resd 1 ; Source IP +.dip: resd 1 ; Destination (our) IP +.rport: resw 1 ; Remote port +.lport: resw 1 ; Local port +.buffersize: resw 1 ; Max packet size +.buffer: resw 2 ; seg:off of buffer -%endif ; GPXE ; ; Misc initialized (data) variables -- cgit v1.2.1 From 04599613bd3fa33e99dde9d3bc12f0cf3b3769fb Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 17 Aug 2009 16:28:52 +0800 Subject: Core: fat: make the file->file_len to store the dir sector number when we search a dir Because the opendir function in com32/lib/opendir.c use the eax to store the dir sector, where we store the file_len before. Well, we may need add a union structure in the file structure to store the file_len for file, file_dir for dir respecifictly Signed-off-by: Liu Aleaxander --- core/comboot.inc | 1 - core/fs/fat/fat.c | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/comboot.inc b/core/comboot.inc index fb0f57f7..60c5d6fd 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -908,7 +908,6 @@ comapi_opendir: pop ds pm_call searchdir jz comapi_err ; Didn't find a directory - mov eax,[si] ; the sector number where the dir stores cmp eax,0 jz comapi_err ; Found nothing mov P_EAX,eax diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 4ba43fef..2f0bac74 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -657,6 +657,11 @@ static void vfat_searchdir(char *filename, struct file *file) dir_sector = PrevDir; found_dir: open_file = alloc_fill_dir(dir_sector); + /* + * for dir, we use the file->file_len to store the sector number + * where the dir is. + */ + file_len = dir_sector; } else if ((attr & 0x18) || (file_len == 0)) { fail: file_len = 0; -- cgit v1.2.1 From 1e5b3e683aacab3f866abfa36e162177e80b6836 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 17 Aug 2009 12:26:08 -0700 Subject: menu: initialize cm (current menu) before empty check The empty check in the menu system used "cm", but before "cm" had actually been initialized. Move the "cm" initialization earlier so we do the right thing here. Reported-by: CKSoon Signed-off-by: H. Peter Anvin --- com32/menu/menumain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index 5b568feb..f3f0154b 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -1101,12 +1101,13 @@ int menu_main(int argc, char *argv[]) m->mparm[i] = max(m->mparm[i] + rows, 0); } + cm = start_menu; + if (!cm->nentries) { fputs("Initial menu has no LABEL entries!\n", stdout); return 1; /* Error! */ } - cm = start_menu; for (;;) { cmdline = run_menu(); -- cgit v1.2.1 From 1c1ca54240d84f93fd5825b77997bcfb4794d84b Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Tue, 18 Aug 2009 07:47:55 +0800 Subject: Core:PXELINUX: improve the pxe_mangle_name in pxe.c the old code has so many goto sentences and labels, so improve it and remove them Signed-off-by: Liu Aleaxander --- core/fs/pxe/pxe.c | 67 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 8ac5b06b..3734e9de 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -404,53 +404,52 @@ static void get_packet_gpxe(struct open_file_t *file) */ static void pxe_mangle_name(char *dst, const char *src) { + extern void dns_resolv(void); const char *p = src; - uint32_t ip = 0; + uint32_t ip = ServerIP; int i = 0; #if GPXE - if (is_url(src)) - goto prefix_done; + if (is_url(src)) { + ip = -1; + goto store; + } #endif - ip = ServerIP; - if (*p == 0) - goto noip; - if (! strncmp(p, "::", 2)) - goto gotprefix; - else { - while (*p && strncmp(p, "::", 2)) - p ++; - if (! *p) - goto noip; + if (*p == 0 || !(p = strstr(src, "::"))) { + /* seems no ip, so make ip to 0 */ + p = src; + ip = 0; + } else if (p == src) { + /* skip the first two-colon */ + p += 2; + } else { /* - * we have a :: prefix of ip sort, it could be either a DNS + * we have a :: prefix of some sort, it could be either a DNS * name or dot-quad IP address. Try the dot-quad first. */ p = src; - if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) - goto gotprefix; - else { -#if 0 - extern void dns_resolv(void); - call16(dns_resolv, regs, regs); - p = (char *)MK_PTR(regs->ds, regs->esi.w[0]); - ip = regs->eax.l; - if (! strncmp(p, "::", 2)) - if (ip) - goto gotprefix; -#endif + if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) { + p += 2; + } else { + com32sys_t regs; + + memset(®s, 0, sizeof regs); + regs.esi.w[0] = OFFS_WRT(p, 0); + call16(dns_resolv, ®s, ®s); + p = MK_PTR(regs.ds, regs.esi.w[0]); + ip = regs.eax.l; + if (!strncmp(p, "::", 2) && ip) { + p += 2; + } else { + /* no ip, too */ + p = src; + ip = 0; + } } } - noip: - p = src; - ip = 0; - goto prefix_done; - - gotprefix: - p += 2; /* skip double colon */ - prefix_done: + store: *(uint32_t *)dst = ip; dst += 4; i = FILENAME_MAX - 5; -- cgit v1.2.1 From f3b1b1b7d183aaef287c74c397507fc34b355e99 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 16 Aug 2009 19:51:38 -0700 Subject: memdisk: make the stack size configurable Make it possible to configure the stack size on the command line, so that we can rule that out in case of problems. Signed-off-by: H. Peter Anvin --- memdisk/setup.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/memdisk/setup.c b/memdisk/setup.c index caee377a..52781694 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -729,7 +729,24 @@ static uint8_t checksum_buf(const void *buf, int count) return c; } -#define STACK_NEEDED 512 /* Number of bytes of stack */ +static int stack_needed(void) +{ + const unsigned int min_stack = 128; /* Minimum stack size */ + const unsigned int def_stack = 512; /* Default stack size */ + unsigned int v = 0; + const char *p; + + if (CMD_HASDATA(p = getcmditem("stack"))) + v = atou(p); + + if (!v) + v = def_stack; + + if (v < min_stack) + v = min_stack; + + return v; +} struct real_mode_args rm_args; @@ -749,7 +766,8 @@ void setup(const struct real_mode_args *rm_args_ptr) uint16_t dosmem_k; uint32_t stddosmem; const struct geometry *geometry; - int total_size, cmdlinelen; + unsigned int total_size; + unsigned int cmdline_len, stack_len, e820_len; com32sys_t regs; uint32_t ramdisk_image, ramdisk_size; uint32_t boot_base, rm_base; @@ -931,11 +949,15 @@ void setup(const struct real_mode_args *rm_args_ptr) map -- 12 bytes per range; we may need as many as 2 additional ranges (each insertrange() can worst-case turn 1 area into 3) plus the terminating range, over what nranges currently show. */ - cmdlinelen = strlen(shdr->cmdline) + 1; total_size = hptr->total_size; /* Actual memdisk code */ - total_size += (nranges + 3) * sizeof(ranges[0]); /* E820 memory ranges */ - total_size += cmdlinelen; /* Command line */ - total_size += STACK_NEEDED; /* Stack */ + e820_len = (nranges + 3) * sizeof(ranges[0]); + total_size += e820_len; /* E820 memory ranges */ + cmdline_len = strlen(shdr->cmdline) + 1; + total_size += cmdline_len; /* Command line */ + stack_len = stack_needed(); + total_size += stack_len; /* Stack */ + printf("Code %u, meminfo %u, cmdline %u, stack %u\n", + hptr->total_size, e820_len, cmdline_len, stack_len); printf("Total size needed = %u bytes, allocating %uK\n", total_size, (total_size + 0x3ff) >> 10); @@ -1053,7 +1075,7 @@ void setup(const struct real_mode_args *rm_args_ptr) /* Actually copy to low memory */ dpp = mempcpy(dpp, memdisk_hook, bin_size); dpp = mempcpy(dpp, ranges, (nranges + 1) * sizeof(ranges[0])); - dpp = mempcpy(dpp, shdr->cmdline, cmdlinelen + 1); + dpp = mempcpy(dpp, shdr->cmdline, cmdline_len); } /* Update various BIOS magic data areas (gotta love this shit) */ -- cgit v1.2.1 From 565c1d8c67289d8df1b16eea1e325d86385d90fb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 17 Aug 2009 19:06:01 -0700 Subject: MEMDISK: generate map files Generate map files to make debugging less painful. Signed-off-by: H. Peter Anvin --- memdisk/Makefile | 1 + memdisk/memdisk_chs.asm | 1 + memdisk/memdisk_edd.asm | 1 + 3 files changed, 3 insertions(+) diff --git a/memdisk/Makefile b/memdisk/Makefile index e1a89351..d185d87c 100644 --- a/memdisk/Makefile +++ b/memdisk/Makefile @@ -49,6 +49,7 @@ all: memdisk # e820test # tidy, clean removes everything except the final binary tidy dist: rm -f *.o *.s *.tmp *.o16 *.s16 *.bin *.lst *.elf e820test .*.d + rm -f *.map clean: tidy diff --git a/memdisk/memdisk_chs.asm b/memdisk/memdisk_chs.asm index 4b06a856..94dad9db 100644 --- a/memdisk/memdisk_chs.asm +++ b/memdisk/memdisk_chs.asm @@ -1,2 +1,3 @@ + [map all memdisk_chs.map] %define EDD 0 %include "memdisk.inc" diff --git a/memdisk/memdisk_edd.asm b/memdisk/memdisk_edd.asm index d2e7b1cf..6f909d74 100644 --- a/memdisk/memdisk_edd.asm +++ b/memdisk/memdisk_edd.asm @@ -1,2 +1,3 @@ + [map all memdisk_edd.map] %define EDD 1 %include "memdisk.inc" -- cgit v1.2.1 From 20a5fcfeb198143ca55cc21cf5ceeb6af80c2548 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Wed, 19 Aug 2009 18:47:04 +0800 Subject: Core:PXELINUX: dnsrelov.inc converted The dnsrelov converted to C. Signed-off-by: Liu Aleaxander --- core/comboot.inc | 3 +- core/dnsresolv.inc | 380 +--------------------------------------------- core/fs/pxe/dhcp_option.c | 14 +- core/fs/pxe/dnsresolv.c | 276 +++++++++++++++++++++++++++++++++ core/fs/pxe/pxe.c | 17 +-- core/fs/pxe/pxe.h | 21 ++- core/include/core.h | 8 +- 7 files changed, 317 insertions(+), 402 deletions(-) create mode 100644 core/fs/pxe/dnsresolv.c diff --git a/core/comboot.inc b/core/comboot.inc index 60c5d6fd..28f0bc2b 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -686,10 +686,11 @@ comapi_ipappend: ; INT 22h AX=0010h Resolve hostname ; %if IS_PXELINUX + extern pxe_dns_resolv comapi_dnsresolv: mov ds,P_ES mov si,P_BX - call dns_resolv + pm_call pxe_dns_resolv mov P_EAX,eax clc ret diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc index 9733282b..6d6c67a2 100644 --- a/core/dnsresolv.inc +++ b/core/dnsresolv.inc @@ -13,381 +13,15 @@ ; ; dnsresolv.inc -; -; Very simple DNS resolver (assumes recursion-enabled DNS server; -; this should be the normal thing for client-serving DNS servers.) -; - -DNS_PORT equ htons(53) ; Default DNS port -DNS_MAX_PACKET equ 512 ; Defined by protocol -; TFTP uses the range 49152-57343 -DNS_LOCAL_PORT equ htons(60053) ; All local DNS queries come from this port # -DNS_MAX_SERVERS equ 4 ; Max no of DNS servers - - section .text16 - -; -; Turn a string in DS:SI into a DNS "label set" in ES:DI. -; On return, DI points to the first byte after the label set, -; and SI to the terminating byte. -; -; On return, DX contains the number of dots encountered. -; - global dns_mangle -dns_mangle: - push ax - push bx - xor dx,dx -.isdot: - inc dx - xor al,al - mov bx,di - stosb -.getbyte: - lodsb - and al,al - jz .endstring - cmp al,':' - jz .endstring - cmp al,'.' - je .isdot - inc byte [es:bx] - stosb - jmp .getbyte -.endstring: - dec si - dec dx ; We always counted one high - cmp byte [es:bx],0 - jz .done - xor al,al - stosb -.done: - pop bx - pop ax - ret - -; -; Compare two sets of DNS labels, in DS:SI and ES:DI; the one in SI -; is allowed pointers relative to a packet in DNSRecvBuf. -; -; Assumes DS == ES. ZF = 1 if same; no registers changed. -; (Note: change reference to [di] to [es:di] to remove DS == ES assumption) -; -dns_compare: - pusha -%if 0 - -.label: - lodsb - cmp al,0C0h - jb .noptr - and al,03Fh ; Get pointer value - mov ah,al ; ... in network byte order! - lodsb - mov si,DNSRecvBuf - add si,ax - jmp .label -.noptr: - cmp al,[di] - jne .done ; Mismatch - inc di - movzx cx,al ; End label? - and cx,cx ; ZF = 1 if match - jz .done - - ; We have a string of bytes that need to match now - repe cmpsb - je .label - -.done: -%else - xor ax,ax -%endif - popa - ret - -; -; Skip past a DNS label set in DS:SI. -; -dns_skiplabel: - push ax - xor ax,ax ; AH == 0 -.loop: - lodsb - cmp al,0C0h ; Pointer? - jae .ptr - and al,al - jz .done - add si,ax - jmp .loop -.ptr: - inc si ; Pointer is two bytes -.done: - pop ax - ret - - ; DNS header format - struc dnshdr -.id: resw 1 -.flags: resw 1 -.qdcount: resw 1 -.ancount: resw 1 -.nscount: resw 1 -.arcount: resw 1 - endstruc - - ; DNS query - struc dnsquery -.qtype: resw 1 -.qclass: resw 1 - endstruc - - ; DNS RR - struc dnsrr -.type: resw 1 -.class: resw 1 -.ttl: resd 1 -.rdlength: resw 1 -.rdata: equ $ - endstruc - - section .bss16 - global LocalDomain, DNSServers +; +DNS_MAX_PACKET equ 512 ;Defined by protocol + + section .bss16 + global LocalDomain + global DNSSendBuf, DNSRecvBuf alignb 2 DNSSendBuf resb DNS_MAX_PACKET DNSRecvBuf resb DNS_MAX_PACKET LocalDomain resb 256 ; Max possible length -DNSServers resd DNS_MAX_SERVERS - - section .data16 -pxe_udp_write_pkt_dns: -.status: dw 0 ; Status -.sip: dd 0 ; Server IP -.gip: dd 0 ; Gateway IP -.lport: dw DNS_LOCAL_PORT ; Local port -.rport: dw DNS_PORT ; Remote port -.buffersize: dw 0 ; Size of packet -.buffer: dw DNSSendBuf, 0 ; off, seg of buffer - -pxe_udp_read_pkt_dns: -.status: dw 0 ; Status -.sip: dd 0 ; Source IP -.dip: dd 0 ; Destination (our) IP -.rport: dw DNS_PORT ; Remote port -.lport: dw DNS_LOCAL_PORT ; Local port -.buffersize: dw DNS_MAX_PACKET ; Max packet size -.buffer: dw DNSRecvBuf, 0 ; off, seg of buffer - - global LastDNSServer -LastDNSServer dw DNSServers - -; Actual resolver function -; Points to a null-terminated or :-terminated string in DS:SI -; and returns the name in EAX if it exists and can be found. -; If EAX = 0 on exit, the lookup failed. -; -; No segment assumptions permitted. -; - section .text16 - global dns_resolv -dns_resolv: - push ds - push es - push di - push bx - push cx - push dx - - push cs - pop es ; ES <- CS - - ; First, build query packet - mov di,DNSSendBuf+dnshdr.flags - inc word [es:di-2] ; New query ID - mov ax,htons(0100h) ; Recursion requested - stosw - mov ax,htons(1) ; One question - stosw - xor ax,ax ; No answers, NS or ARs - stosw - stosw - stosw - - call dns_mangle ; Convert name to DNS labels - - push cs ; DS <- CS - pop ds - - push si ; Save pointer to after DNS string - - ; Initialize... - mov eax,[MyIP] - mov [pxe_udp_read_pkt_dns.dip],eax - - and dx,dx - jnz .fqdn ; If we have dots, assume it's FQDN - dec di ; Remove final null - mov si,LocalDomain - call strcpy ; Uncompressed DNS label set so it ends in null -.fqdn: - - mov ax,htons(1) - stosw ; QTYPE = 1 = A - stosw ; QCLASS = 1 = IN - - sub di,DNSSendBuf - mov [pxe_udp_write_pkt_dns.buffersize],di - - ; Now, send it to the nameserver(s) - ; Outer loop: exponential backoff - ; Inner loop: scan the various DNS servers - - mov bx,TimeoutTable -.backoff: - movzx dx,byte [bx] - mov si,DNSServers -.servers: - cmp si,[LastDNSServer] - jb .moreservers - -.nomoreservers: - inc bx - cmp bx,TimeoutTableEnd - jb .backoff - - xor eax,eax ; Nothing... -.done: - pop si - pop dx - pop cx - pop bx - pop di - pop es - pop ds - ret - -.moreservers: - lodsd ; EAX <- next server - push si - push bx - push cx - push dx - - mov word [pxe_udp_write_pkt_dns.status],0 - - mov [pxe_udp_write_pkt_dns.sip],eax - mov [pxe_udp_read_pkt_dns.sip],eax - xor eax,[MyIP] - and eax,[Netmask] - jz .nogw - mov eax,[Gateway] -.nogw: - mov [pxe_udp_write_pkt_dns.gip],eax - - mov di,pxe_udp_write_pkt_dns - mov bx,PXENV_UDP_WRITE - call pxenv - jc .timeout ; Treat failed transmit as timeout - cmp word [pxe_udp_write_pkt_dns.status],0 - jne .timeout - - mov cx,[BIOS_timer] -.waitrecv: - mov ax,[BIOS_timer] - sub ax,cx - cmp ax,dx - jae .timeout - - mov word [pxe_udp_read_pkt_dns.status],0 - mov word [pxe_udp_read_pkt_dns.buffersize],DNS_MAX_PACKET - mov di,pxe_udp_read_pkt_dns - mov bx,PXENV_UDP_READ - call pxenv - and ax,ax - jnz .waitrecv - cmp [pxe_udp_read_pkt_dns.status],ax - jnz .waitrecv - - ; Got a packet, deal with it... - mov si,DNSRecvBuf - lodsw - cmp ax,[DNSSendBuf] ; ID - jne .waitrecv ; Not ours - - lodsw ; flags - xor al,80h ; Query#/Answer bit - test ax,htons(0F80Fh) - jnz .badness - - lodsw - xchg ah,al ; ntohs - mov cx,ax ; Questions echoed - lodsw - xchg ah,al ; ntohs - push ax ; Replies - lodsw ; NS records - lodsw ; Authority records - - jcxz .qskipped -.skipq: - call dns_skiplabel ; Skip name - add si,4 ; Skip question trailer - loop .skipq - -.qskipped: - pop cx ; Number of replies - jcxz .badness - -.parseanswer: - mov di,DNSSendBuf+dnshdr_size - call dns_compare - pushf - call dns_skiplabel - mov ax,[si+8] ; RDLENGTH - xchg ah,al ; ntohs - popf - jnz .notsame - cmp dword [si],htons(1)*0x10001 ; TYPE = A, CLASS = IN? - jne .notsame - cmp ax,4 ; RDLENGTH = 4? - jne .notsame - ; - ; We hit paydirt here... - ; - mov eax,[si+10] -.gotresult: - add sp,8 ; Drop timeout information - jmp .done - -.notsame: - add si,10 - add si,ax - loop .parseanswer - -.badness: - ; We got back no data from this server. - ; Unfortunately, for a recursive, non-authoritative - ; query there is no such thing as an NXDOMAIN reply, - ; which technically means we can't draw any - ; conclusions. However, in practice that means the - ; domain doesn't exist. If this turns out to be a - ; problem, we may want to add code to go through all - ; the servers before giving up. - - ; If the DNS server wasn't capable of recursion, and - ; isn't capable of giving us an authoritative reply - ; (i.e. neither AA or RA set), then at least try a - ; different setver... - - test word [DNSRecvBuf+dnshdr.flags],htons(0480h) - jz .timeout - - xor eax,eax - jmp .gotresult -.timeout: - pop dx - pop cx - pop bx - pop si - jmp .servers + section .text16 \ No newline at end of file diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c index 5c81fbdd..b44f20de 100644 --- a/core/fs/pxe/dhcp_option.c +++ b/core/fs/pxe/dhcp_option.c @@ -29,25 +29,19 @@ static void dns_servers(void *data, int opt_len) num = DNS_MAX_SERVERS; for (i = 0; i < num; i++) { - DNSServers[i] = *(uint32_t *)data; + dns_server[i] = *(uint32_t *)data; data += 4; } - - /* NOT SURE FOR NOW */ - LastDNSServer = OFFS_WRT(&DNSServers[num - 1], 0); } static void local_domain(void *data, int opt_len) { - com32sys_t regs; char *p = (char *)data + opt_len; + char *ld = LocalDomain; char end = *p; - - memset(®s, 0, sizeof regs); + *p = '\0'; /* Zero-terminate option */ - regs.esi.w[0] = OFFS_WRT(data, 0); - regs.edi.w[0] = OFFS_WRT(LocalDomain, 0); - call16(dns_mangle, ®s, NULL); + dns_mangle(&ld, (char **)&data); *p = end; /* Resotre ending byte */ } diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c new file mode 100644 index 00000000..081b049b --- /dev/null +++ b/core/fs/pxe/dnsresolv.c @@ -0,0 +1,276 @@ +#include +#include +#include +#include "pxe.h" + +/* + * The DNS header structure + */ +struct dnshdr { + uint16_t id; + uint16_t flags; + /* number of entries in the question section */ + uint16_t qdcount; + /* number of resource records in the answer section */ + uint16_t ancount; + /* number of name server resource records in the authority records section*/ + uint16_t nscount; + /* number of resource records in the additional records section */ + uint16_t arcount; +} __attribute__ ((packed)); + +/* + * The DNS query structure + */ +struct dnsquery { + uint16_t qtype; + uint16_t qclass; +} __attribute__ ((packed)); + +/* + * The DNS Resource recodes structure + */ +struct dnsrr { + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t rdlength; /* The lenght of this rr data */ + char rdata[]; +} __attribute__ ((packed)); + + +uint32_t dns_server[DNS_MAX_SERVERS] = {0, }; + +/* + * Turn a string in _src_ into a DNS "label set" in _dst_; returns the + * number of dots encountered. On return, both src and dst are updated. + */ +int dns_mangle(char **dst, char **src) +{ + char *p = *src; + char *q = *dst; + int dots = 0; + int flag = 0; + char c; + + while (1) { + c = *p++; + if (c == 0 || c == ':') + break; + if (c == '.') { + dots++; + flag = *q; + *q++ = 0; + continue; + } + + flag++; + *q++ = c; + } + + if (flag) + *dst++ = 0; + + /* update the strings */ + *src = --p; + *dst = q; + return dots; +} + + +/* + * Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s1_ + * is allowed pointers relative to a packet in DNSRecvBuf. + * + */ +static int dns_compare(char *s1, char *s2) +{ +#if 0 + while (1) { + if (*s1 < 0xc0) + break; + s1 = DNSRecvBuf + (((*s1++ & 0x3f) << 8) | (*s1++)); + } + if (*s1 == 0) + return 1; + else if (*s1++ != *s2++) + return 0; /* not same */ + else + return !strcmp(s1, s2); +#else + (void)s1; + (void)s2; + return 1; +#endif +} + +/* + * Skip past a DNS label set in DS:SI + */ +static char *dns_skiplabel(char *dns) +{ + uint8_t c; + + while (1) { + c = *dns++; + if (c >= 0xc0) + return ++dns; /* pointer is two bytes */ + if (c == 0) + return dns; + dns += c; + } +} + +/* + * Actual resolver function + * Points to a null-terminated or :-terminated string in _name_ + * and returns the ip addr in _ip_ if it exists and can be found. + * If _ip_ = 0 on exit, the lookup failed. _name_ will be updated + * + */ +uint32_t dns_resolv(char **name) +{ + char *p; + int err; + int dots; + int same; + int rd_len; + int ques, reps; /* number of questions and replies */ + uint8_t timeout; + const uint8_t *timeout_ptr = TimeoutTable; + uint16_t oldtime; + uint32_t srv; + uint32_t *srv_ptr = dns_server; + struct dnshdr *hd1 = (struct dnshdr *)DNSSendBuf; + struct dnshdr *hd2 = (struct dnshdr *)DNSRecvBuf; + struct dnsquery *query; + struct dnsrr *rr; + static __lowmem struct pxe_udp_write_pkt uw_pkt; + static __lowmem struct pxe_udp_read_pkt ur_pkt; + + /* First, fill the DNS header struct */ + hd1->id++; /* New query ID */ + hd1->flags = htons(0x0100); /* Recursion requested */ + hd1->qdcount = htons(1); /* One question */ + hd1->ancount = 0; /* No answers */ + hd1->nscount = 0; /* No NS */ + hd1->arcount = 0; /* No AR */ + + p = DNSSendBuf + sizeof(struct dnshdr); + dots = dns_mangle(&p, name); /* store the CNAME */ + + if (!dots) { + p--; /* Remove final null */ + /* Uncompressed DNS label set so it ends in null */ + strcpy(p, LocalDomain); + } + + /* Fill the DNS query packet */ + query = (struct dnsquery *)p; + query->qtype = htons(1); /* QTYPE = 1 = A */ + query->qclass = htons(1); /* QCLASS = 1 = IN */ + p += sizeof(struct dnsquery); + + /* Now send it to name server */ + timeout_ptr = TimeoutTable; + timeout = *timeout_ptr++; + while ((srv = *srv_ptr++)) { + uw_pkt.status = 0; + uw_pkt.sip = srv; + uw_pkt.gip = ((srv ^ MyIP) & Netmask) ? Gateway : 0; + uw_pkt.lport = DNS_LOCAL_PORT; + uw_pkt.rport = DNS_PORT; + uw_pkt.buffersize = p - DNSSendBuf; + uw_pkt.buffer[0] = OFFS_WRT(DNSSendBuf, 0); + uw_pkt.buffer[1] = 0; + err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); + if (err || uw_pkt.status != 0) + continue; + + oldtime = BIOS_timer; + while (oldtime + timeout <= BIOS_timer) { + ur_pkt.status = 0; + ur_pkt.sip = srv; + ur_pkt.dip = MyIP; + ur_pkt.rport = DNS_PORT; + ur_pkt.lport = DNS_LOCAL_PORT; + ur_pkt.buffersize = DNS_MAX_PACKET; + ur_pkt.buffer[0] = OFFS_WRT(DNSRecvBuf, 0); + ur_pkt.buffer[1] = 0; + err = pxe_call(PXENV_UDP_READ, &ur_pkt); + if (err || ur_pkt.status) + continue; + + /* Got a packet, deal with it... */ + if (hd2->id == hd1->id) + break; + } + if (BIOS_timer > oldtime + timeout) { + /* time out */ + timeout = *timeout_ptr++; + if (!timeout) + return 0; /* All time ticks run out */ + else + continue; /* try next */ + } + if ((hd2->flags ^ 0x80) & htons(0xf80f)) + goto badness; + + ques = htons(hd2->qdcount); /* Questions */ + reps = htons(hd2->ancount); /* Replies */ + p = DNSRecvBuf + sizeof(struct dnshdr); + while (ques--) { + p = dns_skiplabel(p); /* Skip name */ + p += 4; /* Skip question trailer */ + } + + /* Parse the replies */ + while (reps--) { + same = dns_compare(p, (char *)(DNSSendBuf + sizeof(struct dnshdr))); + rr = (struct dnsrr *)dns_skiplabel(p); + rd_len = htons(rr->rdlength); + if (same && rd_len == 4 && + htons(rr->type) == 1 && /* TYPE == A */ + htons(rr->class) == 1 ) /* CLASS == IN */ + return *(uint32_t *)rr->rdata; + + /* not the one we want, try next */ + p += sizeof(struct dnsrr) + rd_len; + } + + badness: + /* + * + ; We got back no data from this server. + ; Unfortunately, for a recursive, non-authoritative + ; query there is no such thing as an NXDOMAIN reply, + ; which technically means we can't draw any + ; conclusions. However, in practice that means the + ; domain doesn't exist. If this turns out to be a + ; problem, we may want to add code to go through all + ; the servers before giving up. + + ; If the DNS server wasn't capable of recursion, and + ; isn't capable of giving us an authoritative reply + ; (i.e. neither AA or RA set), then at least try a + ; different setver... + */ + if (hd2->flags == htons(0x480)) + continue; + + break; /* failed */ + } + + return 0; +} + + +/* + * the one should be called from ASM file + */ +void pxe_dns_resolv(com32sys_t *regs) +{ + char *name = MK_PTR(regs->ds, regs->esi.w[0]); + + regs->eax.l = dns_resolv(&name); +} diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 3734e9de..87d03ebb 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -13,7 +13,7 @@ static int has_gpxe; static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; int HaveUUID = 0; -static const uint8_t TimeoutTable[] = { +const uint8_t TimeoutTable[] = { 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 }; @@ -226,7 +226,7 @@ static const char *parse_dotquad(const char *ip_str, uint32_t *res) * the ASM pxenv function wrapper, return 1 if error, or 0 * */ -static int pxe_call(int opcode, void *data) +int pxe_call(int opcode, void *data) { extern void pxenv(void); com32sys_t in_regs, out_regs; @@ -404,7 +404,6 @@ static void get_packet_gpxe(struct open_file_t *file) */ static void pxe_mangle_name(char *dst, const char *src) { - extern void dns_resolv(void); const char *p = src; uint32_t ip = ServerIP; int i = 0; @@ -431,15 +430,9 @@ static void pxe_mangle_name(char *dst, const char *src) p = src; if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) { p += 2; - } else { - com32sys_t regs; - - memset(®s, 0, sizeof regs); - regs.esi.w[0] = OFFS_WRT(p, 0); - call16(dns_resolv, ®s, ®s); - p = MK_PTR(regs.ds, regs.esi.w[0]); - ip = regs.eax.l; - if (!strncmp(p, "::", 2) && ip) { + } else { + ip = dns_resolv(&p); + if (ip && !strncmp(p, "::", 2)) { p += 2; } else { /* no ip, too */ diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 1f66032e..e1138f13 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -29,7 +29,6 @@ #define TFTP_BLOCKSIZE_LG2 9 #define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) #define PKTBUF_SEG 0x4000 -#define DNS_MAX_SERVERS 4 #define is_digit(c) (((c) >= '0') && ((c) <= '9')) @@ -59,6 +58,14 @@ #define BOOTP_OPTION_MAGIC htonl(0x63825363) #define MAC_MAX 32 +/* Defines for DNS */ +#define DNS_PORT htons(53) /* Default DNS port */ +#define DNS_MAX_PACKET 512 /* Defined by protocol */ +/* All local DNS queries come from this port */ +#define DNS_LOCAL_PORT htons(60053) +#define DNS_MAX_SERVERS 4 /* Max no of DNS servers */ + + /* * structures */ @@ -210,10 +217,20 @@ struct gpxe_file_read { } __attribute__ ((packed)); /* - * functions + * functions */ + +/* pxe.c */ int ip_ok(uint32_t); +int pxe_call(int, void *); + +/* dhcp_options.c */ void parse_dhcp(int); void parse_dhcp_options(void *, int, int); +/* dnsresolv.c */ +int dns_mangle(char **, char **); +uint32_t dns_resolve(char **); + + #endif /* pxe.h */ diff --git a/core/include/core.h b/core/include/core.h index ad00492d..f8be6912 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -44,8 +44,6 @@ __noreturn _kaboom(void); /* * externs for pxelinux */ -extern void dns_mangle(void); - extern uint32_t ServerIP; extern uint32_t MyIP; extern uint32_t Netmask; @@ -73,8 +71,9 @@ extern char packet_buf[]; extern char IPOption[]; extern char DotQuadBuf[]; -extern uint32_t DNSServers[]; -extern uint16_t LastDNSServer; +extern uint32_t dns_server[]; +extern char DNSSendBuf[]; +extern char DNSRecvBuf[]; extern uint16_t RealBaseMem; extern uint16_t APIVer; @@ -87,5 +86,6 @@ extern uint8_t UUIDType; extern char UUID[]; extern volatile uint16_t BIOS_timer; +extern const uint8_t TimeoutTable[]; #endif /* CORE_H */ -- cgit v1.2.1 From f856e30a7162319b9743d6742cec9d41b33269b5 Mon Sep 17 00:00:00 2001 From: erwan Date: Thu, 20 Aug 2009 00:19:44 +0200 Subject: hdt: Fixing memory corruption Impact: Improve stability In some case, sectors_to_size can return a 8 char long string like "1000 MiB". In such case, some buffer were corrupted. This is now fixed by a size[9] instead of size[8]. --- com32/hdt/hdt-cli-disk.c | 6 +++--- com32/hdt/hdt-menu-disk.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index ffbec4f1..ef67abf6 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -62,7 +62,7 @@ static void show_partition_information(struct driveinfo *drive_info, int partition_offset, int nb_partitions_seen) { - char size[8]; + char size[9]; char *parttype; int error = 0; char error_buffer[MAX_DISK_ERRNO]; @@ -122,7 +122,7 @@ void main_show_disk(int argc, char **argv, int i = drive - 0x80; struct driveinfo *d = &hardware->disk_info[i]; char error_buffer[MAX_DISK_ERRNO]; - char disk_size[8]; + char disk_size[9]; detect_disks(hardware); if (!hardware->disk_info[i].cbios) @@ -177,7 +177,7 @@ void disks_summary(int argc __unused, char** argv __unused, if (!hardware->disk_info[i].cbios) continue; /* Invalid geometry */ struct driveinfo *d = &hardware->disk_info[i]; - char disk_size[8]; + char disk_size[9]; if ((int) d->edd_params.sectors > 0) sectors_to_size((int) d->edd_params.sectors, disk_size); diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 487d1e45..794efd24 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -80,7 +80,7 @@ static void compute_partition_information(struct driveinfo *drive_info, int partition_offset, int nb_partitions_seen) { - char size[8]; + char size[9]; char *parttype; unsigned int start, end; char buffer[SUBMENULEN+1]; @@ -169,7 +169,7 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, int previous_size, size; char previous_unit[3], unit[3]; // GB - char size_iec[8]; // GiB + char size_iec[9]; // GiB sectors_to_size_dec(previous_unit, &previous_size, unit, &size, d[disk_number].edd_params.sectors); sectors_to_size(d[disk_number].edd_params.sectors, size_iec); -- cgit v1.2.1 From 3b4e0f5e471de0fc6a9c335343a4ad52f8b29aeb Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 19 Aug 2009 21:12:57 -0700 Subject: disklib: fix extended partition code gert1 reported some issues using disklib with HDT. As it turned out, the code that iterated through ebrs in an extended partition was broken: ebr offsets need to be relative to the start of that partition. Misc.: fix memory leak. Signed-off-by: Pierre-Alexandre Meyer Signed-off-by: Erwan Velu --- com32/gpllib/disk/msdos.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c index e69aa71b..1d1ef4df 100644 --- a/com32/gpllib/disk/msdos.c +++ b/com32/gpllib/disk/msdos.c @@ -34,39 +34,42 @@ static inline int msdos_magic_present(const char *ptab) /** * process_extended_partition - execute a callback for each partition contained listed in an ebr * @drive_info: driveinfo struct describing the drive - * @partition_offset: Absolute start (lba) of the partition + * @partition_offset: Absolute start (lba) of the extended partition + * @ebr_offset: Relative start (lba) of the current ebr processed within + * the extended partition * @callback: Callback to execute * @error: Buffer for I/O errors * @nb_part_seen: Number of partitions found on the disk so far **/ static int process_extended_partition(struct driveinfo *drive_info, - int partition_offset, - p_callback callback, - int nb_part_seen) + const int partition_offset, + const int ebr_offset, + p_callback callback, + int nb_part_seen) { int status = 0; /* The ebr is located at the first sector of the extended partition */ char* ebr = malloc(SECTOR * sizeof(char)); - if (read_sectors(drive_info, ebr, partition_offset, 1) == -1) - return -1; + if (read_sectors(drive_info, ebr, partition_offset + ebr_offset, 1) == -1) + goto abort; /* Check msdos magic signature */ if (!msdos_magic_present(ebr)) - return -1; + goto abort; struct part_entry *ptab = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); for (int i = 0; i < 4; i++) { if (status == -1) - return -1; + goto abort; if (!is_extended_partition(&ptab[i])) { /* * This EBR partition table entry points to the * logical partition associated to that EBR */ - int logical_partition_start = partition_offset + ptab[i].start_lba; + int logical_partition_start = ebr_offset + ptab[i].start_lba; /* Last EBR in the extended partition? */ if (!logical_partition_start) @@ -84,16 +87,22 @@ static int process_extended_partition(struct driveinfo *drive_info, nb_part_seen++; callback(drive_info, &ptab[i], - logical_partition_start, + partition_offset + logical_partition_start, nb_part_seen); } else status = process_extended_partition(drive_info, - partition_offset + ptab[i].start_lba, + partition_offset, + ptab[i].start_lba, callback, nb_part_seen); } + free(ebr); return 0; + +abort: + free(ebr); + return -1; } /** @@ -117,7 +126,7 @@ static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, &ptab[i], ptab[i].start_lba, i+1); - status = process_extended_partition(drive_info, ptab[i].start_lba, callback, 4); + status = process_extended_partition(drive_info, ptab[i].start_lba, 0, callback, 4); } else callback(drive_info, &ptab[i], -- cgit v1.2.1 From e8fd12251a93ed182a35389c1992358e9253a37b Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Wed, 19 Aug 2009 21:20:40 -0700 Subject: hdt: fix disklib display We currently display the first sector after the end of an extended. Fix it (-1). Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 2 +- com32/hdt/hdt-menu-disk.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index ef67abf6..ee7c10df 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -71,7 +71,7 @@ static void show_partition_information(struct driveinfo *drive_info, int i = nb_partitions_seen; start = partition_offset; - end = start + ptab->length; + end = start + ptab->length - 1; if (ptab->length > 0) sectors_to_size(ptab->length, size); diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index 794efd24..e5644078 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -99,7 +99,7 @@ static void compute_partition_information(struct driveinfo *drive_info, set_menu_pos(SUBMENU_Y,SUBMENU_X); start = partition_offset; - end = start + ptab->length; + end = start + ptab->length - 1; if (ptab->length > 0) sectors_to_size(ptab->length, size); -- cgit v1.2.1 From daba7ba9c40e257fcb6da033c54dd807f81b1a25 Mon Sep 17 00:00:00 2001 From: erwan Date: Thu, 20 Aug 2009 06:24:16 +0200 Subject: hdt: 0.3.4 Impact: New release 0.3.4 is now out ! --- com32/hdt/hdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index 94ce1f48..04c0e664 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -32,7 +32,7 @@ #define PRODUCT_NAME "Hardware Detection Tool" #define AUTHOR "Erwan Velu" #define CONTACT "hdt@zytor.com" -#define VERSION "0.3.3" +#define VERSION "0.3.4" #define NB_CONTRIBUTORS 2 #define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"} -- cgit v1.2.1 From 4d5026e38d741a75b0fdfd2a04f40dc43f544b76 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 21 Aug 2009 11:41:43 +0800 Subject: Core:PXELINUX: dns_resolv problem resolved. Now the dns_resolv program can work correctly now except sometimes you should add some DNS servers manually by yourself if your current DNS server can not work, this mostly happen when you use something like Qemu. And, we added a host c32 module written by hpa, as a dns resolver test. Signed-off-by: Liu Aleaxander --- com32/modules/Makefile | 2 +- com32/modules/host.c | 42 ++++++++++++++++++++++++++++++++++++++++++ core/fs/pxe/dhcp_option.c | 11 +++++++++++ core/fs/pxe/dnsresolv.c | 34 ++++++++++++++++++++-------------- 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 com32/modules/host.c diff --git a/com32/modules/Makefile b/com32/modules/Makefile index e3155bd5..e0e103b7 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -21,7 +21,7 @@ include ../MCONFIG MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \ sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \ - vpdtest.c32 + vpdtest.c32 host.c32 TESTFILES = diff --git a/com32/modules/host.c b/com32/modules/host.c new file mode 100644 index 00000000..94ca876d --- /dev/null +++ b/com32/modules/host.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +static struct in_addr dnsresolve(const char *hostname) +{ + com32sys_t regs; + struct in_addr addr; + + strcpy(__com32.cs_bounce, hostname); + + regs.eax.w[0] = 0x0010; + regs.es = SEG(__com32.cs_bounce); + regs.ebx.w[0] = OFFS(__com32.cs_bounce); + __intcall(0x22, ®s, ®s); + + addr.s_addr = regs.eax.l; + return addr; +} + +int main(int argc, char *argv[]) +{ + int i; + struct in_addr addr; + + openconsole(&dev_null_r, &dev_stdcon_w); + + for (i = 1; i < argc; i++) { + addr = dnsresolve(argv[i]); + + printf("%-39s %08X %d.%d.%d.%d\n", + argv[i], ntohl(addr.s_addr), + ((uint8_t *)&addr.s_addr)[0], + ((uint8_t *)&addr.s_addr)[1], + ((uint8_t *)&addr.s_addr)[2], + ((uint8_t *)&addr.s_addr)[3]); + } + + return 0; +} diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c index b44f20de..4e40060d 100644 --- a/core/fs/pxe/dhcp_option.c +++ b/core/fs/pxe/dhcp_option.c @@ -32,6 +32,17 @@ static void dns_servers(void *data, int opt_len) dns_server[i] = *(uint32_t *)data; data += 4; } + +#if 0 + /* + * if you find you got no corret DNS server, you can add + * it here manually. BUT be carefull the DNS_MAX_SERVERS + */ + if (i < DNS_MAX_SERVERS ) { + dns_server[i++] = your_master_dns_server; + dns_server[i++] = your_second_dns_server; + } +#endif } static void local_domain(void *data, int opt_len) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index 081b049b..ec6342f3 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -41,6 +41,7 @@ struct dnsrr { uint32_t dns_server[DNS_MAX_SERVERS] = {0, }; + /* * Turn a string in _src_ into a DNS "label set" in _dst_; returns the * number of dots encountered. On return, both src and dst are updated. @@ -49,9 +50,12 @@ int dns_mangle(char **dst, char **src) { char *p = *src; char *q = *dst; - int dots = 0; - int flag = 0; + char *count_ptr; char c; + int dots = 0; + + count_ptr = q; + *q++ = 0; while (1) { c = *p++; @@ -59,17 +63,17 @@ int dns_mangle(char **dst, char **src) break; if (c == '.') { dots++; - flag = *q; + count_ptr = q; *q++ = 0; continue; } - flag++; + *count_ptr += 1; *q++ = c; } - if (flag) - *dst++ = 0; + if (*count_ptr) + *q++ = 0; /* update the strings */ *src = --p; @@ -107,17 +111,17 @@ static int dns_compare(char *s1, char *s2) /* * Skip past a DNS label set in DS:SI */ -static char *dns_skiplabel(char *dns) +static char *dns_skiplabel(char *label) { uint8_t c; while (1) { - c = *dns++; + c = *label++; if (c >= 0xc0) - return ++dns; /* pointer is two bytes */ + return ++label; /* pointer is two bytes */ if (c == 0) - return dns; - dns += c; + return label; + label += c; } } @@ -174,7 +178,8 @@ uint32_t dns_resolv(char **name) /* Now send it to name server */ timeout_ptr = TimeoutTable; timeout = *timeout_ptr++; - while ((srv = *srv_ptr++)) { + while (srv_ptr < dns_server + DNS_MAX_SERVERS) { + srv = *srv_ptr++; uw_pkt.status = 0; uw_pkt.sip = srv; uw_pkt.gip = ((srv ^ MyIP) & Netmask) ? Gateway : 0; @@ -188,7 +193,7 @@ uint32_t dns_resolv(char **name) continue; oldtime = BIOS_timer; - while (oldtime + timeout <= BIOS_timer) { + while (oldtime + timeout >= BIOS_timer) { ur_pkt.status = 0; ur_pkt.sip = srv; ur_pkt.dip = MyIP; @@ -227,7 +232,8 @@ uint32_t dns_resolv(char **name) /* Parse the replies */ while (reps--) { same = dns_compare(p, (char *)(DNSSendBuf + sizeof(struct dnshdr))); - rr = (struct dnsrr *)dns_skiplabel(p); + p = dns_skiplabel(p); + rr = (struct dnsrr *)p; rd_len = htons(rr->rdlength); if (same && rd_len == 4 && htons(rr->type) == 1 && /* TYPE == A */ -- cgit v1.2.1 From 67ce2dc42d50baf6bdd0c53dc2df442cdfcf179a Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 22 Aug 2009 09:42:37 -0700 Subject: hdt: fix CLI crash when parsing unsupported geometries Remove extra free() calls: these were needed before the introduction of the disklib errno. We apparently forgot to remove them. Reported-by: Gert Hulselmans Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index ee7c10df..080e1327 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -95,7 +95,6 @@ static void show_partition_information(struct driveinfo *drive_info, } else if (error) { get_error(&error_buffer); more_printf("%s\n", error_buffer); - free(error_buffer); } more_printf("\n"); @@ -147,7 +146,6 @@ void main_show_disk(int argc, char **argv, if (parse_partition_table(d, &show_partition_information) == -1) { get_error(&error_buffer); more_printf("%s\n", error_buffer); - free(error_buffer); } } -- cgit v1.2.1 From 9ffe8b0b4e2ff9b98813521f79c840d983424f82 Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 22 Aug 2009 10:34:40 -0700 Subject: hdt: make get_error behaves like perror This simplifies buffer handling. Misc.: clean some old error code handling. Signed-off-by: Pierre-Alexandre Meyer --- com32/gplinclude/disk/errno_disk.h | 3 --- com32/gpllib/disk/error.c | 7 +++---- com32/hdt/hdt-cli-disk.c | 15 ++++----------- com32/hdt/hdt-common.c | 7 ------- com32/hdt/hdt-menu-disk.c | 8 ++------ 5 files changed, 9 insertions(+), 31 deletions(-) diff --git a/com32/gplinclude/disk/errno_disk.h b/com32/gplinclude/disk/errno_disk.h index 055eaf58..60b511fc 100644 --- a/com32/gplinclude/disk/errno_disk.h +++ b/com32/gplinclude/disk/errno_disk.h @@ -10,9 +10,6 @@ #ifndef _ERRNO_DISK_H #define _ERRNO_DISK_H -/* Max length of the error string */ -#define MAX_DISK_ERRNO 9 - extern int errno_disk; /* Prefix with ED to avoid confusion with errno */ diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 2b82c359..1853092b 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -8,8 +8,7 @@ * ----------------------------------------------------------------------- */ #include -#include - +#include #include /** @@ -18,7 +17,7 @@ * * Fill @buffer_ptr with the last errno_disk **/ -void get_error(void* buffer_ptr) +void get_error(const char* s) { - snprintf(buffer_ptr, MAX_DISK_ERRNO, "Disklib: error %d\n", errno_disk); + fprintf(stderr, "%s: error %d\n", s, errno_disk); } diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 080e1327..fec98a15 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -64,8 +64,6 @@ static void show_partition_information(struct driveinfo *drive_info, { char size[9]; char *parttype; - int error = 0; - char error_buffer[MAX_DISK_ERRNO]; unsigned int start, end; int i = nb_partitions_seen; @@ -90,12 +88,8 @@ static void show_partition_information(struct driveinfo *drive_info, ptab->ostype, parttype); /* Extra info */ - if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) { + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) more_printf("%s", " (Swsusp sig. detected)"); - } else if (error) { - get_error(&error_buffer); - more_printf("%s\n", error_buffer); - } more_printf("\n"); @@ -120,7 +114,6 @@ void main_show_disk(int argc, char **argv, int i = drive - 0x80; struct driveinfo *d = &hardware->disk_info[i]; - char error_buffer[MAX_DISK_ERRNO]; char disk_size[9]; detect_disks(hardware); @@ -143,9 +136,9 @@ void main_show_disk(int argc, char **argv, disk_size, (int) d->edd_params.bytes_per_sector, (int) d->edd_params.sectors_per_track, remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); - if (parse_partition_table(d, &show_partition_information) == -1) { - get_error(&error_buffer); - more_printf("%s\n", error_buffer); + if (parse_partition_table(d, &show_partition_information)) { + fprintf(stderr, "Error parsing disk 0x%X\n", d->disk); + get_error("parse_partition_table"); } } diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 0f98ab9e..80305a3e 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -252,7 +252,6 @@ void detect_disks(struct s_hardware *hardware) { int i = -1; int err; - char *error_msg; if (hardware->disk_detection) return; @@ -270,12 +269,6 @@ void detect_disks(struct s_hardware *hardware) if (err == -1 || !hardware->disk_info[i].cbios) continue; - if (err) { - get_error(err, &error_msg); - more_printf("Error 0x%Xh while reading disk 0x%X:\n\t%s\n", - err, drive, error_msg); - free(error_msg); - } hardware->disks_count++; } } diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index e5644078..bd33bdf3 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -210,12 +210,8 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, dn=disk_number; parse_partition_table(&d[disk_number], &show_partition_information); - if (parse_partition_table(&d[disk_number], &compute_partition_information) == -1) { - char error_buffer[MAX_DISK_ERRNO]; - get_error(&error_buffer); - snprintf(buffer, sizeof buffer, "I/O error : %s", error_buffer); - snprintf(statbuffer, sizeof statbuffer, "I/O error : %s", error_buffer); - add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + if (!parse_partition_table(&d[disk_number], &compute_partition_information)) { + get_error("parse_partition_table"); menu[nb_sub_disk_menu].items_count++; } -- cgit v1.2.1 From b7ec0f07b339aed8bd2b8da3603b0ee9a6a7417a Mon Sep 17 00:00:00 2001 From: Pierre-Alexandre Meyer Date: Sat, 22 Aug 2009 11:08:04 -0700 Subject: hdt: enhance error reporting in the CLI (disk) parse_partition_table can fail for two reasons: disk I/O error or unrecognized partition layout (non msdos, corrupt, ...). In the latter case, we were displaying Error parsing disk 0x80 parse_partition_table: error 0 which is confusing. We now display Disk 0x80: unrecognized partition layout or the errno_disk in case of I/O errors. Signed-off-by: Pierre-Alexandre Meyer --- com32/hdt/hdt-cli-disk.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index fec98a15..4e2994d9 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -137,8 +137,13 @@ void main_show_disk(int argc, char **argv, remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); if (parse_partition_table(d, &show_partition_information)) { - fprintf(stderr, "Error parsing disk 0x%X\n", d->disk); - get_error("parse_partition_table"); + if (errno_disk) { + fprintf(stderr, "I/O error parsing disk 0x%X\n", d->disk); + get_error("parse_partition_table"); + } else { + fprintf(stderr, "Disk 0x%X: unrecognized partition layout\n", d->disk); + } + fprintf(stderr, "\n"); } } -- cgit v1.2.1 From cd20609d1e2bb3dad3881cc7f6286f165b9a2d42 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 24 Aug 2009 15:41:30 -0700 Subject: netinet/in.h: fix output types We need casts not just on input but on output, in order to make sure only the correct bits are visible. Signed-off-by: H. Peter Anvin --- com32/include/netinet/in.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h index ea0a1788..ccf04750 100644 --- a/com32/include/netinet/in.h +++ b/com32/include/netinet/in.h @@ -6,7 +6,9 @@ #include #include -#define __htons_macro(v) (((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8)) +#define __htons_macro(v) ((uint16_t) \ + (((uint16_t)(v) << 8) | \ + ((uint16_t)(v) >> 8))) static inline __constfunc uint16_t __htons(uint16_t v) { @@ -16,31 +18,29 @@ static inline __constfunc uint16_t __htons(uint16_t v) #define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x)) #define ntohs(x) htons(x) -#define __htonl_macro(v) ((((uint32_t)(v) & 0x000000ff) << 24) | \ - (((uint32_t)(v) & 0x0000ff00) << 8) | \ +#define __htonl_macro(v) ((uint32_t) \ + ((((uint32_t)(v) & 0x000000ff) << 24) | \ + (((uint32_t)(v) & 0x0000ff00) << 8) | \ (((uint32_t)(v) & 0x00ff0000) >> 8) | \ - (((uint32_t)(v) & 0xff000000) >> 24)) + (((uint32_t)(v) & 0xff000000) >> 24))) static inline __constfunc uint32_t __htonl(uint32_t v) { - if (__builtin_constant_p(v)) { - return __htonl_macro(v); - } else { - asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" : "+q"(v)); - return v; - } + asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" + : "+q" (v)); + return v; } #define htonl(x) (__builtin_constant_p(x) ? __htonl_macro(x) : __htonl(x)) #define ntohl(x) htonl(x) -#define __htonq_macro(v) \ - (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ - (__htonl_macro((uint32_t)((uint64_t)(v) >> 32)))) +#define __htonq_macro(v) ((uint64_t) \ + (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ + (__htonl_macro((uint32_t)((uint64_t)(v) >> 32))))) static inline __constfunc uint64_t __htonq(uint64_t v) { - return ((uint64_t) __htonl(v) << 32) | __htonl(v >> 32); + return ((uint64_t)__htonl(v) << 32) | __htonl(v >> 32); } #define htonq(x) (__builtin_constant_p(x) ? __htonq_macro(x) : __htonq(x)) -- cgit v1.2.1 From 6b1a837bf5794bee3a2a3e1733bea321d12a89ad Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 24 Aug 2009 15:43:21 -0700 Subject: dnsresolv: fix timeouts, clean up types Fix timeouts: it was way too easy to make the code give up, which often resulted in a zero response even if valid data would soon be available. Also avoid passing char ** when we don't really need it. Signed-off-by: H. Peter Anvin --- core/fs/pxe/dhcp_option.c | 4 ++-- core/fs/pxe/dnsresolv.c | 44 +++++++++++++++++++++++--------------------- core/fs/pxe/pxe.h | 2 +- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c index 4e40060d..9bd20b07 100644 --- a/core/fs/pxe/dhcp_option.c +++ b/core/fs/pxe/dhcp_option.c @@ -52,8 +52,8 @@ static void local_domain(void *data, int opt_len) char end = *p; *p = '\0'; /* Zero-terminate option */ - dns_mangle(&ld, (char **)&data); - *p = end; /* Resotre ending byte */ + dns_mangle(&ld, data); + *p = end; /* Restore ending byte */ } static void vendor_encaps(void *data, int opt_len) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index ec6342f3..2d90cc7f 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -44,11 +44,10 @@ uint32_t dns_server[DNS_MAX_SERVERS] = {0, }; /* * Turn a string in _src_ into a DNS "label set" in _dst_; returns the - * number of dots encountered. On return, both src and dst are updated. + * number of dots encountered. On return, *dst is updated. */ -int dns_mangle(char **dst, char **src) +int dns_mangle(char **dst, const char *p) { - char *p = *src; char *q = *dst; char *count_ptr; char c; @@ -76,7 +75,6 @@ int dns_mangle(char **dst, char **src) *q++ = 0; /* update the strings */ - *src = --p; *dst = q; return dots; } @@ -87,7 +85,7 @@ int dns_mangle(char **dst, char **src) * is allowed pointers relative to a packet in DNSRecvBuf. * */ -static int dns_compare(char *s1, char *s2) +static bool dns_compare(const char *s1, const char *s2) { #if 0 while (1) { @@ -96,15 +94,15 @@ static int dns_compare(char *s1, char *s2) s1 = DNSRecvBuf + (((*s1++ & 0x3f) << 8) | (*s1++)); } if (*s1 == 0) - return 1; + return true; else if (*s1++ != *s2++) - return 0; /* not same */ + return false; /* not same */ else return !strcmp(s1, s2); #else (void)s1; (void)s2; - return 1; + return true; #endif } @@ -132,7 +130,7 @@ static char *dns_skiplabel(char *label) * If _ip_ = 0 on exit, the lookup failed. _name_ will be updated * */ -uint32_t dns_resolv(char **name) +uint32_t dns_resolv(const char *name) { char *p; int err; @@ -193,7 +191,7 @@ uint32_t dns_resolv(char **name) continue; oldtime = BIOS_timer; - while (oldtime + timeout >= BIOS_timer) { + while (1) { ur_pkt.status = 0; ur_pkt.sip = srv; ur_pkt.dip = MyIP; @@ -209,14 +207,15 @@ uint32_t dns_resolv(char **name) /* Got a packet, deal with it... */ if (hd2->id == hd1->id) break; - } - if (BIOS_timer > oldtime + timeout) { - /* time out */ - timeout = *timeout_ptr++; - if (!timeout) - return 0; /* All time ticks run out */ - else - continue; /* try next */ + + if ((uint16_t)(BIOS_timer-oldtime) >= timeout) { + /* time out */ + timeout = *timeout_ptr++; + if (!timeout) + return 0; /* All time ticks run out */ + else + goto again; + } } if ((hd2->flags ^ 0x80) & htons(0xf80f)) goto badness; @@ -265,6 +264,9 @@ uint32_t dns_resolv(char **name) continue; break; /* failed */ + + again: + continue; } return 0; @@ -276,7 +278,7 @@ uint32_t dns_resolv(char **name) */ void pxe_dns_resolv(com32sys_t *regs) { - char *name = MK_PTR(regs->ds, regs->esi.w[0]); - - regs->eax.l = dns_resolv(&name); + const char *name = MK_PTR(regs->ds, regs->esi.w[0]); + + regs->eax.l = dns_resolv(name); } diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index e1138f13..c2b905fc 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -229,7 +229,7 @@ void parse_dhcp(int); void parse_dhcp_options(void *, int, int); /* dnsresolv.c */ -int dns_mangle(char **, char **); +int dns_mangle(char **, const char *); uint32_t dns_resolve(char **); -- cgit v1.2.1 From 94eca0c06e03a9d50be4e7de06b3a79af8f47083 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 24 Aug 2009 16:32:48 -0700 Subject: dnsresolv: compare returned name; "better" CNAME handling Compare the returned name with the name we requested. Handle CNAMEs by overwriting the requested name with the CNAME, however, we really should: a) rescan the packet from the beginning; b) send a new request if we get no A record for the CNAME. Signed-off-by: H. Peter Anvin --- core/fs/pxe/dnsresolv.c | 109 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index 2d90cc7f..b2c36b7f 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -3,6 +3,13 @@ #include #include "pxe.h" +/* DNS CLASS values we care about */ +#define CLASS_IN 1 + +/* DNS TYPE values we care about */ +#define TYPE_A 1 +#define TYPE_CNAME 5 + /* * The DNS header structure */ @@ -81,29 +88,61 @@ int dns_mangle(char **dst, const char *p) /* - * Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s1_ - * is allowed pointers relative to a packet in DNSRecvBuf. + * Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s2_ + * is allowed pointers relative to a packet in buf. * */ -static bool dns_compare(const char *s1, const char *s2) +static bool dns_compare(const void *s1, const void *s2, const void *buf) { -#if 0 + const uint8_t *q = s1; + const uint8_t *p = s2; + unsigned int c0, c1; + while (1) { - if (*s1 < 0xc0) - break; - s1 = DNSRecvBuf + (((*s1++ & 0x3f) << 8) | (*s1++)); + c0 = p[0]; + if (c0 >= 0xc0) { + /* Follow pointer */ + c1 = p[1]; + p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1; + } else if (c0) { + c0++; /* Include the length byte */ + if (memcmp(q, p, c0)) + return false; + q += c0; + p += c0; + } else { + return *q == 0; + } + } +} + +/* + * Copy a DNS label into a buffer, considering the possibility that we might + * have to follow pointers relative to "buf". + * Returns a pointer to the first free byte *after* the terminal null. + */ +static void *dns_copylabel(void *dst, const void *src, const void *buf) +{ + uint8_t *q = dst; + const uint8_t *p = src; + unsigned int c0, c1; + + while (1) { + c0 = p[0]; + if (c0 >= 0xc0) { + /* Follow pointer */ + c1 = p[1]; + p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1; + } else if (c0) { + c0++; /* Include the length byte */ + memcpy(q, p, c0); + p += c0; + q += c0; + } else { + *q++ = 0; + return q; + } } - if (*s1 == 0) - return true; - else if (*s1++ != *s2++) - return false; /* not same */ - else - return !strcmp(s1, s2); -#else - (void)s1; - (void)s2; - return true; -#endif } /* @@ -169,8 +208,8 @@ uint32_t dns_resolv(const char *name) /* Fill the DNS query packet */ query = (struct dnsquery *)p; - query->qtype = htons(1); /* QTYPE = 1 = A */ - query->qclass = htons(1); /* QCLASS = 1 = IN */ + query->qtype = htons(TYPE_A); + query->qclass = htons(CLASS_IN); p += sizeof(struct dnsquery); /* Now send it to name server */ @@ -230,15 +269,31 @@ uint32_t dns_resolv(const char *name) /* Parse the replies */ while (reps--) { - same = dns_compare(p, (char *)(DNSSendBuf + sizeof(struct dnshdr))); + same = dns_compare(DNSSendBuf + sizeof(struct dnshdr), + p, DNSRecvBuf); p = dns_skiplabel(p); rr = (struct dnsrr *)p; - rd_len = htons(rr->rdlength); - if (same && rd_len == 4 && - htons(rr->type) == 1 && /* TYPE == A */ - htons(rr->class) == 1 ) /* CLASS == IN */ - return *(uint32_t *)rr->rdata; - + rd_len = ntohs(rr->rdlength); + if (same && ntohs(rr->class) == CLASS_IN) { + switch (ntohs(rr->type)) { + case TYPE_A: + if (rd_len == 4) + return *(uint32_t *)rr->rdata; + break; + case TYPE_CNAME: + dns_copylabel(DNSSendBuf + sizeof(struct dnshdr), + rr->rdata, DNSRecvBuf); + /* + * We should probably rescan the packet from the top + * here, and technically we might have to send a whole + * new request here... + */ + break; + default: + break; + } + } + /* not the one we want, try next */ p += sizeof(struct dnsrr) + rd_len; } -- cgit v1.2.1 From edfcc9f1e582d0adb4da88330505771eccd59e6a Mon Sep 17 00:00:00 2001 From: Aleaxander Date: Wed, 26 Aug 2009 05:32:38 +0800 Subject: Core:pxelinux: fix the dns_resolv call reference in pxe.c The current dns_resolv function doesn't update the _name_ string, so we should use the strstr things to make the _p_ pointer to point to the right address we want. Signed-off-by: Liu Aleaxander --- core/fs/pxe/pxe.c | 4 ++-- core/fs/pxe/pxe.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 87d03ebb..b300d6af 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -431,8 +431,8 @@ static void pxe_mangle_name(char *dst, const char *src) if ((p = parse_dotquad(p, &ip)) && !strncmp(p, "::", 2)) { p += 2; } else { - ip = dns_resolv(&p); - if (ip && !strncmp(p, "::", 2)) { + ip = dns_resolv(p); + if (ip && (p = strchr(p, ':')) && p[1] == ':') { p += 2; } else { /* no ip, too */ diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index c2b905fc..a775f26c 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -230,7 +230,7 @@ void parse_dhcp_options(void *, int, int); /* dnsresolv.c */ int dns_mangle(char **, const char *); -uint32_t dns_resolve(char **); +uint32_t dns_resolv(char *); #endif /* pxe.h */ -- cgit v1.2.1 From 788da3035b2cf325658d6123b1bef73c67290f68 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 25 Aug 2009 21:19:26 -0700 Subject: NEWS: update for 3.83 --- NEWS | 6 ++++++ doc/memdisk.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/NEWS b/NEWS index 735bed73..594cf755 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,12 @@ Changes in 3.83: * MEMDISK: fix problems booting from USB on Thinkpads, and possibly other machines or hardware combinations. * isohybrid: fix the -id option. + * HDT: updated to version 0.3.4. + * MEMDISK: the stack size is now configurable, with the stack= + option. + * Simple menu: fix Ctrl-W (word erase) in command-line edit. + * Simple menu: fix crash on some platforms. + * Gfxboot: fixes to the configuration file parsing. Changes in 3.82: * isohybrid: fix the -partok logic for loading from a partition. diff --git a/doc/memdisk.txt b/doc/memdisk.txt index 79d76400..58ec748b 100644 --- a/doc/memdisk.txt +++ b/doc/memdisk.txt @@ -122,6 +122,12 @@ f) The following option can be used to pause to view the messages: pause Wait for a keypress right before booting +g) The following option can be used to set the real-mode stack size. + The default is 512 bytes, but if there is a failure it might be + interesting to set it to something larger: + + stack=size Set the stack to "size" bytes + Some interesting things to note: -- cgit v1.2.1 From 6fcebf4ed2be8de96ff106c3755c7776f1c66804 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Thu, 27 Aug 2009 07:37:44 +0800 Subject: Core: opendir/readdir/closedir stuff added Here're some big changes: 1. The vfs-dir stuff added. 2. The dir-functions in com32/lib are mostly rewritten. 3. with little change on rosh for avoid the compile error Well, I don't think it's a good vfs-dir interface. Signed-off-by: Liu Aleaxander --- com32/include/dirent.h | 15 +++-- com32/lib/closedir.c | 26 ++++---- com32/lib/opendir.c | 20 +++--- com32/lib/readdir.c | 40 ++--------- com32/modules/Makefile | 2 +- com32/modules/dir.c | 35 ++++++++++ com32/rosh/rosh.c | 11 ++-- core/comboot.inc | 18 ++--- core/dir.c | 84 +++++++++++++++++++++++ core/extern.inc | 6 +- core/fs.c | 1 + core/fs/fat/fat.c | 176 +++++++++++++++++++++++-------------------------- core/include/dir.h | 32 +++++++++ core/include/fs.h | 12 ++++ 14 files changed, 297 insertions(+), 181 deletions(-) create mode 100644 com32/modules/dir.c create mode 100644 core/dir.c create mode 100644 core/include/dir.h diff --git a/com32/include/dirent.h b/com32/include/dirent.h index d99b21fb..0fc2e135 100644 --- a/com32/include/dirent.h +++ b/com32/include/dirent.h @@ -15,17 +15,18 @@ #endif struct dirent { - long d_ino; /* Inode/File number */ - off_t d_size; /* Size of file */ - mode_t d_mode; /* Type of file */ + uint32_t d_ino; + uint32_t d_off; + uint16_t d_reclen; + uint16_t d_type; char d_name[NAME_MAX + 1]; }; typedef struct { - short dd_stat; /* status return from last lookup */ - uint16_t dd_fd; - size_t dd_sect; - char dd_name[NAME_MAX + 1]; /* directory */ + uint16_t dd_stat; + uint16_t dd_sect; + uint64_t dd_offset; + char dd_name[NAME_MAX + 1]; } DIR; __extern DIR *opendir(const char *); diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c index f8bbbabd..dcf17049 100644 --- a/com32/lib/closedir.c +++ b/com32/lib/closedir.c @@ -13,17 +13,19 @@ int closedir(DIR * dir) { - int rv; - com32sys_t regs; - if (dir == NULL) { + int rv = -1; + + if (dir) { + /* + com32sys_t regs; + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0022; + regs.esi.l = OFFS_WRT(dir, 0); + __com32.cs_intcall(0x22, ®s, ®s); + */ + free(dir); rv = 0; - } else { - memset(®s, 0, sizeof regs); /* ?Needed? */ - regs.eax.w[0] = 0x0022; - regs.esi.w[0] = dir->dd_fd; - __com32.cs_intcall(0x22, ®s, ®s); - free(dir); /* garbage collection? */ - rv = 0; - } - return rv; + } + + return rv; } diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c index 6fc0f14f..669a04a2 100644 --- a/com32/lib/opendir.c +++ b/com32/lib/opendir.c @@ -13,11 +13,9 @@ DIR *opendir(const char *pathname) { - DIR *newdir; + DIR *newdir = NULL; com32sys_t regs; - - newdir = NULL; - + strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size); regs.eax.w[0] = 0x0020; @@ -25,14 +23,14 @@ DIR *opendir(const char *pathname) regs.es = SEG(__com32.cs_bounce); __com32.cs_intcall(0x22, ®s, ®s); - + if (!(regs.eflags.l & EFLAGS_CF)) { - /* Initialization: malloc() then zero */ - newdir = calloc(1, sizeof(DIR)); - strcpy(newdir->dd_name, pathname); - newdir->dd_fd = regs.esi.w[0]; - newdir->dd_sect = regs.eax.l; - newdir->dd_stat = 0; + /* Initialization: malloc() then zero */ + newdir = calloc(1, sizeof(DIR)); + strcpy(newdir->dd_name, pathname); + newdir->dd_sect = regs.eax.l; + newdir->dd_offset = 0; + newdir->dd_stat = 0; } /* We're done */ diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c index 2ec7c7b3..7fca4761 100644 --- a/com32/lib/readdir.c +++ b/com32/lib/readdir.c @@ -13,42 +13,16 @@ struct dirent *readdir(DIR * dir) { - struct dirent *newde; + struct dirent *newde = NULL;; com32sys_t regs; - - newde = NULL; - if ((dir != NULL) && (dir->dd_fd != 0) && (dir->dd_stat >= 0)) { - memset(__com32.cs_bounce, 0, 32); - memset(®s, 0, sizeof(regs)); - + + if ((dir !=NULL) && (dir->dd_sect != 0) && (dir->dd_stat != 0xffff)) { + memset(®s, 0, sizeof(regs)); regs.eax.w[0] = 0x0021; - regs.esi.w[0] = dir->dd_fd; - regs.edi.w[0] = OFFS(__com32.cs_bounce); - regs.es = SEG(__com32.cs_bounce); - + regs.esi.l = (uint32_t)dir; __com32.cs_intcall(0x22, ®s, ®s); - - /* Don't do this as we won't be able to rewind. - dir->dd_fd = regs.esi.w[0]; /* Shouldn't be needed? */ - if ((!(regs.eflags.l & EFLAGS_CF)) && (regs.esi.w[0] != 0)) { - newde = calloc(1, sizeof(newde)); - if (newde != NULL) { - strcpy(newde->d_name, __com32.cs_bounce); - newde->d_mode = regs.edx.b[0]; - newde->d_size = regs.eax.l; - newde->d_ino = regs.ebx.l; - dir->dd_stat = 1; - } else { - dir->dd_stat = -2; - errno = ENOMEM; - } - } else { - dir->dd_stat = -1; - errno = EIO; /* Is this the right nmber? */ - } - } else { - errno = EBADF; + newde = (struct dirent *)(regs.eax.l); } - + return newde; } diff --git a/com32/modules/Makefile b/com32/modules/Makefile index e0e103b7..23cd31fd 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -21,7 +21,7 @@ include ../MCONFIG MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \ sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \ - vpdtest.c32 host.c32 + vpdtest.c32 host.c32 dir.c32 TESTFILES = diff --git a/com32/modules/dir.c b/com32/modules/dir.c new file mode 100644 index 00000000..a3c98151 --- /dev/null +++ b/com32/modules/dir.c @@ -0,0 +1,35 @@ +/* + * A dir test module + */ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + DIR *dir; + struct dirent *de; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc != 2) { + printf("Usage: dir direcotry\n"); + return 0; + } + + dir = opendir(argv[1]); + if (dir == NULL) { + printf("Unable to read dir: %s\n", argv[1]); + return 0; + } + + while ((de = readdir(dir)) != NULL) + printf("%s\n", de->d_name); + + closedir(dir); + + return 0; +} + diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 631c780e..c634a940 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -389,7 +389,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) ROSH_DEBUG("--'%s'\n", filestr); } fd = open(filestr, O_RDONLY); - if (fd != -1) { + if (fd == -1) { status = fstat(fd, &fdstat); if (S_ISDIR(fdstat.st_mode)) { ROSH_DEBUG("PATH '%s' is a directory\n", ifilstr); @@ -428,14 +428,14 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) filepos = 0; d = opendir(filestr); if (d != NULL) { - printf("DIR:'%s' %08x %8d\n", d->dd_name, d->dd_fd, - d->dd_sect); + printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, + d->dd_offset); de = readdir(d); while (de != NULL) { filepos++; #ifdef DO_DEBUG // if (strlen(de->d_name) > 25) de->d_name[25] = 0; - switch (de->d_mode) { + switch (de->d_type) { case 16: ty = 'D'; break; @@ -445,8 +445,6 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) default: ty = '*'; } - printf("@%8d:%8d:%4d ", (int)de->d_ino, (int)de->d_size, - de->d_mode); #endif /* DO_DEBUG */ // printf("%s\n", de->d_name); printf("'%s'\n", de->d_name); @@ -458,7 +456,6 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) de = readdir(d); // if(filepos>15){ de = NULL; printf("Force Break\n");} } - printf("Dir.dd_fd: '%8d'\n", d->dd_fd); closedir(d); } else { rosh_error(0, "dir:NULL", filestr); diff --git a/core/comboot.inc b/core/comboot.inc index 28f0bc2b..b078aa57 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -901,13 +901,10 @@ comapi_getcwd: ; %if IS_SYSLINUX comapi_opendir: - push ds - mov ds,P_ES + mov es,P_ES mov si,P_SI mov di,InitRD - pm_call mangle_name - pop ds - pm_call searchdir + pm_call opendir jz comapi_err ; Didn't find a directory cmp eax,0 jz comapi_err ; Found nothing @@ -925,14 +922,9 @@ comapi_opendir equ comapi_err ; %if IS_SYSLINUX comapi_readdir: - mov es,P_ES - mov di,P_DI - mov si,P_SI - pm_call vfat_readdir - mov P_EAX,eax - mov P_DL,dl - mov P_EBX,ebx - mov P_SI,si + mov esi,P_ESI ; The address of DIR structure + pm_call readdir + mov P_EAX,eax ; The address of newly read dirent structure ret %else comapi_readdir equ comapi_err diff --git a/core/dir.c b/core/dir.c new file mode 100644 index 00000000..07011256 --- /dev/null +++ b/core/dir.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +/* The dir log structure, to log the status of the dir_buf. */ +struct dir_log { + int offset; /* how far from the dir_buf */ + int index; /* which dir entry have we go */ +}; +static struct dir_log log = {0, 0}; + +/* The dir buffer used by fill_dir to store the newly read dirs*/ +#define DB_SIZE 2048 +char dir_buf[DB_SIZE]; + +void opendir(com32sys_t *regs) +{ + int ds = regs->ds; /* save ds */ + + regs->ds = regs->es; + regs->es = ds; + mangle_name(regs); + regs->ds = ds; /* restore ds */ + searchdir(regs); +} + +/* + * Fill the dir buffer; return 1 for not full, 0 for full + */ +int fill_dir(struct dirent *de) +{ + int de_len = de->d_reclen; + if (log.offset + de_len <= DB_SIZE) { + memcpy(dir_buf + log.offset, de, de_len); + log.offset += de_len; + log.index ++; + return 1; + } + + return 0; +} + +/* + * Read one dirent at one time. + * + * @input: _esi_ register stores the address of DIR structure + * @output: _eax_ register stores the address of newly read dirent structure + */ +void readdir(com32sys_t *regs) +{ + extern struct fs_info *this_fs; + DIR *dir = (DIR *)regs->esi.l; + struct dirent *de = NULL; + static int offset; + + /* If we haven't fill the dir buffer, fill it */ + if (log.index == 0) { + this_fs->fs_ops->readdir(this_fs, dir); + if (log.offset == 0) { + regs->eax.l = 0; + return; + } + offset = 0; /* reset the _offset_ */ + } + + if (offset < log.offset) { + de = (struct dirent *)(dir_buf + offset); + offset += de->d_reclen; + } + if (offset >= log.offset) /* reach the end of buffer, reset it */ + memset(&log, 0, sizeof log); + + /* Return the newly read de in _eax_ register */ + regs->eax.l = (uint32_t)de; +} + +void closedir(com32sys_t *regs) +{ + regs->esi.w[0] = 0; +} + + diff --git a/core/extern.inc b/core/extern.inc index d944bb1f..37024ec1 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -16,9 +16,7 @@ extern fs_init, searchdir, getfssec, mangle_name, load_config extern unmangle_name, close_file -%if IS_SYSLINUX - ; fat.c - extern vfat_readdir -%endif + ; dir.c + extern opendir, readdir, readdir %endif ; EXTERN_INC diff --git a/core/fs.c b/core/fs.c index 2804468b..17303782 100644 --- a/core/fs.c +++ b/core/fs.c @@ -22,6 +22,7 @@ static struct file *alloc_file(void) for (i = 0; i < MAX_OPEN; i++) { if (!file->open_file) return file; + file++; } return NULL; diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 2f0bac74..f219995d 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "fat_fs.h" #define ROOT_DIR_WORD 0x002f @@ -345,7 +346,9 @@ static void vfat_mangle_name(char *dst, const char *src) /* Strip terminal slashes or whitespace */ while (1) { if (dst == p) - break; + break; + if (*(dst-1) == '/' && dst-1 == p) /* it's the '/' case */ + break; if ((*(dst-1) != '/') && (*(dst-1) != '.')) break; @@ -654,8 +657,7 @@ static void vfat_searchdir(char *filename, struct file *file) } if (attr & 0x10) { - dir_sector = PrevDir; - found_dir: + found_dir: open_file = alloc_fill_dir(dir_sector); /* * for dir, we use the file->file_len to store the sector number @@ -678,69 +680,64 @@ static void vfat_searchdir(char *filename, struct file *file) -/** - * readdir: - * +/* * read one file from a directory - * - * returns the file's name in the filename string buffer - * - * @param: filename - * @param: file - * + * return 1 if error, or 0 if success */ -void vfat_readdir(com32sys_t *regs)/* - struct fs_info *fs, struct open_file_t* dir_file, - char* filename, uint32_t *file_len, uint8_t *attr) - */ +void vfat_readdir(struct fs_info *fs, DIR *dir) { uint32_t sector, sec_off; /* make it to be 1 to check if we have met a long name entry before */ uint8_t id = 1; uint8_t init_id, next_id; + uint8_t checksum = 0; uint8_t entries_left; int i; - - char *filename = MK_PTR(regs->es, regs->edi.w[0]); - struct open_file_t *dir_file = MK_PTR(regs->ds, regs->esi.w[0]); - + int not_full = 1; + struct dirent de; + char *de_name = de.d_name; struct cache_struct *cs; - struct fat_dir_entry *dir; - struct fat_long_name_entry *long_dir; - struct open_file_t file; - - sector = dir_file->file_sector; - sec_off = dir_file->file_bytesleft; + struct fat_dir_entry *fat_dir; + struct fat_long_name_entry *long_dir; + + sector = dir->dd_sect; + sec_off = dir->dd_offset; if (!sector) - goto fail; - + return 1; entries_left = (SECTOR_SIZE - sec_off) >> 5; cs = get_cache_block(this_fs->fs_dev, sector); - dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ + fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ - while (1) { - if (dir->name[0] == 0) - goto fail; - - if (dir->attr == FAT_ATTR_LONG_NAME) { + while (not_full) { + if (!entries_left) { + sector = nextsector(fs, sector); + if (!sector) + goto end; + cs = get_cache_block(fs->fs_dev, sector); + fat_dir = (struct fat_dir_entry *)cs->data; + } + + if (fat_dir->name[0] == 0) + goto end; + if (fat_dir->attr == FAT_ATTR_LONG_NAME) { /* it's a long name */ - long_dir = (struct fat_long_name_entry *)dir; + long_dir = (struct fat_long_name_entry *)fat_dir; if (long_dir->id & 0x40) { + checksum = long_dir->checksum; init_id = id = long_dir->id & 0x3f; id--; } else { next_id = (long_dir->id & 0x3f) - 1; id--; - if (id != next_id) + if (id != next_id || long_dir->checksum != checksum) goto next_entry; } long_entry_name(long_dir); - memcpy(filename + id * 13, entry_name, 13); - + memcpy(de_name + id * 13, entry_name, 13); - /* + /* * we need go on with the next entry * and we will fall through to next entry */ @@ -748,73 +745,65 @@ void vfat_readdir(com32sys_t *regs)/* } else { /* it's a short entry */ - if (!id) /* we got a long name match */ - break; + if (!id) { + /* Got a long name match */ + //if (get_checksum(fat_dir->name) != checksum) + //goto next_entry; + + /* reset _id_ and _checksum_ */ + id = 1; + checksum = 0; + goto fill; + } - if (dir->attr & FAT_ATTR_VOLUME_ID) - goto next_entry; + if (fat_dir->attr & FAT_ATTR_VOLUME_ID || + get_checksum(fat_dir->name) != checksum ) + goto next_entry; for(i = 0; i < 8; i ++) { - if (dir->name[i] == ' ') + if (fat_dir->name[i] == ' ') break; - *filename++ = dir->name[i]; - } - - *filename++ = '.'; - + *de_name++ = fat_dir->name[i]; + } + *de_name++ = '.'; for (i = 8; i < 11; i ++) { - if (dir->name[i] == ' ') + if (fat_dir->name[i] == ' ') break; - *filename ++ = dir->name[i]; - } - + *de_name ++ = fat_dir->name[i]; + } /* check if we have got an extention */ - if (*(filename - 1) == '.') - *(filename - 1) = '\0'; + if (*(de_name - 1) == '.') + *(de_name - 1) = '\0'; else - *filename = '\0'; - - break; + *de_name = '\0'; + + fill: + de.d_type = fat_dir->attr; + de.d_reclen = DIR_REC_LEN(de.d_name); + not_full = fill_dir(&de); + de_name = de.d_name; /* reset the de_name pointer */ } next_entry: - dir ++; - entries_left --; - - if (!entries_left) { - sector = nextsector(this_fs, sector); - if (!sector) - goto fail; - cs = get_cache_block(this_fs->fs_dev, sector); - dir = (struct fat_dir_entry *)cs->data; - } + entries_left --; + fat_dir ++; } - /* finally , we get what we want */ - entries_left --; - if (!entries_left) { - sector = nextsector(this_fs, sector); + /* dir buffer filled, now it's time to update the DIR structure */ + if (!entries_left) { + sector = nextsector(fs, sector); if (!sector) - goto fail; - dir_file->file_bytesleft = 0; - } else - dir_file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); - dir_file->file_sector = sector; - - file.file_sector = sector; - file.file_bytesleft = (SECTOR_SIZE - (entries_left << DIRENT_SHIFT)) & 0xffff; - - regs->eax.l = dir->file_size; - regs->ebx.l = first_sector(dir); - regs->edx.b[0] = dir->attr; - - return; - - fail: - //close_dir(dir); - regs->eax.l = 0; - regs->esi.w[0] = 0; - regs->eflags.l |= EFLAGS_CF; + return 1; + dir->dd_offset = 0; + } else { + dir->dd_offset = SECTOR_SIZE - (entries_left << 5); + } + dir->dd_sect = sector; + return; + + end: + /* Reach the end of this directory */ + dir->dd_stat = -1; } static void vfat_load_config(com32sys_t *regs) @@ -908,5 +897,6 @@ const struct fs_ops vfat_fs_ops = { .close_file = vfat_close_file, .mangle_name = vfat_mangle_name, .unmangle_name = generic_unmangle_name, - .load_config = vfat_load_config + .load_config = vfat_load_config, + .readdir = vfat_readdir }; diff --git a/core/include/dir.h b/core/include/dir.h new file mode 100644 index 00000000..454ca483 --- /dev/null +++ b/core/include/dir.h @@ -0,0 +1,32 @@ +#ifndef DIR_H +#define DIR_H + +#include +#include +#include +#include +#include "disk.h" + +struct dirent { + uint32_t d_ino; + uint32_t d_off; + uint16_t d_reclen; + uint16_t d_type; + char d_name[256]; +}; + +typedef struct { + uint16_t dd_stat; + uint16_t dd_sect; + sector_t dd_offset; + char dd_name[256]; +} DIR; + +#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 + +/* + * funtions + */ +int fill_dir(struct dirent *); + +#endif /* dir.h */ diff --git a/core/include/fs.h b/core/include/fs.h index 04e85ef8..d16a5689 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -7,6 +7,7 @@ #include #include "core.h" #include "disk.h" +#include "dir.h" /* * Maximum number of open files. This is *currently* constrained by the @@ -49,6 +50,9 @@ struct fs_ops { void (*mangle_name)(char *, const char *); char * (*unmangle_name)(char *, const char *); void (*load_config)(com32sys_t *); + + /* the _dir_ stuff */ + void (*readdir)(struct fs_info *, DIR *); }; enum dev_type {CHS, EDD}; @@ -83,4 +87,12 @@ static inline bool not_whitespace(char c) return (unsigned char)c > ' '; } +/* + * functions + */ +void mangle_name(com32sys_t *); +void searchdir(com32sys_t *); + + + #endif /* FS_H */ -- cgit v1.2.1 From c29a8049d462815774bbce8f80a8471a985bafcd Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 28 Aug 2009 18:27:51 +0800 Subject: Core: vfs-dir stuff re-implemented We fist make it simple, as told by hpa. Here're the changes: 1, The DIR structure changed, just a file pointer included. 2. So, the open/close/read-dir stuff in com32/lib/ changed again. 3. We read one stuff from every readdir call. Signed-off-by: Liu Aleaxander --- com32/include/dirent.h | 7 ++-- com32/lib/closedir.c | 16 ++++----- com32/lib/opendir.c | 7 ++-- com32/lib/readdir.c | 4 +-- com32/modules/dir.c | 1 + com32/rosh/rosh.c | 3 +- core/comboot.inc | 8 +++-- core/dir.c | 68 ++++++++------------------------------ core/extern.inc | 2 +- core/fs.c | 29 ++++++++--------- core/fs/fat/fat.c | 88 ++++++++++++++++++++++++-------------------------- core/include/dir.h | 12 +++---- core/include/fs.h | 8 +++-- 13 files changed, 101 insertions(+), 152 deletions(-) diff --git a/com32/include/dirent.h b/com32/include/dirent.h index 0fc2e135..d2bfd627 100644 --- a/com32/include/dirent.h +++ b/com32/include/dirent.h @@ -22,11 +22,10 @@ struct dirent { char d_name[NAME_MAX + 1]; }; +struct file; + typedef struct { - uint16_t dd_stat; - uint16_t dd_sect; - uint64_t dd_offset; - char dd_name[NAME_MAX + 1]; + struct file *dd_dir; } DIR; __extern DIR *opendir(const char *); diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c index dcf17049..9e43dd4d 100644 --- a/com32/lib/closedir.c +++ b/com32/lib/closedir.c @@ -16,15 +16,13 @@ int closedir(DIR * dir) int rv = -1; if (dir) { - /* - com32sys_t regs; - memset(®s, 0, sizeof regs); - regs.eax.w[0] = 0x0022; - regs.esi.l = OFFS_WRT(dir, 0); - __com32.cs_intcall(0x22, ®s, ®s); - */ - free(dir); - rv = 0; + com32sys_t regs; + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0022; + regs.esi.l = (uint32_t)dir; + __com32.cs_intcall(0x22, ®s, ®s); + free(dir); + rv = 0; } return rv; diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c index 669a04a2..70f74c15 100644 --- a/com32/lib/opendir.c +++ b/com32/lib/opendir.c @@ -27,12 +27,9 @@ DIR *opendir(const char *pathname) if (!(regs.eflags.l & EFLAGS_CF)) { /* Initialization: malloc() then zero */ newdir = calloc(1, sizeof(DIR)); - strcpy(newdir->dd_name, pathname); - newdir->dd_sect = regs.eax.l; - newdir->dd_offset = 0; - newdir->dd_stat = 0; + newdir->dd_dir = (struct file *)regs.eax.l; } - + /* We're done */ return newdir; } diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c index 7fca4761..6c95bd6d 100644 --- a/com32/lib/readdir.c +++ b/com32/lib/readdir.c @@ -13,16 +13,14 @@ struct dirent *readdir(DIR * dir) { - struct dirent *newde = NULL;; + struct dirent *newde; com32sys_t regs; - if ((dir !=NULL) && (dir->dd_sect != 0) && (dir->dd_stat != 0xffff)) { memset(®s, 0, sizeof(regs)); regs.eax.w[0] = 0x0021; regs.esi.l = (uint32_t)dir; __com32.cs_intcall(0x22, ®s, ®s); newde = (struct dirent *)(regs.eax.l); - } return newde; } diff --git a/com32/modules/dir.c b/com32/modules/dir.c index a3c98151..badc37de 100644 --- a/com32/modules/dir.c +++ b/com32/modules/dir.c @@ -20,6 +20,7 @@ int main(int argc, char *argv[]) } dir = opendir(argv[1]); + printf("back from in main ...? \n"); if (dir == NULL) { printf("Unable to read dir: %s\n", argv[1]); return 0; diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index c634a940..862497be 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -428,8 +428,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) filepos = 0; d = opendir(filestr); if (d != NULL) { - printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, - d->dd_offset); + //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset); de = readdir(d); while (de != NULL) { filepos++; diff --git a/core/comboot.inc b/core/comboot.inc index b078aa57..7f9b3a9b 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -900,6 +900,7 @@ comapi_getcwd: ; INT 22h AX=0020h Open directory ; %if IS_SYSLINUX + global comapi_opendir comapi_opendir: mov es,P_ES mov si,P_SI @@ -909,8 +910,6 @@ comapi_opendir: cmp eax,0 jz comapi_err ; Found nothing mov P_EAX,eax - mov P_CX,SECTOR_SIZE - mov P_SI,si clc ret %else @@ -933,7 +932,10 @@ comapi_readdir equ comapi_err ; ; INT 22h AX=0022h Close directory ; -comapi_closedir equ comapi_close +comapi_closedir: + mov esi,P_ESI ; The address of DIR structure + pm_call closedir + ret ; ; INT 22h AX=0023h Query shuffler size diff --git a/core/dir.c b/core/dir.c index 07011256..1bc8a260 100644 --- a/core/dir.c +++ b/core/dir.c @@ -4,42 +4,15 @@ #include #include -/* The dir log structure, to log the status of the dir_buf. */ -struct dir_log { - int offset; /* how far from the dir_buf */ - int index; /* which dir entry have we go */ -}; -static struct dir_log log = {0, 0}; - -/* The dir buffer used by fill_dir to store the newly read dirs*/ -#define DB_SIZE 2048 -char dir_buf[DB_SIZE]; +extern struct fs_info *this_fs; +/* + * open dir, return the file structure pointer in _eax_, or NULL if failed + */ void opendir(com32sys_t *regs) { - int ds = regs->ds; /* save ds */ - - regs->ds = regs->es; - regs->es = ds; - mangle_name(regs); - regs->ds = ds; /* restore ds */ - searchdir(regs); -} - -/* - * Fill the dir buffer; return 1 for not full, 0 for full - */ -int fill_dir(struct dirent *de) -{ - int de_len = de->d_reclen; - if (log.offset + de_len <= DB_SIZE) { - memcpy(dir_buf + log.offset, de, de_len); - log.offset += de_len; - log.index ++; - return 1; - } - - return 0; + this_fs->fs_ops->opendir(regs); + regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]); } /* @@ -50,35 +23,22 @@ int fill_dir(struct dirent *de) */ void readdir(com32sys_t *regs) { - extern struct fs_info *this_fs; - DIR *dir = (DIR *)regs->esi.l; + DIR *dir = (DIR *)regs->esi.l; struct dirent *de = NULL; - static int offset; - - /* If we haven't fill the dir buffer, fill it */ - if (log.index == 0) { - this_fs->fs_ops->readdir(this_fs, dir); - if (log.offset == 0) { - regs->eax.l = 0; - return; - } - offset = 0; /* reset the _offset_ */ - } - - if (offset < log.offset) { - de = (struct dirent *)(dir_buf + offset); - offset += de->d_reclen; - } - if (offset >= log.offset) /* reach the end of buffer, reset it */ - memset(&log, 0, sizeof log); + if (dir->dd_dir) + de = this_fs->fs_ops->readdir(dir->dd_dir); + else + de = NULL; + /* Return the newly read de in _eax_ register */ regs->eax.l = (uint32_t)de; } void closedir(com32sys_t *regs) { - regs->esi.w[0] = 0; + DIR *dir = (DIR *)regs->esi.l; + _close_file(dir->dd_dir); } diff --git a/core/extern.inc b/core/extern.inc index 37024ec1..20adb768 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -17,6 +17,6 @@ extern unmangle_name, close_file ; dir.c - extern opendir, readdir, readdir + extern opendir, readdir, closedir %endif ; EXTERN_INC diff --git a/core/fs.c b/core/fs.c index 17303782..b6e112ad 100644 --- a/core/fs.c +++ b/core/fs.c @@ -9,7 +9,18 @@ struct fs_info *this_fs = NULL; struct fs_info fs; /* Actual file structures (we don't have malloc yet...) */ -static struct file Files[MAX_OPEN]; +struct file files[MAX_OPEN]; +/* + * Convert between a 16-bit file handle and a file structure + */ +inline uint16_t file_to_handle(struct file *file) +{ + return file ? (file - files)+1 : 0; +} +inline struct file *handle_to_file(uint16_t handle) +{ + return handle ? &files[handle-1] : NULL; +} /* * Get an empty file structure @@ -17,7 +28,7 @@ static struct file Files[MAX_OPEN]; static struct file *alloc_file(void) { int i; - struct file *file = Files; + struct file *file = files; for (i = 0; i < MAX_OPEN; i++) { if (!file->open_file) @@ -36,25 +47,13 @@ static inline void free_file(struct file *file) memset(file, 0, sizeof *file); } -static void _close_file(struct file *file) +void _close_file(struct file *file) { if (file->open_file) file->fs->fs_ops->close_file(file); free_file(file); } -/* - * Convert between a 16-bit file handle and a file structure - */ -static inline uint16_t file_to_handle(struct file *file) -{ - return file ? (file - Files)+1 : 0; -} -static inline struct file *handle_to_file(uint16_t handle) -{ - return handle ? &Files[handle-1] : NULL; -} - void load_config(com32sys_t *regs) { this_fs->fs_ops->load_config(regs); diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index f219995d..a2540420 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -659,12 +659,7 @@ static void vfat_searchdir(char *filename, struct file *file) if (attr & 0x10) { found_dir: open_file = alloc_fill_dir(dir_sector); - /* - * for dir, we use the file->file_len to store the sector number - * where the dir is. - */ - file_len = dir_sector; - } else if ((attr & 0x18) || (file_len == 0)) { + } else if ((attr & 0x18) || (file_len == 0)) { fail: file_len = 0; open_file = NULL; @@ -677,14 +672,22 @@ static void vfat_searchdir(char *filename, struct file *file) file->open_file = open_file; } - - +/* + * The open dir function, just call the searchdir function directly. + * I don't think we need call the mangle_name function first + */ +void vfat_opendir(com32sys_t *regs) +{ + char *src = MK_PTR(regs->es, regs->esi.w[0]); + char *dst = MK_PTR(regs->ds, regs->edi.w[0]); + strcpy(dst, src); + searchdir(regs); +} /* - * read one file from a directory - * return 1 if error, or 0 if success + * read one file from a directory; return the newly read de structure */ -void vfat_readdir(struct fs_info *fs, DIR *dir) +struct dirent* vfat_readdir(struct file *dir) { uint32_t sector, sec_off; /* make it to be 1 to check if we have met a long name entry before */ @@ -693,32 +696,33 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) uint8_t checksum = 0; uint8_t entries_left; int i; - int not_full = 1; - struct dirent de; + static struct dirent de; char *de_name = de.d_name; struct cache_struct *cs; struct fat_dir_entry *fat_dir; - struct fat_long_name_entry *long_dir; - - sector = dir->dd_sect; - sec_off = dir->dd_offset; + struct fat_long_name_entry *long_dir; + struct open_file_t *file = dir->open_file; + struct fs_info *fs = dir->fs; + + sector = file->file_sector; + sec_off = file->file_bytesleft; if (!sector) - return 1; + return NULL; entries_left = (SECTOR_SIZE - sec_off) >> 5; cs = get_cache_block(this_fs->fs_dev, sector); fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ - while (not_full) { + while (1) { if (!entries_left) { sector = nextsector(fs, sector); if (!sector) - goto end; + return NULL; cs = get_cache_block(fs->fs_dev, sector); fat_dir = (struct fat_dir_entry *)cs->data; } if (fat_dir->name[0] == 0) - goto end; + return NULL; if (fat_dir->attr == FAT_ATTR_LONG_NAME) { /* it's a long name */ long_dir = (struct fat_long_name_entry *)fat_dir; @@ -747,13 +751,10 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) if (!id) { /* Got a long name match */ - //if (get_checksum(fat_dir->name) != checksum) - //goto next_entry; + if (get_checksum(fat_dir->name) != checksum) + goto next_entry; - /* reset _id_ and _checksum_ */ - id = 1; - checksum = 0; - goto fill; + break; } if (fat_dir->attr & FAT_ATTR_VOLUME_ID || @@ -777,33 +778,29 @@ void vfat_readdir(struct fs_info *fs, DIR *dir) else *de_name = '\0'; - fill: - de.d_type = fat_dir->attr; - de.d_reclen = DIR_REC_LEN(de.d_name); - not_full = fill_dir(&de); - de_name = de.d_name; /* reset the de_name pointer */ + break; } next_entry: entries_left --; fat_dir ++; } - - /* dir buffer filled, now it's time to update the DIR structure */ + + /* found what we want, fill the de structure */ + de.d_reclen = DIR_REC_LEN(de.d_name); + de.d_type = fat_dir->attr; + + /* update the DIR structure */ + entries_left--; if (!entries_left) { - sector = nextsector(fs, sector); - if (!sector) - return 1; - dir->dd_offset = 0; + sector = nextsector(fs, sector); + file->file_bytesleft = 0; } else { - dir->dd_offset = SECTOR_SIZE - (entries_left << 5); + file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); } - dir->dd_sect = sector; - return; - - end: - /* Reach the end of this directory */ - dir->dd_stat = -1; + file->file_sector = sector; + + return &de; } static void vfat_load_config(com32sys_t *regs) @@ -898,5 +895,6 @@ const struct fs_ops vfat_fs_ops = { .mangle_name = vfat_mangle_name, .unmangle_name = generic_unmangle_name, .load_config = vfat_load_config, + .opendir = vfat_opendir, .readdir = vfat_readdir }; diff --git a/core/include/dir.h b/core/include/dir.h index 454ca483..04f0d090 100644 --- a/core/include/dir.h +++ b/core/include/dir.h @@ -6,6 +6,7 @@ #include #include #include "disk.h" +#include "fs.h" struct dirent { uint32_t d_ino; @@ -15,18 +16,13 @@ struct dirent { char d_name[256]; }; +struct file; + typedef struct { - uint16_t dd_stat; - uint16_t dd_sect; - sector_t dd_offset; - char dd_name[256]; + struct file *dd_dir; } DIR; #define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 -/* - * funtions - */ -int fill_dir(struct dirent *); #endif /* dir.h */ diff --git a/core/include/fs.h b/core/include/fs.h index d16a5689..a8b02945 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -52,7 +52,8 @@ struct fs_ops { void (*load_config)(com32sys_t *); /* the _dir_ stuff */ - void (*readdir)(struct fs_info *, DIR *); + void (*opendir)(com32sys_t *); + struct dirent * (*readdir)(struct file *); }; enum dev_type {CHS, EDD}; @@ -92,7 +93,8 @@ static inline bool not_whitespace(char c) */ void mangle_name(com32sys_t *); void searchdir(com32sys_t *); - - +void _close_file(struct file *); +inline uint16_t file_to_handle(struct file *); +inline struct file *handle_to_file(uint16_t); #endif /* FS_H */ -- cgit v1.2.1 From ad49e6d67851b450a8b2b30f8d8042af2082d9ba Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 28 Aug 2009 18:56:00 +0800 Subject: Core: vfs-dir stuff cleaned Removes the core/include/dir.h, and put the dir structures to sys/dirent.h to avoid the compile error. Signed-off-by: Liu Aleaxander --- com32/include/dirent.h | 18 +----------------- com32/include/sys/dirent.h | 30 ++++++++++++++++++++++++++++++ com32/modules/dir.c | 1 - core/comboot.inc | 1 - core/dir.c | 2 +- core/fs.c | 23 ++++++++++++----------- core/fs/fat/fat.c | 2 +- core/include/dir.h | 28 ---------------------------- core/include/fs.h | 2 +- 9 files changed, 46 insertions(+), 61 deletions(-) create mode 100644 com32/include/sys/dirent.h delete mode 100644 core/include/dir.h diff --git a/com32/include/dirent.h b/com32/include/dirent.h index d2bfd627..c4aca4f0 100644 --- a/com32/include/dirent.h +++ b/com32/include/dirent.h @@ -10,23 +10,7 @@ #include #include -#ifndef NAME_MAX -#define NAME_MAX 255 -#endif - -struct dirent { - uint32_t d_ino; - uint32_t d_off; - uint16_t d_reclen; - uint16_t d_type; - char d_name[NAME_MAX + 1]; -}; - -struct file; - -typedef struct { - struct file *dd_dir; -} DIR; +#include __extern DIR *opendir(const char *); __extern struct dirent *readdir(DIR *); diff --git a/com32/include/sys/dirent.h b/com32/include/sys/dirent.h new file mode 100644 index 00000000..bfdbb9b7 --- /dev/null +++ b/com32/include/sys/dirent.h @@ -0,0 +1,30 @@ +/* + * sys/dirent.h + */ + +#ifndef DIRENT_H +#define DIRENT_H + +#include + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +struct dirent { + uint32_t d_ino; + uint32_t d_off; + uint16_t d_reclen; + uint16_t d_type; + char d_name[NAME_MAX + 1]; +}; + +struct file; + +typedef struct { + struct file *dd_dir; +} DIR; + +#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 + +#endif /* sys/dirent.h */ diff --git a/com32/modules/dir.c b/com32/modules/dir.c index badc37de..a3c98151 100644 --- a/com32/modules/dir.c +++ b/com32/modules/dir.c @@ -20,7 +20,6 @@ int main(int argc, char *argv[]) } dir = opendir(argv[1]); - printf("back from in main ...? \n"); if (dir == NULL) { printf("Unable to read dir: %s\n", argv[1]); return 0; diff --git a/core/comboot.inc b/core/comboot.inc index 7f9b3a9b..731e4327 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -900,7 +900,6 @@ comapi_getcwd: ; INT 22h AX=0020h Open directory ; %if IS_SYSLINUX - global comapi_opendir comapi_opendir: mov es,P_ES mov si,P_SI diff --git a/core/dir.c b/core/dir.c index 1bc8a260..a8d58052 100644 --- a/core/dir.c +++ b/core/dir.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/core/fs.c b/core/fs.c index b6e112ad..9a812d59 100644 --- a/core/fs.c +++ b/core/fs.c @@ -10,17 +10,6 @@ struct fs_info fs; /* Actual file structures (we don't have malloc yet...) */ struct file files[MAX_OPEN]; -/* - * Convert between a 16-bit file handle and a file structure - */ -inline uint16_t file_to_handle(struct file *file) -{ - return file ? (file - files)+1 : 0; -} -inline struct file *handle_to_file(uint16_t handle) -{ - return handle ? &files[handle-1] : NULL; -} /* * Get an empty file structure @@ -54,6 +43,18 @@ void _close_file(struct file *file) free_file(file); } +/* + * Convert between a 16-bit file handle and a file structure + */ +inline uint16_t file_to_handle(struct file *file) +{ + return file ? (file - files)+1 : 0; +} +inline struct file *handle_to_file(uint16_t handle) +{ + return handle ? &files[handle-1] : NULL; +} + void load_config(com32sys_t *regs) { this_fs->fs_ops->load_config(regs); diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index a2540420..3efba4c5 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -1,10 +1,10 @@ #include #include +#include #include #include #include #include -#include #include "fat_fs.h" #define ROOT_DIR_WORD 0x002f diff --git a/core/include/dir.h b/core/include/dir.h deleted file mode 100644 index 04f0d090..00000000 --- a/core/include/dir.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DIR_H -#define DIR_H - -#include -#include -#include -#include -#include "disk.h" -#include "fs.h" - -struct dirent { - uint32_t d_ino; - uint32_t d_off; - uint16_t d_reclen; - uint16_t d_type; - char d_name[256]; -}; - -struct file; - -typedef struct { - struct file *dd_dir; -} DIR; - -#define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 - - -#endif /* dir.h */ diff --git a/core/include/fs.h b/core/include/fs.h index a8b02945..a6687593 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -7,7 +7,6 @@ #include #include "core.h" #include "disk.h" -#include "dir.h" /* * Maximum number of open files. This is *currently* constrained by the @@ -27,6 +26,7 @@ struct fs_info { }; struct open_file_t; /* Filesystem private structure */ +struct dirent; /* Directory entry structure */ struct file { struct open_file_t *open_file; /* Filesystem private data */ -- cgit v1.2.1 From 284ae5d0427e59def2210ecfc262965ade767337 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 28 Aug 2009 19:26:04 +0800 Subject: Core:pxelinux: fix the probaly hang when use host We shoud check the server if vaild or not; if not, move no until we run out the time. Signed-off-by: Liu Aleaxander --- core/fs/pxe/dnsresolv.c | 2 ++ core/fs/pxe/pxe.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index b2c36b7f..70e00c67 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -217,6 +217,8 @@ uint32_t dns_resolv(const char *name) timeout = *timeout_ptr++; while (srv_ptr < dns_server + DNS_MAX_SERVERS) { srv = *srv_ptr++; + if (!srv) + continue; /* just move on before runing the time out */ uw_pkt.status = 0; uw_pkt.sip = srv; uw_pkt.gip = ((srv ^ MyIP) & Netmask) ? Gateway : 0; diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index a775f26c..86bf92f7 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -230,7 +230,7 @@ void parse_dhcp_options(void *, int, int); /* dnsresolv.c */ int dns_mangle(char **, const char *); -uint32_t dns_resolv(char *); +uint32_t dns_resolv(const char *); #endif /* pxe.h */ -- cgit v1.2.1 From e0b07793a4cccc6921170ad83d292a9aa4895efb Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Fri, 28 Aug 2009 22:55:52 +0800 Subject: Core: code clean -- re-style the unstyle code With the emacs config given by hpa, which is really powfull, I restyled the unsytled code. Signed-off-by: Liu Aleaxander --- com32/include/sys/dirent.h | 2 +- com32/lib/closedir.c | 20 ++++++------ com32/lib/opendir.c | 2 +- com32/lib/readdir.c | 14 ++++---- com32/modules/dir.c | 42 ++++++++++++------------ com32/rosh/rosh.c | 2 +- core/dir.c | 20 ++++++------ core/fs.c | 18 +++++------ core/fs/fat/fat.c | 80 +++++++++++++++++++++------------------------- core/include/fs.h | 6 ++-- 10 files changed, 100 insertions(+), 106 deletions(-) diff --git a/com32/include/sys/dirent.h b/com32/include/sys/dirent.h index bfdbb9b7..cc2916e1 100644 --- a/com32/include/sys/dirent.h +++ b/com32/include/sys/dirent.h @@ -22,7 +22,7 @@ struct dirent { struct file; typedef struct { - struct file *dd_dir; + struct file *dd_dir; } DIR; #define DIR_REC_LEN(name) (12 + strlen(name) + 1 + 3) & ~3 diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c index 9e43dd4d..b3f55642 100644 --- a/com32/lib/closedir.c +++ b/com32/lib/closedir.c @@ -16,14 +16,14 @@ int closedir(DIR * dir) int rv = -1; if (dir) { - com32sys_t regs; - memset(®s, 0, sizeof regs); - regs.eax.w[0] = 0x0022; - regs.esi.l = (uint32_t)dir; - __com32.cs_intcall(0x22, ®s, ®s); - free(dir); - rv = 0; - } - - return rv; + com32sys_t regs; + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0022; + regs.esi.l = (uint32_t)dir; + __com32.cs_intcall(0x22, ®s, ®s); + free(dir); + rv = 0; + } + + return rv; } diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c index 70f74c15..6f91032b 100644 --- a/com32/lib/opendir.c +++ b/com32/lib/opendir.c @@ -27,7 +27,7 @@ DIR *opendir(const char *pathname) if (!(regs.eflags.l & EFLAGS_CF)) { /* Initialization: malloc() then zero */ newdir = calloc(1, sizeof(DIR)); - newdir->dd_dir = (struct file *)regs.eax.l; + newdir->dd_dir = (struct file *)regs.eax.l; } /* We're done */ diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c index 6c95bd6d..07ca3955 100644 --- a/com32/lib/readdir.c +++ b/com32/lib/readdir.c @@ -15,12 +15,12 @@ struct dirent *readdir(DIR * dir) { struct dirent *newde; com32sys_t regs; - - memset(®s, 0, sizeof(regs)); - regs.eax.w[0] = 0x0021; - regs.esi.l = (uint32_t)dir; - __com32.cs_intcall(0x22, ®s, ®s); - newde = (struct dirent *)(regs.eax.l); - + + memset(®s, 0, sizeof(regs)); + regs.eax.w[0] = 0x0021; + regs.esi.l = (uint32_t)dir; + __com32.cs_intcall(0x22, ®s, ®s); + newde = (struct dirent *)(regs.eax.l); + return newde; } diff --git a/com32/modules/dir.c b/com32/modules/dir.c index a3c98151..913c2ca7 100644 --- a/com32/modules/dir.c +++ b/com32/modules/dir.c @@ -9,27 +9,27 @@ int main(int argc, char *argv[]) { - DIR *dir; - struct dirent *de; - - openconsole(&dev_null_r, &dev_stdcon_w); - - if (argc != 2) { - printf("Usage: dir direcotry\n"); - return 0; - } - - dir = opendir(argv[1]); - if (dir == NULL) { - printf("Unable to read dir: %s\n", argv[1]); - return 0; - } - - while ((de = readdir(dir)) != NULL) - printf("%s\n", de->d_name); - - closedir(dir); - + DIR *dir; + struct dirent *de; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc != 2) { + printf("Usage: dir direcotry\n"); + return 0; + } + + dir = opendir(argv[1]); + if (dir == NULL) { + printf("Unable to read dir: %s\n", argv[1]); return 0; + } + + while ((de = readdir(dir)) != NULL) + printf("%s\n", de->d_name); + + closedir(dir); + + return 0; } diff --git a/com32/rosh/rosh.c b/com32/rosh/rosh.c index 862497be..2221bb0a 100644 --- a/com32/rosh/rosh.c +++ b/com32/rosh/rosh.c @@ -428,7 +428,7 @@ void rosh_dir_arg(const char *ifilstr, const char *pwdstr) filepos = 0; d = opendir(filestr); if (d != NULL) { - //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset); + //printf("DIR:'%s' %08x %8d\n", d->dd_name, (int)d->dd_sect, d->dd_offset); de = readdir(d); while (de != NULL) { filepos++; diff --git a/core/dir.c b/core/dir.c index a8d58052..42400c91 100644 --- a/core/dir.c +++ b/core/dir.c @@ -11,8 +11,8 @@ extern struct fs_info *this_fs; */ void opendir(com32sys_t *regs) { - this_fs->fs_ops->opendir(regs); - regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]); + this_fs->fs_ops->opendir(regs); + regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[0]); } /* @@ -23,14 +23,14 @@ void opendir(com32sys_t *regs) */ void readdir(com32sys_t *regs) { - DIR *dir = (DIR *)regs->esi.l; + DIR *dir = (DIR *)regs->esi.l; struct dirent *de = NULL; - - if (dir->dd_dir) - de = this_fs->fs_ops->readdir(dir->dd_dir); - else - de = NULL; - + + if (dir->dd_dir) + de = this_fs->fs_ops->readdir(dir->dd_dir); + else + de = NULL; + /* Return the newly read de in _eax_ register */ regs->eax.l = (uint32_t)de; } @@ -38,7 +38,7 @@ void readdir(com32sys_t *regs) void closedir(com32sys_t *regs) { DIR *dir = (DIR *)regs->esi.l; - _close_file(dir->dd_dir); + _close_file(dir->dd_dir); } diff --git a/core/fs.c b/core/fs.c index 9a812d59..f7bf68c2 100644 --- a/core/fs.c +++ b/core/fs.c @@ -64,7 +64,7 @@ void mangle_name(com32sys_t *regs) { const char *src = MK_PTR(regs->ds, regs->esi.w[0]); char *dst = MK_PTR(regs->es, regs->edi.w[0]); - + this_fs->fs_ops->mangle_name(dst, src); } @@ -73,7 +73,7 @@ void unmangle_name(com32sys_t *regs) { const char *src = MK_PTR(regs->ds, regs->esi.w[0]); char *dst = MK_PTR(regs->es, regs->edi.w[0]); - + dst = this_fs->fs_ops->unmangle_name(dst, src); /* Update the di register to point to the last null char */ @@ -94,7 +94,7 @@ void getfssec(com32sys_t *regs) handle = regs->esi.w[0]; file = handle_to_file(handle); - + buf = MK_PTR(regs->es, regs->ebx.w[0]); bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more); @@ -121,11 +121,11 @@ void searchdir(com32sys_t *regs) #endif file = alloc_file(); - + if (file) { file->fs = this_fs; file->fs->fs_ops->searchdir(filename, file); - + if (file->open_file) { regs->esi.w[0] = file_to_handle(file); regs->eax.l = file->file_len; @@ -133,7 +133,7 @@ void searchdir(com32sys_t *regs) return; } } - + /* failure... */ regs->esi.w[0] = 0; regs->eax.l = 0; @@ -144,7 +144,7 @@ void close_file(com32sys_t *regs) { uint16_t handle = regs->esi.w[0]; struct file *file; - + if (handle) { file = handle_to_file(handle); _close_file(file); @@ -163,7 +163,7 @@ void fs_init(com32sys_t *regs) { int blk_shift; const struct fs_ops *ops = (const struct fs_ops *)regs->eax.l; - + /* set up the fs stucture */ fs.fs_ops = ops; @@ -175,7 +175,7 @@ void fs_init(com32sys_t *regs) regs->esi.w[0], regs->edi.w[0]); this_fs = &fs; - + /* invoke the fs-specific init code */ blk_shift = fs.fs_ops->fs_init(&fs); diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 3efba4c5..58226a71 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -47,10 +47,6 @@ static char long_name[0x40 * 13]; static char *NameStart; static int NameLen; -/* do this for readdir, because it called from asm and don't know the fs structure */ -static struct fs_info *this_fs = NULL; - - /* * Allocate a file structure, if successful return the file pointer, or NULL. * @@ -616,8 +612,6 @@ static void vfat_searchdir(char *filename, struct file *file) uint8_t attr = 0; char *p; struct open_file_t *open_file = NULL; - - this_fs = file->fs; dir_sector = CurrentDir; if (*filename == '/') { @@ -678,10 +672,10 @@ static void vfat_searchdir(char *filename, struct file *file) */ void vfat_opendir(com32sys_t *regs) { - char *src = MK_PTR(regs->es, regs->esi.w[0]); - char *dst = MK_PTR(regs->ds, regs->edi.w[0]); - strcpy(dst, src); - searchdir(regs); + char *src = MK_PTR(regs->es, regs->esi.w[0]); + char *dst = MK_PTR(regs->ds, regs->edi.w[0]); + strcpy(dst, src); + searchdir(regs); } /* @@ -696,24 +690,24 @@ struct dirent* vfat_readdir(struct file *dir) uint8_t checksum = 0; uint8_t entries_left; int i; - static struct dirent de; + static struct dirent de; char *de_name = de.d_name; struct cache_struct *cs; struct fat_dir_entry *fat_dir; struct fat_long_name_entry *long_dir; - struct open_file_t *file = dir->open_file; - struct fs_info *fs = dir->fs; - + struct open_file_t *file = dir->open_file; + struct fs_info *fs = dir->fs; + sector = file->file_sector; sec_off = file->file_bytesleft; if (!sector) return NULL; entries_left = (SECTOR_SIZE - sec_off) >> 5; - cs = get_cache_block(this_fs->fs_dev, sector); + cs = get_cache_block(fs->fs_dev, sector); fat_dir = (struct fat_dir_entry *)(cs->data + sec_off);/* resume last position in sector */ while (1) { - if (!entries_left) { + if (!entries_left) { sector = nextsector(fs, sector); if (!sector) return NULL; @@ -722,13 +716,13 @@ struct dirent* vfat_readdir(struct file *dir) } if (fat_dir->name[0] == 0) - return NULL; + return NULL; if (fat_dir->attr == FAT_ATTR_LONG_NAME) { /* it's a long name */ long_dir = (struct fat_long_name_entry *)fat_dir; if (long_dir->id & 0x40) { - checksum = long_dir->checksum; + checksum = long_dir->checksum; init_id = id = long_dir->id & 0x3f; id--; } else { @@ -741,7 +735,7 @@ struct dirent* vfat_readdir(struct file *dir) long_entry_name(long_dir); memcpy(de_name + id * 13, entry_name, 13); - /* + /* * we need go on with the next entry * and we will fall through to next entry */ @@ -750,16 +744,16 @@ struct dirent* vfat_readdir(struct file *dir) /* it's a short entry */ if (!id) { - /* Got a long name match */ - if (get_checksum(fat_dir->name) != checksum) - goto next_entry; - - break; - } + /* Got a long name match */ + if (get_checksum(fat_dir->name) != checksum) + goto next_entry; + + break; + } if (fat_dir->attr & FAT_ATTR_VOLUME_ID || - get_checksum(fat_dir->name) != checksum ) - goto next_entry; + get_checksum(fat_dir->name) != checksum ) + goto next_entry; for(i = 0; i < 8; i ++) { if (fat_dir->name[i] == ' ') @@ -778,29 +772,29 @@ struct dirent* vfat_readdir(struct file *dir) else *de_name = '\0'; - break; + break; } next_entry: - entries_left --; + entries_left --; fat_dir ++; } - - /* found what we want, fill the de structure */ - de.d_reclen = DIR_REC_LEN(de.d_name); - de.d_type = fat_dir->attr; - - /* update the DIR structure */ + + /* found what we want, fill the de structure */ + de.d_reclen = DIR_REC_LEN(de.d_name); + de.d_type = fat_dir->attr; + + /* update the DIR structure */ entries_left--; - if (!entries_left) { - sector = nextsector(fs, sector); - file->file_bytesleft = 0; + if (!entries_left) { + sector = nextsector(fs, sector); + file->file_bytesleft = 0; } else { file->file_bytesleft = SECTOR_SIZE - (entries_left << 5); - } + } file->file_sector = sector; - - return &de; + + return &de; } static void vfat_load_config(com32sys_t *regs) @@ -895,6 +889,6 @@ const struct fs_ops vfat_fs_ops = { .mangle_name = vfat_mangle_name, .unmangle_name = generic_unmangle_name, .load_config = vfat_load_config, - .opendir = vfat_opendir, - .readdir = vfat_readdir + .opendir = vfat_opendir, + .readdir = vfat_readdir }; diff --git a/core/include/fs.h b/core/include/fs.h index a6687593..e66c3bde 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -51,9 +51,9 @@ struct fs_ops { char * (*unmangle_name)(char *, const char *); void (*load_config)(com32sys_t *); - /* the _dir_ stuff */ - void (*opendir)(com32sys_t *); - struct dirent * (*readdir)(struct file *); + /* the _dir_ stuff */ + void (*opendir)(com32sys_t *); + struct dirent * (*readdir)(struct file *); }; enum dev_type {CHS, EDD}; -- cgit v1.2.1 From 71edc894196649651f77fe17b0f2bc81f47324ca Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sat, 29 Aug 2009 07:18:12 +0800 Subject: Core:pxelinux: The pxe structures are all converted to standard structures. converts the current pxe structures to standard structures; removes the old one in pxe.h. Signed-off-by: Liu Aleaxander --- com32/include/syslinux/pxe_api.h | 30 +++++++ core/fs/pxe/dnsresolv.c | 44 +++++----- core/fs/pxe/pxe.c | 174 +++++++++++++++++++-------------------- core/fs/pxe/pxe.h | 62 -------------- 4 files changed, 139 insertions(+), 171 deletions(-) diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h index 5fd102ef..6c9efc24 100644 --- a/com32/include/syslinux/pxe_api.h +++ b/com32/include/syslinux/pxe_api.h @@ -379,6 +379,36 @@ typedef struct s_PXENV_UNDI_ISR { uint8_t ProtType; uint8_t PktType; } __packed t_PXENV_UNDI_ISR; + +typedef struct s_PXENV_FILE_API_CHECK { + pxenv_status_t Status; + uint16_t Size; + uint32_t Magic; + uint32_t Provider; + uint32_t APIMask; + uint32_t Flags; +} __packed t_PXENV_FILE_API_CHECK; + +typedef struct s_PXENV_FILE_READ { + pxenv_status_t Status; + uint16_t FileHandle; + uint16_t BufferSize; + segoff16_t Buffer; +} __packed t_PXENV_FILE_READ; + +typedef struct s_PXENV_FILE_OPEN { + pxenv_status_t Status; + uint16_t FileHandle; + segoff16_t FileName; + uint32_t Reserved; +} __packed t_PXENV_FILE_OPEN; + +typedef struct s_PXENV_GET_FILE_SIZE { + pxenv_status_t Status; + uint16_t FileHandle; + uint32_t FileSize; +} __packed t_PXENV_GET_FILE_SIZE; + #define PXENV_UNDI_ISR_IN_START 1 #define PXENV_UNDI_ISR_IN_PROCESS 2 #define PXENV_UNDI_ISR_IN_GET_NEXT 3 diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index 70e00c67..8fccd372 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -186,8 +186,8 @@ uint32_t dns_resolv(const char *name) struct dnshdr *hd2 = (struct dnshdr *)DNSRecvBuf; struct dnsquery *query; struct dnsrr *rr; - static __lowmem struct pxe_udp_write_pkt uw_pkt; - static __lowmem struct pxe_udp_read_pkt ur_pkt; + static __lowmem struct s_PXENV_UDP_WRITE udp_write; + static __lowmem struct s_PXENV_UDP_READ udp_read; /* First, fill the DNS header struct */ hd1->id++; /* New query ID */ @@ -219,30 +219,30 @@ uint32_t dns_resolv(const char *name) srv = *srv_ptr++; if (!srv) continue; /* just move on before runing the time out */ - uw_pkt.status = 0; - uw_pkt.sip = srv; - uw_pkt.gip = ((srv ^ MyIP) & Netmask) ? Gateway : 0; - uw_pkt.lport = DNS_LOCAL_PORT; - uw_pkt.rport = DNS_PORT; - uw_pkt.buffersize = p - DNSSendBuf; - uw_pkt.buffer[0] = OFFS_WRT(DNSSendBuf, 0); - uw_pkt.buffer[1] = 0; - err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); - if (err || uw_pkt.status != 0) + udp_write.status = 0; + udp_write.ip = srv; + udp_write.gw = ((srv ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.src_port = DNS_LOCAL_PORT; + udp_write.dst_port = DNS_PORT; + udp_write.buffer_size = p - DNSSendBuf; + udp_write.buffer.offs = OFFS_WRT(DNSSendBuf, 0); + udp_write.buffer.seg = 0; + err = pxe_call(PXENV_UDP_WRITE, &udp_write); + if (err || udp_write.status != 0) continue; oldtime = BIOS_timer; while (1) { - ur_pkt.status = 0; - ur_pkt.sip = srv; - ur_pkt.dip = MyIP; - ur_pkt.rport = DNS_PORT; - ur_pkt.lport = DNS_LOCAL_PORT; - ur_pkt.buffersize = DNS_MAX_PACKET; - ur_pkt.buffer[0] = OFFS_WRT(DNSRecvBuf, 0); - ur_pkt.buffer[1] = 0; - err = pxe_call(PXENV_UDP_READ, &ur_pkt); - if (err || ur_pkt.status) + udp_read.status = 0; + udp_read.src_ip = srv; + udp_read.dest_ip = MyIP; + udp_read.s_port = DNS_PORT; + udp_read.d_port = DNS_LOCAL_PORT; + udp_read.buffer_size = DNS_MAX_PACKET; + udp_read.buffer.offs = OFFS_WRT(DNSRecvBuf, 0); + udp_read.buffer.seg = 0; + err = pxe_call(PXENV_UDP_READ, &udp_read); + if (err || udp_read.status) continue; /* Got a packet, deal with it... */ diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index b300d6af..8adcb150 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -242,7 +242,7 @@ int pxe_call(int opcode, void *data) in_regs.edi.w[0] = OFFS(data); call16(pxenv, &in_regs, &out_regs); - return out_regs.eflags.l & EFLAGS_CF; /* CF SET for fail */ + return out_regs.eflags.l & EFLAGS_CF; /* CF SET if fail */ } /** @@ -255,19 +255,19 @@ int pxe_call(int opcode, void *data) static void ack_packet(struct open_file_t *file, uint16_t ack_num) { int err; - static __lowmem struct pxe_udp_write_pkt uw_pkt; + static __lowmem struct s_PXENV_UDP_WRITE udp_write; /* Packet number to ack */ - ack_packet_buf[1] = ack_num; - uw_pkt.lport = file->tftp_localport; - uw_pkt.rport = file->tftp_remoteport; - uw_pkt.sip = file->tftp_remoteip; - uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; - uw_pkt.buffer[0] = OFFS_WRT(ack_packet_buf, 0); - uw_pkt.buffer[1] = 0; /* seems SEG and OFFS stuff doesn't work here */ - uw_pkt.buffersize = 4; - - err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); + ack_packet_buf[1] = ack_num; + udp_write.src_port = file->tftp_localport; + udp_write.dst_port = file->tftp_remoteport; + udp_write.ip = file->tftp_remoteip; + udp_write.gw = ((udp_write.ip ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.buffer.offs = OFFS_WRT(ack_packet_buf, 0); + udp_write.buffer.seg = 0; + udp_write.buffer_size = 4; + + err = pxe_call(PXENV_UDP_WRITE, &udp_write); #if 0 printf("sent %s\n", err ? "FAILED" : "OK"); #endif @@ -284,21 +284,21 @@ static void ack_packet(struct open_file_t *file, uint16_t ack_num) static int pxe_get_cached_info(int type) { int err; - static __lowmem struct pxe_bootp_query_pkt bq_pkt; + static __lowmem struct s_PXENV_GET_CACHED_INFO get_cached_info; printf(" %02x", type); - bq_pkt.status = 0; - bq_pkt.packettype = type; - bq_pkt.buffersize = 8192; - bq_pkt.buffer[0] = OFFS_WRT(trackbuf, 0); - bq_pkt.buffer[1] = 0; - err = pxe_call(PXENV_GET_CACHED_INFO, &bq_pkt); + get_cached_info.Status = 0; + get_cached_info.PacketType = type; + get_cached_info.BufferSize = 8192; + get_cached_info.Buffer.offs = OFFS_WRT(trackbuf, 0); + get_cached_info.Buffer.seg = 0; + err = pxe_call(PXENV_GET_CACHED_INFO, &get_cached_info); if (err) { printf("PXE API call failed, error %04x\n", err); kaboom(); } - return bq_pkt.buffersize; + return get_cached_info.BufferSize; } @@ -330,22 +330,22 @@ static int is_url(const char *url) static int is_gpxe(char *url) { int err; - static __lowmem struct gpxe_file_api_check ac; + static __lowmem struct s_PXENV_FILE_API_CHECK api_check; char *gpxe_warning_msg = "URL syntax, but gPXE extensions not detected, tring plain TFTP...\n"; if (! is_url(url)) return 0; - ac.size = 20; - ac.magic = 0x91d447b2; + api_check.Size = sizeof api_check; + api_check.Magic = 0x91d447b2; /* If has_gpxe is greater than one, means the gpxe status is unknow */ while (has_gpxe > 1) { - err = pxe_call(PXENV_FILE_API_CHECK, &ac); - if (err || ac.magic != 0xe9c17b20) + err = pxe_call(PXENV_FILE_API_CHECK, &api_check); + if (err || api_check.Magic != 0xe9c17b20) printf("%s\n", gpxe_warning_msg); else - has_gpxe = (~ac.provider & 0xffff) & 0x4b ? 0 : 1; + has_gpxe = (~api_check.Provider & 0xffff) & 0x4b ? 0 : 1; if (!has_gpxe) printf("%s\n", gpxe_warning_msg); @@ -361,24 +361,24 @@ static int is_gpxe(char *url) */ static void get_packet_gpxe(struct open_file_t *file) { - static __lowmem struct gpxe_file_read fr; + static __lowmem struct s_PXENV_FILE_READ file_read; int err; while (1) { - fr.filehandle = file->tftp_remoteport; - fr.buffer[0] = file->tftp_pktbuf; - fr.buffer[1] = PKTBUF_SEG; - fr.buffersize = PKTBUF_SIZE; - err = pxe_call(PXENV_FILE_READ, &fr); + file_read.FileHandle = file->tftp_remoteport; + file_read.Buffer.offs = file->tftp_pktbuf; + file_read.Buffer.seg = PKTBUF_SEG; + file_read.BufferSize = PKTBUF_SIZE; + err = pxe_call(PXENV_FILE_READ, &file_read); if (!err) /* successed */ break; - if (fr.status != PXENV_STATUS_TFTP_OPEN) + if (file_read.Status != PXENV_STATUS_TFTP_OPEN) kaboom(); } - file->tftp_bytesleft = fr.buffersize; - file->tftp_filepos += fr.buffersize; + file->tftp_bytesleft = file_read.BufferSize; + file->tftp_filepos += file_read.BufferSize; if (file->tftp_bytesleft == 0) file->tftp_filesize = file->tftp_filepos; @@ -389,7 +389,7 @@ static void get_packet_gpxe(struct open_file_t *file) /* Got EOF, close it */ file->tftp_goteof = 1; - pxe_call(PXENV_FILE_CLOSE, &fr); + pxe_call(PXENV_FILE_CLOSE, &file_read); } #endif /* GPXE */ @@ -492,7 +492,7 @@ static void fill_buffer(struct open_file_t *file) uint16_t buffersize; uint16_t old_time; void *data = NULL; - static __lowmem struct pxe_udp_read_pkt pkt; + static __lowmem struct s_PXENV_UDP_READ udp_read; if (file->tftp_bytesleft || file->tftp_goteof) return; @@ -516,14 +516,14 @@ static void fill_buffer(struct open_file_t *file) timeout = *timeout_ptr++; old_time = BIOS_timer; while (timeout) { - pkt.buffer[0] = file->tftp_pktbuf; - pkt.buffer[1] = PKTBUF_SEG; - pkt.buffersize = PKTBUF_SIZE; - pkt.sip = file->tftp_remoteip; - pkt.dip = MyIP; - pkt.rport = file->tftp_remoteport; - pkt.lport = file->tftp_localport; - err = pxe_call(PXENV_UDP_READ, &pkt); + udp_read.buffer.offs = file->tftp_pktbuf; + udp_read.buffer.seg = PKTBUF_SEG; + udp_read.buffer_size = PKTBUF_SIZE; + udp_read.src_ip = file->tftp_remoteip; + udp_read.dest_ip = MyIP; + udp_read.s_port = file->tftp_remoteport; + udp_read.d_port = file->tftp_localport; + err = pxe_call(PXENV_UDP_READ, &udp_read); if (err) { if (BIOS_timer == old_time) continue; @@ -538,7 +538,7 @@ static void fill_buffer(struct open_file_t *file) continue; } - if (pkt.buffersize < 4) /* Bad size for a DATA packet */ + if (udp_read.buffer_size < 4) /* Bad size for a DATA packet */ continue; data = MK_PTR(PKTBUF_SEG, file->tftp_pktbuf); @@ -572,7 +572,7 @@ static void fill_buffer(struct open_file_t *file) /* It's the packet we want. We're also EOF if the size < blocksize */ file->tftp_lastpkt = last_pkt; /* Update last packet number */ - buffersize = pkt.buffersize - 4; /* Skip TFTP header */ + buffersize = udp_read.buffer_size - 4; /* Skip TFTP header */ file->tftp_dataptr = file->tftp_pktbuf + 4; file->tftp_filepos += buffersize; file->tftp_bytesleft = buffersize; @@ -670,10 +670,10 @@ static void pxe_searchdir(char *filename, struct file *file) char *options; char *data; struct open_file_t *open_file; - static __lowmem struct pxe_udp_write_pkt uw_pkt; - static __lowmem struct pxe_udp_read_pkt ur_pkt; - static __lowmem struct gpxe_file_open fo; - static __lowmem struct gpxe_get_file_size gs; + static __lowmem struct s_PXENV_UDP_WRITE udp_write; + static __lowmem struct s_PXENV_UDP_READ udp_read; + static __lowmem struct s_PXENV_FILE_OPEN file_open; + static __lowmem struct s_PXENV_GET_FILE_SIZE get_file_size; const struct tftp_options *tftp_opt; int i = 0; int err; @@ -697,8 +697,8 @@ static void pxe_searchdir(char *filename, struct file *file) timeout_ptr = TimeoutTable; /* Reset timeout */ sendreq: - uw_pkt.buffer[0] = OFFS_WRT(buf, 0); - uw_pkt.buffer[1] = 0; + udp_write.buffer.offs = OFFS_WRT(buf, 0); + udp_write.buffer.seg = 0; *(uint16_t *)buf = TFTP_RRQ; /* TFTP opcode */ buf += 2; @@ -716,21 +716,21 @@ static void pxe_searchdir(char *filename, struct file *file) #if GPXE if (is_gpxe(packet_buf + 2)) { - fo.status = PXENV_STATUS_BAD_FUNC; - fo.filename[0] = OFFS_WRT(packet_buf + 2, 0); - fo.filename[1] = 0; - err = pxe_call(PXENV_FILE_OPEN, &fo); + file_open.Status = PXENV_STATUS_BAD_FUNC; + file_open.FileName.offs = OFFS_WRT(packet_buf + 2, 0); + file_open.FileName.seg = 0; + err = pxe_call(PXENV_FILE_OPEN, &file_open); if (err) goto done; open_file->tftp_localport = -1; - open_file->tftp_remoteport = fo.filehandle; - gs.filehandle = fo.filehandle; + open_file->tftp_remoteport = file_open.FileHandle; + get_file_size.FileHandle = file_open.FileHandle; #if 0 - err = pxe_call(PXENV_GET_FILE_SIZE, &gs); + err = pxe_call(PXENV_GET_FILE_SIZE, &get_file_size); if (!err) - open_file->tftp_filesize = gs.filesize; + open_file->tftp_filesize = get_file_size.FileSize; else #endif open_file->tftp_filesize = -1; @@ -740,14 +740,14 @@ static void pxe_searchdir(char *filename, struct file *file) open_file->tftp_remoteip = ip; tid = open_file->tftp_localport; /* TID(local port No) */ - uw_pkt.sip = ip; - uw_pkt.gip = ((uw_pkt.sip ^ MyIP) & Netmask) ? Gateway : 0; - uw_pkt.lport = tid; - uw_pkt.rport = ServerPort; + udp_write.ip = ip; + udp_write.gw = ((udp_write.ip ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.src_port = tid; + udp_write.dst_port = ServerPort; buf += fill_tail(buf); - uw_pkt.buffersize = buf - packet_buf; - err = pxe_call(PXENV_UDP_WRITE, &uw_pkt); - if (err || uw_pkt.status != 0) + udp_write.buffer_size = buf - packet_buf; + err = pxe_call(PXENV_UDP_WRITE, &udp_write); + if (err || udp_write.status != 0) goto failure; /* * In fact, the 'failure' target will not do * a failure thing; it will move on to the @@ -765,12 +765,12 @@ static void pxe_searchdir(char *filename, struct file *file) oldtime = BIOS_timer; while (timeout) { buf = packet_buf; - ur_pkt.buffer[0] = OFFS_WRT(buf, 0); - ur_pkt.buffer[1] = 0; - ur_pkt.buffersize = 2048; - ur_pkt.dip = MyIP; - ur_pkt.lport = tid; - err = pxe_call(PXENV_UDP_READ, &ur_pkt); + udp_read.buffer.offs = OFFS_WRT(buf, 0); + udp_read.buffer.seg = 0; + udp_read.buffer_size = 2048; + udp_read.dest_ip = MyIP; + udp_read.d_port = tid; + err = pxe_call(PXENV_UDP_READ, &udp_read); if (err) { if (oldtime == BIOS_timer) continue; @@ -780,19 +780,19 @@ static void pxe_searchdir(char *filename, struct file *file) } /* Make sure the packet actually came from the server */ - if (ur_pkt.sip == open_file->tftp_remoteip) + if (udp_read.src_ip == open_file->tftp_remoteip) break; } /* Got packet; reset timeout */ timeout_ptr = TimeoutTable; - open_file->tftp_remoteport = ur_pkt.rport; + open_file->tftp_remoteport = udp_read.s_port; /* filesize <- -1 == unknown */ open_file->tftp_filesize = -1; /* Default blksize unless blksize option negotiated */ open_file->tftp_blksize = TFTP_BLOCKSIZE; - buffersize = ur_pkt.buffersize - 2; /* bytes after opcode */ + buffersize = udp_read.buffer_size - 2; /* bytes after opcode */ if (buffersize < 0) goto failure; /* Garbled reply */ @@ -931,11 +931,11 @@ done: return; err_reply: - uw_pkt.rport = open_file->tftp_remoteport; - uw_pkt.buffer[0] = OFFS_WRT(tftp_proto_err, 0); - uw_pkt.buffer[1] = 0; - uw_pkt.buffersize = 24; - pxe_call(PXENV_UDP_WRITE, &uw_pkt); + udp_write.dst_port = open_file->tftp_remoteport; + udp_write.buffer.offs = OFFS_WRT(tftp_proto_err, 0); + udp_write.buffer.seg = 0; + udp_write.buffer_size = 24; + pxe_call(PXENV_UDP_WRITE, &udp_write); printf("TFTP server sent an incomprehesible reply\n"); kaboom(); @@ -1366,12 +1366,12 @@ static void pxe_init(void) static void udp_init(void) { int err; - static __lowmem struct pxe_udp_open_pkt uo_pkt; - uo_pkt.sip = MyIP; - err = pxe_call(PXENV_UDP_OPEN, &uo_pkt); - if (err || uo_pkt.status) { + static __lowmem struct s_PXENV_UDP_OPEN udp_open; + udp_open.src_ip = MyIP; + err = pxe_call(PXENV_UDP_OPEN, &udp_open); + if (err || udp_open.status) { printf("Failed to initialize UDP stack "); - printf("%d\n", uo_pkt.status); + printf("%d\n", udp_open.status); kaboom(); } } diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 86bf92f7..dc1a52fc 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -154,68 +154,6 @@ struct open_file_t { uint16_t tftp_pktbuf; /* Packet buffer offset */ } __attribute__ ((packed)); -struct pxe_udp_write_pkt { - uint16_t status; - uint32_t sip; - uint32_t gip; - uint16_t lport; - uint16_t rport; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - -struct pxe_udp_read_pkt { - uint16_t status; - uint32_t sip; - uint32_t dip; - uint16_t rport; - uint16_t lport; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - -struct pxe_bootp_query_pkt { - uint16_t status; - uint16_t packettype; - uint16_t buffersize; - uint16_t buffer[2]; - uint16_t bufferlimit; -} __attribute__ ((packed)); - -struct pxe_udp_open_pkt { - uint16_t status; - uint32_t sip; -} __attribute__ ((packed)); - -struct gpxe_file_api_check { - uint16_t status; - uint16_t size; - uint32_t magic; - uint32_t provider; - uint32_t apimask; - uint32_t flags; -} __attribute__ ((packed)); - -struct gpxe_file_open { - uint16_t status; - uint16_t filehandle; - uint16_t filename[2]; - uint32_t reserved; -} __attribute__ ((packed)); - -struct gpxe_get_file_size { - uint16_t status; - uint16_t filehandle; - uint32_t filesize; -} __attribute__ ((packed)); - -struct gpxe_file_read { - uint16_t status; - uint16_t filehandle; - uint16_t buffersize; - uint16_t buffer[2]; -} __attribute__ ((packed)); - /* * functions */ -- cgit v1.2.1 From ca319d3cda6d40d38150c89fb0510069649f4fd1 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 30 Aug 2009 04:13:40 +0800 Subject: Core:pxelinux: code clean--removes the unused variables in ASM file And also converts some asm-variables to c-variables. Signed-off-by: Liu Aleaxander --- core/fs/pxe/pxe.c | 25 ++++++++++++++++++++----- core/fs/pxe/pxe.h | 5 +++-- core/include/core.h | 4 +--- core/pxelinux.asm | 38 ++------------------------------------ 4 files changed, 26 insertions(+), 46 deletions(-) diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 8adcb150..8c006fea 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -8,6 +8,11 @@ #define GPXE 1 +uint32_t ServerIP = 0; /* IP address of boot server */ +uint32_t Netmask = 0; /* Netmask of this subnet */ +uint32_t Gateway = 0; /* Default router */ +uint16_t ServerPort = TFTP_PORT; /* TFTP server port */ + static struct open_file_t Files[MAX_OPEN]; static int has_gpxe; static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; @@ -255,16 +260,18 @@ int pxe_call(int opcode, void *data) static void ack_packet(struct open_file_t *file, uint16_t ack_num) { int err; + static __lowmem uint16_t ack_packet_buf[2]; static __lowmem struct s_PXENV_UDP_WRITE udp_write; /* Packet number to ack */ + ack_packet_buf[0] = TFTP_ACK; ack_packet_buf[1] = ack_num; udp_write.src_port = file->tftp_localport; udp_write.dst_port = file->tftp_remoteport; udp_write.ip = file->tftp_remoteip; udp_write.gw = ((udp_write.ip ^ MyIP) & Netmask) ? Gateway : 0; - udp_write.buffer.offs = OFFS_WRT(ack_packet_buf, 0); - udp_write.buffer.seg = 0; + udp_write.buffer.offs = OFFS(ack_packet_buf); + udp_write.buffer.seg = SEG(ack_packet_buf); udp_write.buffer_size = 4; err = pxe_call(PXENV_UDP_WRITE, &udp_write); @@ -664,7 +671,7 @@ static int fill_tail(char *dst) */ static void pxe_searchdir(char *filename, struct file *file) { - extern char tftp_proto_err[]; + static __lowmem char tftp_proto_err[32]; char *buf = packet_buf; char *p = filename; char *options; @@ -931,9 +938,17 @@ done: return; err_reply: + /* Build the TFTP error packet */ + p = tftp_proto_err; + *(uint16_t *)p = TFTP_ERROR; + p += 2; + *(uint16_t *)p = TFTP_EOPTNEG; + p += 2; + strcat(p, "TFTP_protocol error"); + udp_write.dst_port = open_file->tftp_remoteport; - udp_write.buffer.offs = OFFS_WRT(tftp_proto_err, 0); - udp_write.buffer.seg = 0; + udp_write.buffer.offs = OFFS(tftp_proto_err); + udp_write.buffer.seg = SEG(tftp_proto_err); udp_write.buffer_size = 24; pxe_call(PXENV_UDP_WRITE, &udp_write); printf("TFTP server sent an incomprehesible reply\n"); diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index dc1a52fc..864815bd 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -24,11 +24,11 @@ /* * Some basic defines... */ -#define PKTBUF_SIZE (65536 / MAX_OPEN) - +#define TFTP_PORT htons(69) /* Default TFTP port */ #define TFTP_BLOCKSIZE_LG2 9 #define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) #define PKTBUF_SEG 0x4000 +#define PKTBUF_SIZE (65536 / MAX_OPEN) #define is_digit(c) (((c) >= '0') && ((c) <= '9')) @@ -55,6 +55,7 @@ #define TFTP_ENOUSER htons(7) // No such user #define TFTP_EOPTNEG htons(8) // Option negotiation failure + #define BOOTP_OPTION_MAGIC htonl(0x63825363) #define MAC_MAX 32 diff --git a/core/include/core.h b/core/include/core.h index f8be6912..52a35d4e 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -48,7 +48,7 @@ extern uint32_t ServerIP; extern uint32_t MyIP; extern uint32_t Netmask; extern uint32_t Gateway; -extern uint32_t ServerPort; +extern uint16_t ServerPort; extern char MACStr[]; /* MAC address as a string */ extern char MAC[]; /* Actual MAC address */ @@ -59,8 +59,6 @@ extern uint8_t MACType; /* MAC address type */ extern uint8_t DHCPMagic; extern uint8_t OverLoad; extern uint32_t RebootTime; -/* TFTP ACK packet */ -extern uint16_t ack_packet_buf[]; extern char BootFile[]; extern char PathPrefix[]; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index ed67518f..8f0b7acd 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -33,7 +33,6 @@ NULLFILE equ 0 ; Zero byte == null file name NULLOFFSET equ 4 ; Position in which to look REBOOT_TIME equ 5*60 ; If failure, time until full reset %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top -TFTP_PORT equ htons(69) ; Default TFTP port TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block) TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2) @@ -399,19 +398,6 @@ pxe_int1a: ret ; -; TimeoutTable: list of timeouts (in 18.2 Hz timer ticks) -; -; This is roughly an exponential backoff... -; - section .data16 -TimeoutTable: - db 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18 - db 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132 - db 159, 191, 229, 255, 255, 255, 255 -TimeoutTableEnd equ $ - - section .text16 -; ; unload_pxe: ; ; This function unloads the PXE and UNDI stacks and unclaims @@ -598,30 +584,10 @@ BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack KeepPXE db 0 ; Should PXE be kept around? - alignz 2 -; -; Error packet to return on TFTP protocol error -; Most of our errors are OACK parsing errors, so use that error code -; - global tftp_proto_err, tftp_proto_err_len -tftp_proto_err dw TFTP_ERROR ; ERROR packet - dw TFTP_EOPTNEG ; ERROR 8: OACK error - db 'TFTP protocol error', 0 ; Error message -tftp_proto_err_len equ ($-tftp_proto_err) - - alignz 4 - global ack_packet_buf -ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet - ; ; IP information (initialized to "unknown" values) - global MyIP, ServerIP, Netmask, Gateway, ServerPort -MyIP dd 0 ; My IP address -ServerIP dd 0 ; IP address of boot server -Netmask dd 0 ; Netmask of this subnet -Gateway dd 0 ; Default router -ServerPort dw TFTP_PORT ; TFTP server port - + global MyIP +MyIP dd 0 ; My IP address ; ; Variables that are uninitialized in SYSLINUX but initialized here ; -- cgit v1.2.1 From b17a78c59d28b06b77b3a9af636664a7299adbc9 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 30 Aug 2009 05:37:30 +0800 Subject: Core:pxelinux: unload_pxe converted. I found it's also better to convert the unload_pxe, but I am not sure I'm right. Signed-off-by: Liu Aleaxander --- com32/include/syslinux/pxe_api.h | 5 ++ core/bootsect.inc | 2 +- core/comboot.inc | 2 +- core/extern.inc | 3 + core/fs/pxe/pxe.c | 69 +++++++++++++++++- core/fs/pxe/pxe.h | 9 +-- core/include/core.h | 2 + core/pxeidle.inc | 12 +++- core/pxelinux.asm | 146 +-------------------------------------- 9 files changed, 98 insertions(+), 152 deletions(-) diff --git a/com32/include/syslinux/pxe_api.h b/com32/include/syslinux/pxe_api.h index 6c9efc24..fcc4f873 100644 --- a/com32/include/syslinux/pxe_api.h +++ b/com32/include/syslinux/pxe_api.h @@ -408,6 +408,11 @@ typedef struct s_PXENV_GET_FILE_SIZE { uint16_t FileHandle; uint32_t FileSize; } __packed t_PXENV_GET_FILE_SIZE; + +typedef struct s_PXENV_UNLOAD_STACK { + pxenv_status_t Status; + uint8_t reserved[10]; +} __packed t_PXENV_UNLOAD_STACK; #define PXENV_UNDI_ISR_IN_START 1 #define PXENV_UNDI_ISR_IN_PROCESS 2 diff --git a/core/bootsect.inc b/core/bootsect.inc index 4d70998c..23b4fdb4 100644 --- a/core/bootsect.inc +++ b/core/bootsect.inc @@ -80,7 +80,7 @@ load_bootsec: xor bx,bx %elif IS_PXELINUX mov byte [KeepPXE],03h ; Chainloading + keep PXE - call reset_pxe + pm_call reset_pxe lfs si,[InitStack] ; Put restore DS, EDX and ESI to the true initial values mov bx,[fs:si+6] diff --git a/core/comboot.inc b/core/comboot.inc index 731e4327..72f642e4 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -635,7 +635,7 @@ comapi_cleanup: test dl,3 setnz [KeepPXE] sub bp,sp ; unload_pxe may move the stack around - call unload_pxe + pm_call unload_pxe add bp,sp ; restore frame pointer... %elif IS_SYSLINUX || IS_EXTLINUX ; Restore original FDC table diff --git a/core/extern.inc b/core/extern.inc index 20adb768..6ce807a7 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -19,4 +19,7 @@ ; dir.c extern opendir, readdir, closedir + ; pxe.c + extern unload_pxe, reset_pxe + %endif ; EXTERN_INC diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 8c006fea..a4537855 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -23,6 +23,16 @@ const uint8_t TimeoutTable[] = { 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0 }; +/* PXE unload sequences */ +const uint8_t new_api_unload[] = { + PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN, + PXENV_UNLOAD_STACK, PXENV_STOP_UNDI, 0 +}; +const uint8_t old_api_unload[] = { + PXENV_UDP_CLOSE, PXENV_UNDI_SHUTDOWN, + PXENV_UNLOAD_STACK, PXENV_UNDI_CLEANUP, 0 +}; + struct tftp_options { const char *str_ptr; /* string pointer */ size_t offset; /* offset into socket structre */ @@ -1471,9 +1481,66 @@ static int pxe_fs_init(struct fs_info *fs) /* Network-specific initialization */ network_init(); - + return 0; } + +inline void reset_pxe(void) +{ + static __lowmem struct s_PXENV_UDP_CLOSE udp_close; + pxe_call(PXENV_UDP_CLOSE, &udp_close); +} + +/* + * This function unloads the PXE and UNDI stacks and + * unclaims the memory. + */ +void unload_pxe(void) +{ + uint8_t api; + const uint8_t *api_ptr; + uint16_t flag = 0; + int err; + int int_addr; + static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack; + + if (KeepPXE) { + /* + * We want to keep PXE around, but still we should reset + * it to the standard bootup configuration. + */ + reset_pxe(); + return; + } + + api_ptr = major_ver(APIVer) >= 2 ? new_api_unload : old_api_unload; + while((api = *api_ptr++)) { + memset(&unload_stack, 0, sizeof unload_stack); + err = pxe_call(api, &unload_stack); + if (err || unload_stack.Status != PXENV_STATUS_SUCCESS) + goto cant_free; + } + + flag = 0xff00; + if (RealBaseMem <= BIOS_fbm) /* Santiy check */ + goto cant_free; + flag ++; + + /* Check that PXE actually unhooked the INT 0x1A chain */ + int_addr = (int)MK_PTR(*(uint16_t *)(4*0x1a+2), *(uint16_t *)(4*0x1a)); + int_addr >>= 10; + if (int_addr >= RealBaseMem || int_addr < BIOS_fbm) { + BIOS_fbm = RealBaseMem; + return; + } + +cant_free: + printf("Failed to free base memory error %04x-%08x\n", + flag, *(uint32_t *)(4 * 0x1a)); + return; +} + + const struct fs_ops pxe_fs_ops = { .fs_name = "pxe", diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 864815bd..7c30d66e 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -26,11 +26,12 @@ */ #define TFTP_PORT htons(69) /* Default TFTP port */ #define TFTP_BLOCKSIZE_LG2 9 -#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) -#define PKTBUF_SEG 0x4000 -#define PKTBUF_SIZE (65536 / MAX_OPEN) +#define TFTP_BLOCKSIZE (1 << TFTP_BLOCKSIZE_LG2) +#define PKTBUF_SEG 0x4000 +#define PKTBUF_SIZE (65536 / MAX_OPEN) -#define is_digit(c) (((c) >= '0') && ((c) <= '9')) +#define is_digit(c) (((c) >= '0') && ((c) <= '9')) +#define major_ver(v) (((v) >> 8) && 0xff) /* * TFTP operation codes diff --git a/core/include/core.h b/core/include/core.h index 52a35d4e..61097a63 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -76,6 +76,7 @@ extern char DNSRecvBuf[]; extern uint16_t RealBaseMem; extern uint16_t APIVer; extern far_ptr_t PXEEntry; +extern uint8_t KeepPXE; extern far_ptr_t InitStack; @@ -84,6 +85,7 @@ extern uint8_t UUIDType; extern char UUID[]; extern volatile uint16_t BIOS_timer; +extern uint16_t BIOS_fbm; extern const uint8_t TimeoutTable[]; #endif /* CORE_H */ diff --git a/core/pxeidle.inc b/core/pxeidle.inc index ef3e1b7f..4cfdc1b0 100644 --- a/core/pxeidle.inc +++ b/core/pxeidle.inc @@ -18,8 +18,18 @@ ;; Query for the NIC type, and detect certain special cases. ;; - section .text16 + section .bss16 + pxe_udp_read_pkt: +.status: resw 1 ; Status +.sip: resd 1 ; Source IP +.dip: resd 1 ; Destination (our) IP +.rport: resw 1 ; Remote port +.lport: resw 1 ; Local port +.buffersize: resw 1 ; Max packet size +.buffer: resw 2 ; seg:off of buffer + + section .text16 ;; ;; Initializes the idle mechanism based on the device type ;; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 8f0b7acd..7643d009 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -127,17 +127,6 @@ UUIDType resb 1 ; Type byte from DHCP option UUID resb 16 ; UUID, from the PXE stack UUIDNull resb 1 ; dhcp_copyoption zero-terminates -; -; PXE packets which don't need static initialization -; - alignb 4 -pxe_unload_stack_pkt: -.status: resw 1 ; Status -.reserved: resb 10 ; Reserved -pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt - - alignb 16 - ; BOOTP/DHCP packet buffer section .bss16 global packet_buf @@ -250,7 +239,7 @@ _start1: ; Unload PXE stack %define HAVE_UNLOAD_PREP %macro UNLOAD_PREP 0 - call unload_pxe + pm_call unload_pxe %endmacro ; @@ -397,104 +386,6 @@ pxe_int1a: %endif ret -; -; unload_pxe: -; -; This function unloads the PXE and UNDI stacks and unclaims -; the memory. -; -unload_pxe: - cmp byte [KeepPXE],0 ; Should we keep PXE around? - jne reset_pxe - - push ds - push es - - mov ax,cs - mov ds,ax - mov es,ax - - mov si,new_api_unload - cmp byte [APIVer+1],2 ; Major API version >= 2? - jae .new_api - mov si,old_api_unload -.new_api: - -.call_loop: xor ax,ax - lodsb - and ax,ax - jz .call_done - xchg bx,ax - mov di,pxe_unload_stack_pkt - push di - xor ax,ax - mov cx,pxe_unload_stack_pkt_len >> 1 - rep stosw - pop di - call pxenv - jc .cant_free - mov ax,word [pxe_unload_stack_pkt.status] - cmp ax,PXENV_STATUS_SUCCESS - jne .cant_free - jmp .call_loop - -.call_done: - mov bx,0FF00h - - mov dx,[RealBaseMem] - cmp dx,[BIOS_fbm] ; Sanity check - jna .cant_free - inc bx - - ; Check that PXE actually unhooked the INT 1Ah chain - movzx eax,word [4*0x1a] - movzx ecx,word [4*0x1a+2] - shl ecx,4 - add eax,ecx - shr eax,10 - cmp ax,dx ; Not in range - jae .ok - cmp ax,[BIOS_fbm] - jae .cant_free - ; inc bx - -.ok: - mov [BIOS_fbm],dx -.pop_ret: - pop es - pop ds - ret - -.cant_free: - mov si,cant_free_msg - call writestr_early - push ax - xchg bx,ax - call writehex4 - mov al,'-' - call writechr - pop ax - call writehex4 - mov al,'-' - call writechr - mov eax,[4*0x1a] - call writehex8 - call crlf - jmp .pop_ret - - ; We want to keep PXE around, but still we should reset - ; it to the standard bootup configuration -reset_pxe: - push es - push cs - pop es - mov bx,PXENV_UDP_CLOSE - mov di,pxe_udp_close_pkt - call pxenv - pop es - ret - - ; ----------------------------------------------------------------------------- ; Common modules @@ -540,46 +431,13 @@ exten_table: db '.cbt' ; COMBOOT (specific) exten_table_end: dd 0, 0 ; Need 8 null bytes here -; -; PXE unload sequences -; -new_api_unload: - db PXENV_UDP_CLOSE - db PXENV_UNDI_SHUTDOWN - db PXENV_UNLOAD_STACK - db PXENV_STOP_UNDI - db 0 -old_api_unload: - db PXENV_UDP_CLOSE - db PXENV_UNDI_SHUTDOWN - db PXENV_UNLOAD_STACK - db PXENV_UNDI_CLEANUP - db 0 - -; -; PXE query packets partially filled in -; - section .bss16 -pxe_udp_close_pkt: -.status: resw 1 ; Status - -pxe_udp_read_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Source IP -.dip: resd 1 ; Destination (our) IP -.rport: resw 1 ; Remote port -.lport: resw 1 ; Local port -.buffersize: resw 1 ; Max packet size -.buffer: resw 2 ; seg:off of buffer - - ; ; Misc initialized (data) variables ; section .data16 alignz 4 - global BaseStack + global BaseStack, KeepPXE BaseStack dd StackTop ; ESP of base stack dw 0 ; SS of base stack KeepPXE db 0 ; Should PXE be kept around? -- cgit v1.2.1 From e2d252347b046b157a65cbcb82d5909a494b6682 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Sun, 30 Aug 2009 07:05:58 +0800 Subject: Core:pxelinux: code clean Two main things: 1. Redeclare the varibales that are't needed by any asm files in C file. 2. Move the extern statements of PXELINUX into pxe.h, instead of in core.h Signed-off-by: Liu Aleaxander --- core/fs/pxe/dhcp_option.c | 57 ++++++++++++++------------- core/fs/pxe/dnsresolv.c | 2 +- core/fs/pxe/pxe.c | 98 ++++++++++++++++++++++++++--------------------- core/fs/pxe/pxe.h | 47 +++++++++++++++++++++++ core/include/core.h | 46 ---------------------- core/pxelinux.asm | 36 ++--------------- 6 files changed, 135 insertions(+), 151 deletions(-) diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c index 9bd20b07..ebe8eb49 100644 --- a/core/fs/pxe/dhcp_option.c +++ b/core/fs/pxe/dhcp_option.c @@ -4,20 +4,23 @@ #include #include "pxe.h" +int over_load; +uint8_t uuid_type; +char uuid[17]; void parse_dhcp_options(void *, int, int); static void subnet_mask(void *data, int opt_len) { if (opt_len != 4) return; - Netmask = *(uint32_t *)data; + net_mask = *(uint32_t *)data; } static void router(void *data, int opt_len) { if (opt_len != 4) return; - Gateway = *(uint32_t *)data; + gate_way = *(uint32_t *)data; } static void dns_servers(void *data, int opt_len) @@ -66,7 +69,7 @@ static void option_overload(void *data, int opt_len) { if (opt_len != 1) return; - OverLoad = *(uint8_t *)data; + over_load = *(uint8_t *)data; } @@ -77,44 +80,44 @@ static void server(void *data, int opt_len) if (opt_len != 4) return; - if (ServerIP) + if (server_ip) return; ip = *(uint32_t *)data; if (ip_ok(ip)) - ServerIP = ip; + server_ip = ip; } static void client_identifier(void *data, int opt_len) { if (opt_len > MAC_MAX || opt_len < 2 || - MACLen != (opt_len >> 8) || - *(uint8_t *)data != MACType) + MAC_len != (opt_len >> 8) || + *(uint8_t *)data != MAC_type) return; opt_len --; - MACLen = opt_len & 0xff; + MAC_len = opt_len & 0xff; memcpy(MAC, data+1, opt_len); MAC[opt_len] = 0; } static void bootfile_name(void *data, int opt_len) { - strncpy(BootFile, data, opt_len); - BootFile[opt_len] = 0; + strncpy(boot_file, data, opt_len); + boot_file[opt_len] = 0; } static void uuid_client_identifier(void *data, int opt_len) { int type = *(uint8_t *)data; if (opt_len != 17 || - (type | HaveUUID)) + (type | have_uuid)) return; - HaveUUID = 1; - UUIDType = type; - memcpy(UUID, data+1, 16); - UUID[16] = 0; + have_uuid = 1; + uuid_type = type; + memcpy(uuid, data+1, 16); + uuid[16] = 0; } static void pxelinux_configfile(void *data, int opt_len) @@ -127,8 +130,8 @@ static void pxelinux_configfile(void *data, int opt_len) static void pxelinux_pathprefix(void *data,int opt_len) { DHCPMagic |= 4; - strncpy(PathPrefix, data, opt_len); - PathPrefix[opt_len] = 0; + strncpy(path_prefix, data, opt_len); + path_prefix[opt_len] = 0; } static void pxelinux_reboottime(void *data, int opt_len) @@ -229,13 +232,13 @@ void parse_dhcp_options(void *option, int size, int filter) ; information is present: ; ; MyIP - client IP address - ; ServerIP - boot server IP address - ; Netmask - network mask - ; Gateway - default gateway router IP - ; BootFile - boot file name + ; server_ip - boot server IP address + ; net_mask - network mask + ; gate_way - default gateway router IP + ; boot_file - boot file name ; DNSServers - DNS server IPs ; LocalDomain - Local domain name - ; MACLen, MAC - Client identifier, if MACLen == 0 + ; MAC_len, MAC - Client identifier, if MAC_len == 0 ; ; This assumes the DHCP packet is in "trackbuf". ; @@ -245,22 +248,22 @@ void parse_dhcp(int pkt_len) struct bootp_t *dhcp = (struct bootp_t *)trackbuf; int opt_len; - OverLoad = 0; + over_load = 0; if (ip_ok(dhcp->yip)) MyIP = dhcp->yip; if (ip_ok(dhcp->sip)) - ServerIP = dhcp->sip; + server_ip = dhcp->sip; opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options; if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) parse_dhcp_options(&dhcp->options, opt_len, 0); - if (OverLoad & 1) + if (over_load & 1) parse_dhcp_options(&dhcp->bootfile, 128, 0); else if (dhcp->bootfile[0]) - strcpy(BootFile, dhcp->bootfile); + strcpy(boot_file, dhcp->bootfile); - if (OverLoad & 2) + if (over_load & 2) parse_dhcp_options(dhcp->sname, 64, 0); } diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index 8fccd372..dbabbb62 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -221,7 +221,7 @@ uint32_t dns_resolv(const char *name) continue; /* just move on before runing the time out */ udp_write.status = 0; udp_write.ip = srv; - udp_write.gw = ((srv ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.gw = ((srv ^ MyIP) & net_mask) ? gate_way : 0; udp_write.src_port = DNS_LOCAL_PORT; udp_write.dst_port = DNS_PORT; udp_write.buffer_size = p - DNSSendBuf; diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index a4537855..e73211c5 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -8,15 +8,25 @@ #define GPXE 1 -uint32_t ServerIP = 0; /* IP address of boot server */ -uint32_t Netmask = 0; /* Netmask of this subnet */ -uint32_t Gateway = 0; /* Default router */ -uint16_t ServerPort = TFTP_PORT; /* TFTP server port */ +uint32_t server_ip = 0; /* IP address of boot server */ +uint32_t net_mask = 0; /* net_mask of this subnet */ +uint32_t gate_way = 0; /* Default router */ +uint16_t server_port = TFTP_PORT; /* TFTP server port */ +uint16_t real_base_mem; /* Amount of DOS memory after freeing */ + +char MAC_str[3 * (MAC_MAX + 1)]; /* MAC address as a string */ +char MAC[MAC_MAX + 1]; /* Actual MAC address */ +uint8_t MAC_len; /* MAC address len */ +uint8_t MAC_type; /* MAC address type */ + +char boot_file[256]; +char path_prefix[256]; +char dot_quad_buf[16]; static struct open_file_t Files[MAX_OPEN]; static int has_gpxe; static uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0}; -int HaveUUID = 0; +int have_uuid = 0; const uint8_t TimeoutTable[] = { 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44, 53, 64, 77, @@ -279,7 +289,7 @@ static void ack_packet(struct open_file_t *file, uint16_t ack_num) udp_write.src_port = file->tftp_localport; udp_write.dst_port = file->tftp_remoteport; udp_write.ip = file->tftp_remoteip; - udp_write.gw = ((udp_write.ip ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0; udp_write.buffer.offs = OFFS(ack_packet_buf); udp_write.buffer.seg = SEG(ack_packet_buf); udp_write.buffer_size = 4; @@ -422,7 +432,7 @@ static void get_packet_gpxe(struct open_file_t *file) static void pxe_mangle_name(char *dst, const char *src) { const char *p = src; - uint32_t ip = ServerIP; + uint32_t ip = server_ip; int i = 0; #if GPXE @@ -723,9 +733,9 @@ static void pxe_searchdir(char *filename, struct file *file) p += 4; if (ip == 0) { /* Have prefix */ - strcpy(buf, PathPrefix); - buf += strlen(PathPrefix); - ip = ServerIP; /* Get the default server */ + strcpy(buf, path_prefix); + buf += strlen(path_prefix); + ip = server_ip; /* Get the default server */ } strcpy(buf, p); /* Copy the filename */ @@ -758,9 +768,9 @@ static void pxe_searchdir(char *filename, struct file *file) open_file->tftp_remoteip = ip; tid = open_file->tftp_localport; /* TID(local port No) */ udp_write.ip = ip; - udp_write.gw = ((udp_write.ip ^ MyIP) & Netmask) ? Gateway : 0; + udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0; udp_write.src_port = tid; - udp_write.dst_port = ServerPort; + udp_write.dst_port = server_port; buf += fill_tail(buf); udp_write.buffer_size = buf - packet_buf; err = pxe_call(PXENV_UDP_WRITE, &udp_write); @@ -983,9 +993,9 @@ static void get_prefix(void) if (DHCPMagic & 0x04) /* Did we get a path prefix option */ goto got_prefix; - strcpy(PathPrefix, BootFile); - len = strlen(PathPrefix); - p = &PathPrefix[len - 1]; + strcpy(path_prefix, boot_file); + len = strlen(path_prefix); + p = &path_prefix[len - 1]; while (len--) { c = *p--; @@ -1004,8 +1014,8 @@ static void get_prefix(void) *(p + 2) = 0; /* Zero-terminate after delimiter */ got_prefix: - printf("TFTP prefix: %s\n", PathPrefix); - strcpy(CurrentDirName, PathPrefix); + printf("TFTP prefix: %s\n", path_prefix); + strcpy(CurrentDirName, path_prefix); } /* @@ -1062,12 +1072,12 @@ static void pxe_load_config(com32sys_t *regs) */ /* Try loading by UUID */ - if (HaveUUID) { + if (have_uuid) { uuid_ptr = uuid_dashes; p = config_file; while (*uuid_ptr) { int len = *uuid_ptr; - char *src = UUID; + char *src = uuid; lchexbytes(p, src, len); p += len * 2; @@ -1083,7 +1093,7 @@ static void pxe_load_config(com32sys_t *regs) } /* Try loading by MAC address */ - strcpy(config_file, MACStr); + strcpy(config_file, MAC_str); regs->edi.w[0] = OFFS_WRT(ConfigName, 0); if (try_load(regs)) return; @@ -1121,13 +1131,14 @@ static void pxe_load_config(com32sys_t *regs) */ static void make_bootif_string(void) { - char *bootif_str = "BOOTIF="; - uint8_t *src = &MACType; /* MACType just followed by MAC */ - char *dst; - int i = MACLen + 1; /* MACType included */ - - strcpy(BOOTIFStr, bootif_str); - dst = strchr(BOOTIFStr, '\0'); + char mac[18]; + char *src = mac; + char *dst = MAC_str; + int i = MAC_len + 1; + + *(uint8_t *)src++ = MAC_type; + memcpy(src, MAC, MAC_len); + src = mac; for (; i > 0; i--) { lchexbytes(dst, src, 1); dst += 2; @@ -1135,6 +1146,8 @@ static void make_bootif_string(void) *dst++ = '-'; } *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */ + strcat(BOOTIFStr, "BOOTIF="); + strcat(BOOTIFStr, MAC_str); #if 0 printf("%s\n", BOOTIFStr); @@ -1157,31 +1170,28 @@ static void genipopt(void) p += ip_len; *p++ = ':'; - ip_len = gendotquad(p, ServerIP); + ip_len = gendotquad(p, server_ip); p += ip_len; *p++ = ':'; - ip_len = gendotquad(p, Gateway); + ip_len = gendotquad(p, gate_way); p += ip_len; *p++ = ':'; - ip_len = gendotquad(p, Netmask); + ip_len = gendotquad(p, net_mask); } /* Generate ip= option and print the ip adress */ static void ip_init(void) { - int ip = MyIP; - char *myipaddr_msg = "My IP address seems to be "; - + uint32_t ip = MyIP; + genipopt(); - - gendotquad(DotQuadBuf, ip); + gendotquad(dot_quad_buf, ip); ip = ntohl(ip); - printf("%s %08X %s\n", myipaddr_msg, ip, DotQuadBuf); - + printf("My IP address seems to be %08X %s\n", ip, dot_quad_buf); printf("%s\n", IPOption); } @@ -1381,7 +1391,7 @@ static void pxe_init(void) code_seg = code_seg + ((code_len + 15) >> 4); data_seg = data_seg + ((data_len + 15) >> 4); - RealBaseMem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */ + real_base_mem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */ } /* @@ -1440,9 +1450,9 @@ static void network_init(void) * turns out to be problematic it might be better getting it from * the query info 1 packet */ - MACLen = bp->hardlen > 16 ? 0 : bp->hardlen; - MACType = bp->hardware; - memcpy(MAC, bp->macaddr, MACLen); + MAC_len = bp->hardlen > 16 ? 0 : bp->hardlen; + MAC_type = bp->hardware; + memcpy(MAC, bp->macaddr, MAC_len); /* * Get the boot file and other info. This lives in the CACHED_REPLY @@ -1522,15 +1532,15 @@ void unload_pxe(void) } flag = 0xff00; - if (RealBaseMem <= BIOS_fbm) /* Santiy check */ + if (real_base_mem <= BIOS_fbm) /* Santiy check */ goto cant_free; flag ++; /* Check that PXE actually unhooked the INT 0x1A chain */ int_addr = (int)MK_PTR(*(uint16_t *)(4*0x1a+2), *(uint16_t *)(4*0x1a)); int_addr >>= 10; - if (int_addr >= RealBaseMem || int_addr < BIOS_fbm) { - BIOS_fbm = RealBaseMem; + if (int_addr >= real_base_mem || int_addr < BIOS_fbm) { + BIOS_fbm = real_base_mem; return; } diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 7c30d66e..224b8a26 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -156,6 +156,53 @@ struct open_file_t { uint16_t tftp_pktbuf; /* Packet buffer offset */ } __attribute__ ((packed)); +/* + * Variable externs + */ +extern uint32_t server_ip; +extern uint32_t MyIP; +extern uint32_t net_mask; +extern uint32_t gate_way; +extern uint16_t server_port; + +extern char MAC_str[]; +extern char MAC[]; +extern char BOOTIFStr[]; +extern uint8_t MAC_len; +extern uint8_t MAC_type; + +extern uint8_t DHCPMagic; +extern uint32_t RebootTime; + +extern char boot_file[]; +extern char path_prefix[]; +extern char LocalDomain[]; + +extern char packet_buf[]; + +extern char IPOption[]; +extern char dot_quad_buf[]; + +extern uint32_t dns_server[]; +extern char DNSSendBuf[]; +extern char DNSRecvBuf[]; + +extern uint16_t real_base_mem; +extern uint16_t APIVer; +extern far_ptr_t PXEEntry; +extern uint8_t KeepPXE; + +extern far_ptr_t InitStack; + +extern int have_uuid; +extern uint8_t uuid_type; +extern char uuid[]; + +extern volatile uint16_t BIOS_timer; +extern uint16_t BIOS_fbm; +extern const uint8_t TimeoutTable[]; + + /* * functions */ diff --git a/core/include/core.h b/core/include/core.h index 61097a63..9ab03517 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -41,51 +41,5 @@ void call16(void (*)(void), const com32sys_t *, com32sys_t *); __noreturn _kaboom(void); #define kaboom() _kaboom() -/* - * externs for pxelinux - */ -extern uint32_t ServerIP; -extern uint32_t MyIP; -extern uint32_t Netmask; -extern uint32_t Gateway; -extern uint16_t ServerPort; - -extern char MACStr[]; /* MAC address as a string */ -extern char MAC[]; /* Actual MAC address */ -extern char BOOTIFStr[]; /* Space for "BOOTIF=" */ -extern uint8_t MACLen; /* MAC address len */ -extern uint8_t MACType; /* MAC address type */ - -extern uint8_t DHCPMagic; -extern uint8_t OverLoad; -extern uint32_t RebootTime; - -extern char BootFile[]; -extern char PathPrefix[]; -extern char LocalDomain[]; - -extern char packet_buf[]; - -extern char IPOption[]; -extern char DotQuadBuf[]; - -extern uint32_t dns_server[]; -extern char DNSSendBuf[]; -extern char DNSRecvBuf[]; - -extern uint16_t RealBaseMem; -extern uint16_t APIVer; -extern far_ptr_t PXEEntry; -extern uint8_t KeepPXE; - -extern far_ptr_t InitStack; - -extern int HaveUUID; -extern uint8_t UUIDType; -extern char UUID[]; - -extern volatile uint16_t BIOS_timer; -extern uint16_t BIOS_fbm; -extern const uint8_t TimeoutTable[]; #endif /* CORE_H */ diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 7643d009..e8c81301 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -44,17 +44,6 @@ TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2) SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2 SECTOR_SIZE equ TFTP_BLOCKSIZE -; -; TFTP operation codes -; -TFTP_ACK equ htons(4) ; ACK packet -TFTP_ERROR equ htons(5) ; ERROR packet - -; -; TFTP error codes -; -TFTP_EOPTNEG equ htons(8) ; Option negotiation failure - ; ; The following structure is used for "virtual kernels"; i.e. LILO-style ; option labels. The options we permit here are `kernel' and `append @@ -94,39 +83,21 @@ InitStack resd 1 section .bss16 alignb FILENAME_MAX - global BootFile, PathPrefix, DotQuadBuf, IPOption -BootFile resb 256 ; Boot file from DHCP packet -PathPrefix resb 256 ; Path prefix derived from boot file -DotQuadBuf resb 16 ; Buffer for dotted-quad IP address + global IPOption IPOption resb 80 ; ip= option buffer PXEStack resd 1 ; Saved stack during PXE call alignb 4 - global DHCPMagic, OverLoad, RebootTime, APIVer, RealBaseMem - global StructPtr + global DHCPMagic, RebootTime, APIVer RebootTime resd 1 ; Reboot timeout, if set by option StrucPtr resw 2 ; Pointer to PXENV+ or !PXE structure APIVer resw 1 ; PXE API version found LocalBootType resw 1 ; Local boot return code -RealBaseMem resw 1 ; Amount of DOS memory after freeing -OverLoad resb 1 ; Set if DHCP packet uses "overloading" DHCPMagic resb 1 ; PXELINUX magic flags ; The relative position of these fields matter! - global MACStr, MACLen, MACType, MAC, BOOTIFStr -MAC_MAX equ 32 ; Handle hardware addresses this long -MACLen resb 1 ; MAC address len -MACType resb 1 ; MAC address type -MAC resb MAC_MAX+1 ; Actual MAC address + global BOOTIFStr BOOTIFStr resb 7 ; Space for "BOOTIF=" -MACStr resb 3*(MAC_MAX+1) ; MAC address as a string - -; The relative position of these fields matter! - global UUID, UUIDType -UUIDType resb 1 ; Type byte from DHCP option -UUID resb 16 ; UUID, from the PXE stack -UUIDNull resb 1 ; dhcp_copyoption zero-terminates - section .bss16 global packet_buf @@ -410,7 +381,6 @@ copyright_str db ' Copyright (C) 1994-' db ' H. Peter Anvin et al', CR, LF, 0 err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0 bailmsg equ err_bootfailed -cant_free_msg db 'Failed to free base memory, error ', 0 localboot_msg db 'Booting from local disk...', CR, LF, 0 syslinux_banner db CR, LF, 'PXELINUX ', VERSION_STR, ' ', DATE_STR, ' ', 0 -- cgit v1.2.1 From 53af19b2336ac0342856498e413dab22d0d6300f Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 31 Aug 2009 04:25:00 +0800 Subject: Core:pxelinux: add %if IS_PXELINUX statement in extern.inc Add this to avoid the compile error. Signed-off-by: Liu Aleaxander --- core/extern.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/extern.inc b/core/extern.inc index 6ce807a7..95a9c88d 100644 --- a/core/extern.inc +++ b/core/extern.inc @@ -18,8 +18,9 @@ ; dir.c extern opendir, readdir, closedir - +%if IS_PXELINUX ; pxe.c extern unload_pxe, reset_pxe +%endif %endif ; EXTERN_INC -- cgit v1.2.1 From 8b584217d5b18b7737c344bfb45570af1379da24 Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 31 Aug 2009 05:51:38 +0800 Subject: Core: get rid of passing com32sys_t structure as parameter in PMode Well, this molstly be about xxx_load_config function, with function type changed. The new load_config function will return 1 if failed, or 0 if successed. Signed-off-by: Liu Aleaxander --- core/fs.c | 9 +++-- core/fs/ext2/ext2.c | 17 +++++---- core/fs/fat/fat.c | 19 +++++----- core/fs/iso9660/iso9660.c | 19 ++++------ core/fs/pxe/pxe.c | 91 +++++++++++++++++++---------------------------- core/include/core.h | 2 +- core/include/fs.h | 2 +- 7 files changed, 71 insertions(+), 88 deletions(-) diff --git a/core/fs.c b/core/fs.c index f7bf68c2..a3407cfe 100644 --- a/core/fs.c +++ b/core/fs.c @@ -55,9 +55,14 @@ inline struct file *handle_to_file(uint16_t handle) return handle ? &files[handle-1] : NULL; } -void load_config(com32sys_t *regs) +void load_config(void) { - this_fs->fs_ops->load_config(regs); + int err; + err = this_fs->fs_ops->load_config(); + +#if 0 + printf("Loading config file %s\n", err ? "failed" : "successed"); +#endif } void mangle_name(com32sys_t *regs) diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c index dcd4a49b..7db45fc1 100644 --- a/core/fs/ext2/ext2.c +++ b/core/fs/ext2/ext2.c @@ -679,21 +679,20 @@ static void ext2_searchdir(char *filename, struct file *file) } -static void ext2_load_config(com32sys_t *regs) +/* Load the config file, return 1 if failed, or 0 */ +static int ext2_load_config(void) { char *config_name = "extlinux.conf"; + com32sys_t regs; strcpy(ConfigName, config_name); *(uint32_t *)CurrentDirName = 0x00002f2e; + + memset(®s, 0, sizeof regs); + regs.edi.w[0] = OFFS_WRT(ConfigName, 0); + call16(core_open, ®s, ®s); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - call16(core_open, regs, regs); - -#if 0 - printf("the zero flag is %s\n", regs->eax.w[0] ? \ - "CLEAR, means we found the config file" : - "SET, menas we didn't find the config file"); -#endif + return regs.eflags.l & EFLAGS_ZF; } diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c index 58226a71..e7931b0f 100644 --- a/core/fs/fat/fat.c +++ b/core/fs/fat/fat.c @@ -797,16 +797,16 @@ struct dirent* vfat_readdir(struct file *dir) return &de; } -static void vfat_load_config(com32sys_t *regs) +/* Load the config file, return 1 if failed, or 0 */ +static int vfat_load_config(void) { static const char syslinux_cfg1[] = "/boot/syslinux/syslinux.cfg"; static const char syslinux_cfg2[] = "/syslinux/syslinux.cfg"; static const char syslinux_cfg3[] = "/syslinux.cfg"; - static const char config_name[] = "syslinux.cfg"; - + static const char config_name[] = "syslinux.cfg"; const char * const syslinux_cfg[] = { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 }; - com32sys_t oregs; + com32sys_t regs; int i = 0; *(uint16_t *)CurrentDirName = ROOT_DIR_WORD; @@ -816,25 +816,26 @@ static void vfat_load_config(com32sys_t *regs) * we use the ConfigName to pass the config path because * it is under the address 0xffff */ - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); + memset(®s, 0, sizeof regs); + regs.edi.w[0] = OFFS_WRT(ConfigName, 0); for (; i < 3; i++) { strcpy(ConfigName, syslinux_cfg[i]); - memset(&oregs, 0, sizeof oregs); - call16(core_open, regs, &oregs); + call16(core_open, ®s, ®s); /* if zf flag set, then failed; try another */ - if (! (oregs.eflags.l & EFLAGS_ZF)) + if (! (regs.eflags.l & EFLAGS_ZF)) break; } if (i == 3) { printf("no config file found\n"); - return; /* no config file */ + return 1; /* no config file */ } strcpy(ConfigName, config_name); strcpy(CurrentDirName, syslinux_cfg[i]); CurrentDirName[strlen(syslinux_cfg[i])-strlen(config_name)] = '\0'; CurrentDir = PrevDir; + return 0; } static inline __constfunc uint32_t bsr(uint32_t num) diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 68d57363..eb9dede8 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -445,23 +445,18 @@ static void iso_searchdir(char *filename, struct file *file) #endif } -static void iso_load_config(com32sys_t *regs) +/* Load the config file, return 1 if failed, or 0 */ +static int iso_load_config(void) { char *config_name = "isolinux.cfg"; + com32sys_t regs; -#if DEBUG - printf("About to load config file...\n"); -#endif - + memset(®s, 0, sizeof regs); strcpy(ConfigName, config_name); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - call16(core_open, regs, regs); + regs.edi.w[0] = OFFS_WRT(ConfigName, 0); + call16(core_open, ®s, ®s); -#if DEBUG - printf("the zero flag is %s\n", regs->eax.w[0] ? - "CLEAR, means we found the config file" : - "SET, menas we didn't find the config file"); -#endif + return regs.eflags.l & EFLAGS_ZF; } diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index e73211c5..bbc77e04 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -254,20 +254,19 @@ static const char *parse_dotquad(const char *ip_str, uint32_t *res) int pxe_call(int opcode, void *data) { extern void pxenv(void); - com32sys_t in_regs, out_regs; + com32sys_t regs; #if 0 printf("pxe_call op %04x data %p\n", opcode, data); #endif - memset(&in_regs, 0, sizeof in_regs); - - in_regs.ebx.w[0] = opcode; - in_regs.es = SEG(data); - in_regs.edi.w[0] = OFFS(data); - call16(pxenv, &in_regs, &out_regs); + memset(®s, 0, sizeof regs); + regs.ebx.w[0] = opcode; + regs.es = SEG(data); + regs.edi.w[0] = OFFS(data); + call16(pxenv, ®s, ®s); - return out_regs.eflags.l & EFLAGS_CF; /* CF SET if fail */ + return regs.eflags.l & EFLAGS_CF; /* CF SET if fail */ } /** @@ -1022,17 +1021,17 @@ static void get_prefix(void) * try to load a config file, if found, return 1, or return 0 * */ -static int try_load(com32sys_t *regs) +static int try_load(char *config_name) { - extern char KernelName[]; - char *config_name = (char *)MK_PTR(regs->ds, regs->edi.w[0]); - + com32sys_t regs; + printf("Trying to load: %-50s ", config_name); pxe_mangle_name(KernelName, config_name); - regs->edi.w[0] = OFFS_WRT(KernelName, 0); - call16(core_open, regs, regs); - if (regs->eflags.l & EFLAGS_ZF) { + memset(®s, 0, sizeof regs); + regs.edi.w[0] = OFFS_WRT(KernelName, 0); + call16(core_open, ®s, ®s); + if (regs.eflags.l & EFLAGS_ZF) { printf(" [FAILED]\n"); return 0; } else { @@ -1042,35 +1041,31 @@ static int try_load(com32sys_t *regs) } - /* - * load configuration file - * - */ -static void pxe_load_config(com32sys_t *regs) +/* Load the config file, return 1 if failed, or 0 */ +static int pxe_load_config(void) { - char *cfgprefix = "pxelinux.cfg/"; - char *default_str = "default"; - char *config_file; /* Pointer to the variable suffix */ - char *p; - + const char *cfgprefix = "pxelinux.cfg/"; + const char *default_str = "default"; + char *config_file; + char *last; + char *p; uint8_t *uuid_ptr; - int tries = 8; - char *last; get_prefix(); if (DHCPMagic & 0x02) { /* We got a DHCP option, try it first */ - if (try_load(regs)) - return; + /* XXX: I have no idea where the config_file came from */ + //if (try_load(NULL)) + //return 0; } - memcpy(ConfigName, cfgprefix, strlen(cfgprefix)); - config_file = ConfigName + strlen(cfgprefix); /* * Have to guess config file name ... - */ - + */ + memcpy(ConfigName, cfgprefix, strlen(cfgprefix)); + config_file = ConfigName + strlen(cfgprefix); + /* Try loading by UUID */ if (have_uuid) { uuid_ptr = uuid_dashes; @@ -1087,44 +1082,34 @@ static void pxe_load_config(com32sys_t *regs) } /* Remove last dash and zero-terminate */ *--p = '\0'; - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; + if (try_load(ConfigName)) + return 0; } /* Try loading by MAC address */ strcpy(config_file, MAC_str); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; - -#if 0 - printf("MY IP: %p(%X)\n", MyIP, *(uint32_t *)MyIP); - #endif + if (try_load(ConfigName)) + return 0; /* Nope, try hexadecimal IP prefixes... */ uchexbytes(config_file, (uint8_t *)&MyIP, 4); /* Convet to hex string */ last = &config_file[8]; while (tries) { *last = '\0'; /* Zero-terminate string */ - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; + if (try_load(ConfigName)) + return 0; last--; /* Drop one character */ tries--; }; /* Final attempt: "default" string */ strcpy(config_file, default_str); - regs->edi.w[0] = OFFS_WRT(ConfigName, 0); - if (try_load(regs)) - return; + if (try_load(ConfigName)) + return 0; printf("Unable to locate configuration file\n"); kaboom(); } - - /* * Generate the botif string, and the hardware-based config string @@ -1319,9 +1304,7 @@ static void pxe_init(void) if (is_pxenv(pxenv)) goto have_pxenv; - /* - * Plan C: PXENV+ structure via INT 1Ah AX=5650h - */ + /* Plan C: PXENV+ structure via INT 1Ah AX=5650h */ plan++; memset(®s, 0, sizeof regs); regs.eax.w[0] = 0x5650; diff --git a/core/include/core.h b/core/include/core.h index 9ab03517..004c729f 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -9,7 +9,7 @@ extern char core_cache_buf[65536]; extern char trackbuf[]; extern char CurrentDirName[]; extern char ConfigName[]; - +extern char KernelName[]; /* diskstart.inc isolinux.asm*/ extern void getlinsec(void); diff --git a/core/include/fs.h b/core/include/fs.h index e66c3bde..df103023 100644 --- a/core/include/fs.h +++ b/core/include/fs.h @@ -49,7 +49,7 @@ struct fs_ops { void (*close_file)(struct file *); void (*mangle_name)(char *, const char *); char * (*unmangle_name)(char *, const char *); - void (*load_config)(com32sys_t *); + int (*load_config)(); /* the _dir_ stuff */ void (*opendir)(com32sys_t *); -- cgit v1.2.1 From 53793f217eef16ac53000730fa364efb3b3f4a7a Mon Sep 17 00:00:00 2001 From: Liu Aleaxander Date: Mon, 31 Aug 2009 06:22:26 +0800 Subject: Core:pxelinux: fix the config file loading when we got a DHCP option I knew what the DHCP option is now. Signed-off-by: Liu Aleaxander --- core/fs/pxe/pxe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index bbc77e04..37ba0310 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -1055,9 +1055,8 @@ static int pxe_load_config(void) get_prefix(); if (DHCPMagic & 0x02) { /* We got a DHCP option, try it first */ - /* XXX: I have no idea where the config_file came from */ - //if (try_load(NULL)) - //return 0; + if (try_load(boot_file)) + return 0; } /* -- cgit v1.2.1 From 0396e62e734b8d919f395adfe09d0046b840a823 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 30 Aug 2009 09:46:45 -0700 Subject: core: booleanize the return value from *_load_config() The *_load_config() file is specific to each filesystem, and documented to return 0 or 1. Make sure the return value actually is zero or one. Signed-off-by: H. Peter Anvin --- core/fs/ext2/ext2.c | 2 +- core/fs/iso9660/iso9660.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c index 7db45fc1..8c44b3ae 100644 --- a/core/fs/ext2/ext2.c +++ b/core/fs/ext2/ext2.c @@ -692,7 +692,7 @@ static int ext2_load_config(void) regs.edi.w[0] = OFFS_WRT(ConfigName, 0); call16(core_open, ®s, ®s); - return regs.eflags.l & EFLAGS_ZF; + return !!(regs.eflags.l & EFLAGS_ZF); } diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index eb9dede8..e060b13d 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -456,7 +456,7 @@ static int iso_load_config(void) regs.edi.w[0] = OFFS_WRT(ConfigName, 0); call16(core_open, ®s, ®s); - return regs.eflags.l & EFLAGS_ZF; + return !!(regs.eflags.l & EFLAGS_ZF); } -- cgit v1.2.1 From 5d32a45d1a7801d15a69a353db2fa8f33806d298 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 31 Aug 2009 20:55:11 -0700 Subject: core: drop any .eh_frame sections We have no use of .eh_frames... Signed-off-by: H. Peter Anvin --- core/syslinux.ld | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/syslinux.ld b/core/syslinux.ld index 3032dd2d..50e73050 100644 --- a/core/syslinux.ld +++ b/core/syslinux.ld @@ -326,4 +326,9 @@ SECTIONS /* COM32R and kernels are loaded after our own PM code */ . = ALIGN(65536); free_high_memory = .; + + /* Stuff we don't need... */ + /DISCARD/ : { + *(.eh_frame) + } } -- cgit v1.2.1 From b381542a3f987dfe33cbb635beee214efc2de642 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 1 Sep 2009 16:58:11 -0700 Subject: core: pxe: port the PXE idle function to C Port the PXE idle function to C; make the idle hook a protected-mode call. Signed-off-by: H. Peter Anvin --- core/fs/pxe/idle.c | 110 +++++++++++++++++++++++++++++++++++++++++++ core/fs/pxe/pxe.c | 7 ++- core/fs/pxe/pxe.h | 3 ++ core/idle.inc | 14 ++++-- core/include/core.h | 4 +- core/pxeidle.inc | 132 ---------------------------------------------------- core/pxelinux.asm | 4 +- 7 files changed, 133 insertions(+), 141 deletions(-) create mode 100644 core/fs/pxe/idle.c delete mode 100644 core/pxeidle.inc diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c new file mode 100644 index 00000000..5b51d608 --- /dev/null +++ b/core/fs/pxe/idle.c @@ -0,0 +1,110 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include "pxe.h" + +static void pxe_idle_poll(void) +{ + static __lowmem char junk_pkt[PKTBUF_SIZE]; + static __lowmem t_PXENV_UDP_READ read_buf; + + memset(&read_buf, 0, sizeof read_buf); + + read_buf.src_ip = 0; /* Any destination */ + read_buf.dest_ip = MyIP; + read_buf.s_port = 0; /* Any source port */ + read_buf.d_port = htons(9); /* Discard port (not used...) */ + read_buf.buffer_size = sizeof junk_pkt; + read_buf.buffer.offs = OFFS(junk_pkt); + read_buf.buffer.seg = SEG(junk_pkt); + + pxe_call(PXENV_UDP_READ, &read_buf); +} + +static uint32_t pxe_detect_nic_type(void) +{ + static __lowmem t_PXENV_UNDI_GET_NIC_TYPE nic_type; + + if (pxe_call(PXENV_UNDI_GET_NIC_TYPE, &nic_type)) + return -1; /* Unknown NIC */ + + if (nic_type.NicType != PCI_NIC && nic_type.NicType != CardBus_NIC) + return -1; /* Not a PCI NIC */ + + /* + * Return VID:DID as a single number, with the VID in the high word + * -- this is opposite from the usual order, but it makes it easier to + * enforce that the table is sorted. + */ + return (nic_type.info.pci.Vendor_ID << 16) + nic_type.info.pci.Dev_ID; +} + +#define PCI_DEV(vid, did) (((vid) << 16) + (did)) + +/* This array should be sorted!! */ +static const uint32_t pxe_need_idle_drain[] = +{ + /* + * Older Broadcom NICs: they need receive calls on idle to avoid + * FIFO stalls. + */ + PCI_DEV(0x14e4, 0x1659), /* BCM5721 */ + PCI_DEV(0x14e4, 0x165a), /* BCM5722 */ + PCI_DEV(0x14e4, 0x165b), /* BCM5723 */ + PCI_DEV(0x14e4, 0x1668), /* BCM5714 */ + PCI_DEV(0x14e4, 0x1669), /* BCM5714S */ + PCI_DEV(0x14e4, 0x166a), /* BCM5780 */ + PCI_DEV(0x14e4, 0x1673), /* BCM5755M */ + PCI_DEV(0x14e4, 0x1674), /* BCM5756ME */ + PCI_DEV(0x14e4, 0x1678), /* BCM5715 */ + PCI_DEV(0x14e4, 0x1679), /* BCM5715S */ + PCI_DEV(0x14e4, 0x167b), /* BCM5755 */ +}; + +void pxe_idle_init(void) +{ + uint32_t dev_id = pxe_detect_nic_type(); + int l, h; + bool found; + + l = 0; + h = sizeof pxe_need_idle_drain / sizeof pxe_need_idle_drain[0] - 1; + + found = false; + while (h >= l) { + uint32_t e = pxe_need_idle_drain[(l+h) >> 1]; + + if (e == dev_id) { + found = true; + break; + } else if (e < dev_id) { + l = e+1; + } else { + h = e-1; + } + } + + if (found) + idle_hook_func = pxe_idle_poll; +} + +void pxe_idle_cleanup(void) +{ + idle_hook_func = NULL; +} diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 37ba0310..5a40205c 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -1473,7 +1473,10 @@ static int pxe_fs_init(struct fs_info *fs) /* Network-specific initialization */ network_init(); - + + /* Initialize network-card-specific idle handling */ + pxe_idle_init(); + return 0; } @@ -1495,6 +1498,8 @@ void unload_pxe(void) int err; int int_addr; static __lowmem struct s_PXENV_UNLOAD_STACK unload_stack; + + pxe_idle_cleanup(); if (KeepPXE) { /* diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 224b8a26..07a6b6e7 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -219,5 +219,8 @@ void parse_dhcp_options(void *, int, int); int dns_mangle(char **, const char *); uint32_t dns_resolv(const char *); +/* idle.c */ +void pxe_idle_init(void); +void pxe_idle_cleanup(void); #endif /* pxe.h */ diff --git a/core/idle.inc b/core/idle.inc index f563def7..966b6e26 100644 --- a/core/idle.inc +++ b/core/idle.inc @@ -23,7 +23,7 @@ reset_idle: ret do_idle: - push ax + push eax push ds push es mov ax,cs @@ -58,18 +58,24 @@ do_idle: sub ax,[IdleTimer] cmp ax,TICKS_TO_IDLE jb .done - call [IdleHook] + + mov eax,[idle_hook_func] + and eax,eax + jz .no_idle_hook + pm_call eax +.no_idle_hook: cmp word [NoHalt],0 jne .done hlt .done: pop es pop ds - pop ax + pop eax .ret: ret section .data16 -IdleHook dw do_idle.ret + global idle_hook_func +idle_hook_func dd 0 NoHalt dw 0 hlt_err db 'ERROR: idle with IF=0', CR, LF, 0 diff --git a/core/include/core.h b/core/include/core.h index 004c729f..c13aa16f 100644 --- a/core/include/core.h +++ b/core/include/core.h @@ -17,10 +17,12 @@ extern void getlinsec(void); /* getc.inc */ extern void core_open(void); +/* idle.inc */ +extern void (*idle_hook_func)(void); + /* hello.c */ extern void myputs(const char*); - void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); int __cdecl core_cfarcall(uint32_t, const void *, uint32_t); diff --git a/core/pxeidle.inc b/core/pxeidle.inc deleted file mode 100644 index 4cfdc1b0..00000000 --- a/core/pxeidle.inc +++ /dev/null @@ -1,132 +0,0 @@ -;; -*- fundamental -*- --------------------------------------------------- -;; -;; Copyright 2008 H. Peter Anvin - All Rights Reserved -;; Copyright 2009 Intel Corporation; author: H. Peter Anvin -;; -;; 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, Inc., 51 Franklin St, Fifth Floor, -;; Boston MA 02110-1301, USA; either version 2 of the License, or -;; (at your option) any later version; incorporated herein by reference. -;; -;; ----------------------------------------------------------------------- - -;; -;; pxeidle.inc -;; -;; -;; Query for the NIC type, and detect certain special cases. -;; - - section .bss16 - pxe_udp_read_pkt: -.status: resw 1 ; Status -.sip: resd 1 ; Source IP -.dip: resd 1 ; Destination (our) IP -.rport: resw 1 ; Remote port -.lport: resw 1 ; Local port -.buffersize: resw 1 ; Max packet size -.buffer: resw 2 ; seg:off of buffer - - - section .text16 -;; -;; Initializes the idle mechanism based on the device type -;; -;; Assumes CS == DS == ES -;; -pxe_detect_nic_type: - pushad - - mov di,pxenv_get_nic_type - mov bx,PXENV_UNDI_GET_NIC_TYPE - call pxenv - jc .done - cmp word [di],0 - jne .done - cmp byte [di+2],2 ; PCI_NIC - jne .done ; No list for non-PCI nics - - mov cx,pxe_idle_pci_list.len - mov si,pxe_idle_pci_list -.look_for_id: - lodsd - cmp eax,[di+3] ; VID:DID - je .found_device - loop .look_for_id -.done: - popad - ret - -.found_device: - mov word [IdleHook],check_for_arp - jmp .done - -;; -;; List of devices for which we want to actually issue idle calls. -;; - section .data16 - alignz 4 -pxe_idle_pci_list: -; -; Older Broadcom NICs; these need idle calls to avoid FIFO stalls. -; - dw 0x14e4, 0x1659 ; BCM5721 - dw 0x14e4, 0x165a ; BCM5722 - dw 0x14e4, 0x165b ; BCM5723 - dw 0x14e4, 0x1668 ; BCM5714 - dw 0x14e4, 0x1669 ; BCM5714S - dw 0x14e4, 0x166a ; BCM5780 - dw 0x14e4, 0x166b ; BCM5780S - dw 0x14e4, 0x1673 ; BCM5755M - dw 0x14e4, 0x1674 ; BCM5756ME - dw 0x14e4, 0x1678 ; BCM5715 - dw 0x14e4, 0x1679 ; BCM5715S - dw 0x14e4, 0x167b ; BCM5755 -; -.len equ ($-pxe_idle_pci_list) >> 2 - - section .bss16 -pxenv_get_nic_type: -.status: resw 1 -.nic_type: resb 1 -.vid: resw 1 -.did: resw 1 -.base_class: resb 1 -.sub_class: resb 1 -.prog_intf: resb 1 -.rev: resb 1 -.busdevfunc: resw 1 -.svid: resw 1 -.sdid: resw 1 - - section .text16 -; -; Call the receive loop while idle. This is done mostly so we can respond to -; ARP messages, but perhaps in the future this can be used to do network -; console. -; -; hpa sez: people using automatic control on the serial port get very -; unhappy if we poll for ARP too often (the PXE stack is pretty slow, -; typically.) Therefore, only poll if at least 4 BIOS timer ticks have -; passed since the last poll, and reset this when a character is -; received (call reset_idle). -; -; Note: we only do this if pxe_detect_nic_type has set the IdleHook -; to point to this routine. -; -check_for_arp: - pushad - mov di,packet_buf - mov [pxe_udp_read_pkt.buffer],di - mov [pxe_udp_read_pkt.buffer+2],ds - mov word [pxe_udp_read_pkt.buffersize],packet_buf_size - mov eax,[MyIP] - mov [pxe_udp_read_pkt.dip],eax - mov word [pxe_udp_read_pkt.lport],htons(9) ; discard port - mov di,pxe_udp_read_pkt - mov bx,PXENV_UDP_READ - call pxenv - ; Ignore result... - popad - ret diff --git a/core/pxelinux.asm b/core/pxelinux.asm index e8c81301..876d06f2 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -178,9 +178,8 @@ _start1: %include "cpuinit.inc" ; -; Detect NIC type and initialize the idle mechanism +; Initialize the idle mechanism ; - call pxe_detect_nic_type call reset_idle ; @@ -368,7 +367,6 @@ writestr_early equ writestr %include "writehex.inc" ; Hexadecimal output %include "rawcon.inc" ; Console I/O w/o using the console functions %include "dnsresolv.inc" ; DNS resolver -%include "pxeidle.inc" ; PXE-specific idle mechanism ; ----------------------------------------------------------------------------- ; Begin data section -- cgit v1.2.1 From 4ef0e7caa56701bd453baa4e4e6542ee4523cf09 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 1 Sep 2009 17:08:52 -0700 Subject: core: pxe: remove vestigial dnsresolv.inc Remove dnsresolv.inc, which was already unused except for a couple of buffer declarations. Move those buffers to regular C variables. Signed-off-by: H. Peter Anvin --- core/dnsresolv.inc | 27 --------------------------- core/fs/pxe/dhcp_option.c | 3 +++ core/fs/pxe/dnsresolv.c | 10 ++++++---- core/fs/pxe/pxe.h | 3 +-- core/pxelinux.asm | 1 - 5 files changed, 10 insertions(+), 34 deletions(-) delete mode 100644 core/dnsresolv.inc diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc deleted file mode 100644 index 6d6c67a2..00000000 --- a/core/dnsresolv.inc +++ /dev/null @@ -1,27 +0,0 @@ -; -*- fundamental -*- -; ----------------------------------------------------------------------- -; -; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved -; -; 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, Inc., 53 Temple Place Ste 330, -; Bostom MA 02111-1307, USA; either version 2 of the License, or -; (at your option) any later version; incorporated herein by reference. -; -; ----------------------------------------------------------------------- - -; -; dnsresolv.inc -; -DNS_MAX_PACKET equ 512 ;Defined by protocol - - section .bss16 - global LocalDomain - global DNSSendBuf, DNSRecvBuf - alignb 2 -DNSSendBuf resb DNS_MAX_PACKET -DNSRecvBuf resb DNS_MAX_PACKET -LocalDomain resb 256 ; Max possible length - - section .text16 \ No newline at end of file diff --git a/core/fs/pxe/dhcp_option.c b/core/fs/pxe/dhcp_option.c index ebe8eb49..7935f8ba 100644 --- a/core/fs/pxe/dhcp_option.c +++ b/core/fs/pxe/dhcp_option.c @@ -4,9 +4,12 @@ #include #include "pxe.h" +char LocalDomain[256]; + int over_load; uint8_t uuid_type; char uuid[17]; + void parse_dhcp_options(void *, int, int); static void subnet_mask(void *data, int opt_len) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index dbabbb62..d019514f 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -171,6 +171,8 @@ static char *dns_skiplabel(char *label) */ uint32_t dns_resolv(const char *name) { + static char __lowmem DNSSendBuf[PKTBUF_SIZE]; + static char __lowmem DNSRecvBuf[PKTBUF_SIZE]; char *p; int err; int dots; @@ -225,8 +227,8 @@ uint32_t dns_resolv(const char *name) udp_write.src_port = DNS_LOCAL_PORT; udp_write.dst_port = DNS_PORT; udp_write.buffer_size = p - DNSSendBuf; - udp_write.buffer.offs = OFFS_WRT(DNSSendBuf, 0); - udp_write.buffer.seg = 0; + udp_write.buffer.offs = OFFS(DNSSendBuf); + udp_write.buffer.seg = SEG(DNSSendBuf); err = pxe_call(PXENV_UDP_WRITE, &udp_write); if (err || udp_write.status != 0) continue; @@ -239,8 +241,8 @@ uint32_t dns_resolv(const char *name) udp_read.s_port = DNS_PORT; udp_read.d_port = DNS_LOCAL_PORT; udp_read.buffer_size = DNS_MAX_PACKET; - udp_read.buffer.offs = OFFS_WRT(DNSRecvBuf, 0); - udp_read.buffer.seg = 0; + udp_read.buffer.offs = OFFS(DNSRecvBuf); + udp_read.buffer.seg = SEG(DNSRecvBuf); err = pxe_call(PXENV_UDP_READ, &udp_read); if (err || udp_read.status) continue; diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h index 07a6b6e7..8a2b190c 100644 --- a/core/fs/pxe/pxe.h +++ b/core/fs/pxe/pxe.h @@ -20,6 +20,7 @@ #define PXE_H #include +#include "fs.h" /* For MAX_OPEN, should go away */ /* * Some basic defines... @@ -184,8 +185,6 @@ extern char IPOption[]; extern char dot_quad_buf[]; extern uint32_t dns_server[]; -extern char DNSSendBuf[]; -extern char DNSRecvBuf[]; extern uint16_t real_base_mem; extern uint16_t APIVer; diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 876d06f2..5512e843 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -366,7 +366,6 @@ pxe_int1a: writestr_early equ writestr %include "writehex.inc" ; Hexadecimal output %include "rawcon.inc" ; Console I/O w/o using the console functions -%include "dnsresolv.inc" ; DNS resolver ; ----------------------------------------------------------------------------- ; Begin data section -- cgit v1.2.1 From 25fb8ebda235fad14d64949180405877a3a394df Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 1 Sep 2009 17:13:41 -0700 Subject: core: pxe: use FAR_PTR() macro where appropriate Use the FAR_PTR() macro to convert a pointer in lowmem to SEG:OFFS format as unit. Signed-off-by: H. Peter Anvin --- core/fs/pxe/dnsresolv.c | 6 ++---- core/fs/pxe/idle.c | 3 +-- core/fs/pxe/pxe.c | 9 +++------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c index d019514f..98bc960e 100644 --- a/core/fs/pxe/dnsresolv.c +++ b/core/fs/pxe/dnsresolv.c @@ -227,8 +227,7 @@ uint32_t dns_resolv(const char *name) udp_write.src_port = DNS_LOCAL_PORT; udp_write.dst_port = DNS_PORT; udp_write.buffer_size = p - DNSSendBuf; - udp_write.buffer.offs = OFFS(DNSSendBuf); - udp_write.buffer.seg = SEG(DNSSendBuf); + udp_write.buffer = FAR_PTR(DNSSendBuf); err = pxe_call(PXENV_UDP_WRITE, &udp_write); if (err || udp_write.status != 0) continue; @@ -241,8 +240,7 @@ uint32_t dns_resolv(const char *name) udp_read.s_port = DNS_PORT; udp_read.d_port = DNS_LOCAL_PORT; udp_read.buffer_size = DNS_MAX_PACKET; - udp_read.buffer.offs = OFFS(DNSRecvBuf); - udp_read.buffer.seg = SEG(DNSRecvBuf); + udp_read.buffer = FAR_PTR(DNSRecvBuf); err = pxe_call(PXENV_UDP_READ, &udp_read); if (err || udp_read.status) continue; diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c index 5b51d608..73379fe6 100644 --- a/core/fs/pxe/idle.c +++ b/core/fs/pxe/idle.c @@ -31,8 +31,7 @@ static void pxe_idle_poll(void) read_buf.s_port = 0; /* Any source port */ read_buf.d_port = htons(9); /* Discard port (not used...) */ read_buf.buffer_size = sizeof junk_pkt; - read_buf.buffer.offs = OFFS(junk_pkt); - read_buf.buffer.seg = SEG(junk_pkt); + read_buf.buffer = FAR_PTR(junk_pkt); pxe_call(PXENV_UDP_READ, &read_buf); } diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 5a40205c..f3c9bf30 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -289,8 +289,7 @@ static void ack_packet(struct open_file_t *file, uint16_t ack_num) udp_write.dst_port = file->tftp_remoteport; udp_write.ip = file->tftp_remoteip; udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0; - udp_write.buffer.offs = OFFS(ack_packet_buf); - udp_write.buffer.seg = SEG(ack_packet_buf); + udp_write.buffer = FAR_PTR(ack_packet_buf); udp_write.buffer_size = 4; err = pxe_call(PXENV_UDP_WRITE, &udp_write); @@ -316,8 +315,7 @@ static int pxe_get_cached_info(int type) get_cached_info.Status = 0; get_cached_info.PacketType = type; get_cached_info.BufferSize = 8192; - get_cached_info.Buffer.offs = OFFS_WRT(trackbuf, 0); - get_cached_info.Buffer.seg = 0; + get_cached_info.Buffer = FAR_PTR(trackbuf); err = pxe_call(PXENV_GET_CACHED_INFO, &get_cached_info); if (err) { printf("PXE API call failed, error %04x\n", err); @@ -966,8 +964,7 @@ err_reply: strcat(p, "TFTP_protocol error"); udp_write.dst_port = open_file->tftp_remoteport; - udp_write.buffer.offs = OFFS(tftp_proto_err); - udp_write.buffer.seg = SEG(tftp_proto_err); + udp_write.buffer = FAR_PTR(tftp_proto_err); udp_write.buffer_size = 24; pxe_call(PXENV_UDP_WRITE, &udp_write); printf("TFTP server sent an incomprehesible reply\n"); -- cgit v1.2.1