summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-09-02 11:27:11 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-09-02 11:27:11 -0700
commit8a33d6742b1c76c0cf86fe0154e761ff2353dc39 (patch)
tree1b300a29cbd983267163e9158ab8cee3192ef321
parentbb1023d5da5914999484164205f383412bf3ca5e (diff)
parent25fb8ebda235fad14d64949180405877a3a394df (diff)
downloadsyslinux-8a33d6742b1c76c0cf86fe0154e761ff2353dc39.tar.gz
Merge branch 'fsc' into elflink
Resolved Conflicts: MCONFIG.embedded com32/MCONFIG com32/lib/Makefile core/Makefile core/extern.inc core/extlinux.asm core/isolinux.asm core/syslinux.ld Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--MCONFIG.embedded1
-rw-r--r--NEWS6
-rw-r--r--com32/MCONFIG3
-rw-r--r--com32/cmenu/libmenu/com32io.h2
-rw-r--r--com32/gplinclude/disk/common.h33
-rw-r--r--com32/gplinclude/disk/errno_disk.h50
-rw-r--r--com32/gplinclude/disk/error.h13
-rw-r--r--com32/gplinclude/disk/geom.h325
-rw-r--r--com32/gplinclude/disk/msdos.h19
-rw-r--r--com32/gplinclude/disk/partition.h37
-rw-r--r--com32/gplinclude/disk/read.h18
-rw-r--r--com32/gplinclude/disk/swsusp.h19
-rw-r--r--com32/gplinclude/disk/util.h22
-rw-r--r--com32/gplinclude/disk/write.h28
-rw-r--r--com32/gplinclude/dmi/dmi.h36
-rw-r--r--com32/gplinclude/dmi/dmi_base_board.h33
-rw-r--r--com32/gplinclude/dmi/dmi_cache.h47
-rw-r--r--com32/gplinclude/dmi/dmi_memory.h16
-rw-r--r--com32/gplinclude/dmi/dmi_system.h19
-rw-r--r--com32/gplinclude/memory.h37
-rw-r--r--com32/gpllib/Makefile5
-rw-r--r--com32/gpllib/disk/ata.c61
-rw-r--r--com32/gpllib/disk/errno_disk.c12
-rw-r--r--com32/gpllib/disk/error.c23
-rw-r--r--com32/gpllib/disk/geom.c272
-rw-r--r--com32/gpllib/disk/labels.c254
-rw-r--r--com32/gpllib/disk/msdos.c167
-rw-r--r--com32/gpllib/disk/read.c133
-rw-r--r--com32/gpllib/disk/swsusp.c27
-rw-r--r--com32/gpllib/disk/util.c44
-rw-r--r--com32/gpllib/disk/write.c125
-rw-r--r--com32/gpllib/dmi/dmi.c521
-rw-r--r--com32/gpllib/dmi/dmi_cache.c135
-rw-r--r--com32/gpllib/dmi/dmi_memory.c92
-rw-r--r--com32/gpllib/memory.c216
-rw-r--r--com32/hdt/hdt-ata.c247
-rw-r--r--com32/hdt/hdt-ata.h50
-rw-r--r--com32/hdt/hdt-cli-disk.c222
-rw-r--r--com32/hdt/hdt-cli-dmi.c208
-rw-r--r--com32/hdt/hdt-cli-hdt.c30
-rw-r--r--com32/hdt/hdt-cli-kernel.c5
-rw-r--r--com32/hdt/hdt-cli-memory.c116
-rw-r--r--com32/hdt/hdt-cli-pci.c27
-rw-r--r--com32/hdt/hdt-cli.c45
-rw-r--r--com32/hdt/hdt-cli.h19
-rw-r--r--com32/hdt/hdt-common.c54
-rw-r--r--com32/hdt/hdt-common.h20
-rw-r--r--com32/hdt/hdt-menu-disk.c271
-rw-r--r--com32/hdt/hdt-menu-dmi.c141
-rw-r--r--com32/hdt/hdt-menu-kernel.c13
-rw-r--r--com32/hdt/hdt-menu-memory.c277
-rw-r--r--com32/hdt/hdt-menu-pci.c15
-rw-r--r--com32/hdt/hdt-menu-vpd.c70
-rw-r--r--com32/hdt/hdt-menu.c8
-rw-r--r--com32/hdt/hdt-menu.h4
-rw-r--r--com32/hdt/hdt-util.c71
-rw-r--r--com32/hdt/hdt-util.h33
-rw-r--r--com32/hdt/hdt.c3
-rw-r--r--com32/hdt/hdt.h2
-rw-r--r--com32/hdt/lib-ansi.c7
-rw-r--r--com32/hdt/lib-ansi.h1
-rw-r--r--com32/include/dirent.h18
-rw-r--r--com32/include/netinet/in.h48
-rw-r--r--com32/include/png.h2906
-rw-r--r--com32/include/pngconf.h121
-rw-r--r--com32/include/string.h1
-rw-r--r--com32/include/sys/dirent.h30
-rw-r--r--com32/include/sys/pci.h12
-rw-r--r--com32/include/syslinux/pxe.h487
-rw-r--r--com32/include/syslinux/pxe_api.h566
-rw-r--r--com32/lib/MCONFIG5
-rw-r--r--com32/lib/Makefile38
-rw-r--r--com32/lib/closedir.c16
-rw-r--r--com32/lib/opendir.c19
-rw-r--r--com32/lib/pci/scan.c299
-rw-r--r--com32/lib/readdir.c42
-rw-r--r--com32/lib/strpcpy.c20
-rw-r--r--com32/lib/zlib/example.c566
-rw-r--r--com32/lib/zlib/gzio.c1017
-rw-r--r--com32/lib/zlib/minigzip.c322
-rw-r--r--com32/mboot/mboot.c2
-rw-r--r--com32/menu/menumain.c3
-rw-r--r--com32/modules/Makefile4
-rw-r--r--com32/modules/dir.c35
-rw-r--r--com32/modules/disk.c63
-rw-r--r--com32/modules/host.c42
-rw-r--r--com32/rosh/rosh.c18
-rw-r--r--com32/rosh/rosh.h2
-rw-r--r--core/Makefile21
-rw-r--r--core/bios.inc1
-rw-r--r--core/bootsect.inc2
-rw-r--r--core/cache.c155
-rw-r--r--core/call16.c2
-rw-r--r--core/comboot.inc58
-rw-r--r--core/config.inc6
-rw-r--r--core/conio.inc4
-rw-r--r--core/dir.c44
-rw-r--r--core/diskfs.inc182
-rw-r--r--core/diskio.c352
-rw-r--r--core/diskstart.inc21
-rw-r--r--core/dnsresolv.inc389
-rw-r--r--core/ext2_fs.inc183
-rw-r--r--core/extern.inc11
-rw-r--r--core/extlinux.asm902
-rw-r--r--core/fs.c190
-rw-r--r--core/fs/ext2/ext2.c736
-rw-r--r--core/fs/ext2/ext2_fs.h252
-rw-r--r--core/fs/fat/fat.c895
-rw-r--r--core/fs/fat/fat_fs.h114
-rw-r--r--core/fs/iso9660/iso9660.c536
-rw-r--r--core/fs/iso9660/iso9660_fs.h21
-rw-r--r--core/fs/lib/mangle.c47
-rw-r--r--core/fs/pxe/dhcp_option.c272
-rw-r--r--core/fs/pxe/dnsresolv.c341
-rw-r--r--core/fs/pxe/idle.c109
-rw-r--r--core/fs/pxe/pxe.c1549
-rw-r--r--core/fs/pxe/pxe.h225
-rw-r--r--core/getc.inc13
-rw-r--r--core/hello.c7
-rw-r--r--core/idle.inc14
-rw-r--r--core/include/cache.h25
-rw-r--r--core/include/core.h29
-rw-r--r--core/include/disk.h40
-rw-r--r--core/include/fs.h100
-rw-r--r--core/init.inc13
-rw-r--r--core/isolinux.asm478
-rw-r--r--core/kaboom.c16
-rw-r--r--core/layout.inc5
-rw-r--r--core/ldlinux.asm1389
-rw-r--r--core/loadhigh.inc2
-rw-r--r--core/parsecmd.inc1
-rw-r--r--core/parseconfig.inc16
-rw-r--r--core/pxeidle.inc122
-rw-r--r--core/pxelinux.asm2418
-rw-r--r--core/runkernel.inc8
-rw-r--r--core/syslinux.ld6
-rw-r--r--core/ui.inc10
-rw-r--r--doc/memdisk.txt6
-rw-r--r--extlinux/main.c9
-rw-r--r--memdisk/Makefile1
-rw-r--r--memdisk/memdisk_chs.asm1
-rw-r--r--memdisk/memdisk_edd.asm1
-rw-r--r--memdisk/setup.c36
143 files changed, 12829 insertions, 11069 deletions
diff --git a/MCONFIG.embedded b/MCONFIG.embedded
index b74d8da7..bb718963 100644
--- a/MCONFIG.embedded
+++ b/MCONFIG.embedded
@@ -25,6 +25,7 @@ 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/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/com32/MCONFIG b/com32/MCONFIG
index 5d2e747a..aa55741e 100644
--- a/com32/MCONFIG
+++ b/com32/MCONFIG
@@ -26,6 +26,9 @@ GCCOPT += -march=i386 -Os -fomit-frame-pointer -mregparm=3 -DREGPARM=3
GCCOPT += $(call gcc_ok,-fno-exceptions,)
GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,)
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/cmenu/libmenu/com32io.h b/com32/cmenu/libmenu/com32io.h
index ba955e99..cdaf0a84 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)
diff --git a/com32/gplinclude/disk/common.h b/com32/gplinclude/disk/common.h
new file mode 100644
index 00000000..c6df2f4e
--- /dev/null
+++ b/com32/gplinclude/disk/common.h
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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_
+
+#include <stdint.h>
+
+#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/errno_disk.h b/com32/gplinclude/disk/errno_disk.h
new file mode 100644
index 00000000..60b511fc
--- /dev/null
+++ b/com32/gplinclude/disk/errno_disk.h
@@ -0,0 +1,50 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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;
+
+/* 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 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/error.h b/com32/gplinclude/disk/error.h
new file mode 100644
index 00000000..f9e319c4
--- /dev/null
+++ b/com32/gplinclude/disk/error.h
@@ -0,0 +1,13 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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(void*);
+#endif /* _UTIL_H_ */
diff --git a/com32/gplinclude/disk/geom.h b/com32/gplinclude/disk/geom.h
new file mode 100644
index 00000000..0d3eed57
--- /dev/null
+++ b/com32/gplinclude/disk/geom.h
@@ -0,0 +1,325 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <Matt_Domsch@dell.com>
+ *
+ * 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_
+
+#include <stdint.h>
+
+/**
+ * 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 edd_device_parameters {
+ 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 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));
+
+/*
+ * 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)
+ * 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)
+{
+ /* 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,
+ 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/msdos.h b/com32/gplinclude/disk/msdos.h
new file mode 100644
index 00000000..405b9b99
--- /dev/null
+++ b/com32/gplinclude/disk/msdos.h
@@ -0,0 +1,19 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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_
+
+#include <disk/geom.h>
+#include <disk/partition.h>
+
+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/gplinclude/disk/partition.h b/com32/gplinclude/disk/partition.h
new file mode 100644
index 00000000..be6bfaab
--- /dev/null
+++ b/com32/gplinclude/disk/partition.h
@@ -0,0 +1,37 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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_
+
+#include <stdint.h>
+
+#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/read.h b/com32/gplinclude/disk/read.h
new file mode 100644
index 00000000..43762a68
--- /dev/null
+++ b/com32/gplinclude/disk/read.h
@@ -0,0 +1,18 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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_
+
+#include <disk/geom.h>
+
+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/swsusp.h b/com32/gplinclude/disk/swsusp.h
new file mode 100644
index 00000000..1d77c878
--- /dev/null
+++ b/com32/gplinclude/disk/swsusp.h
@@ -0,0 +1,19 @@
+#ifndef _SWSUSP_H_
+#define _SWSUSP_H_
+
+#include <disk/geom.h>
+#include <disk/common.h>
+#include <disk/partition.h>
+
+#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*);
+#endif /* _SWSUSP_H */
diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h
new file mode 100644
index 00000000..df2eadda
--- /dev/null
+++ b/com32/gplinclude/disk/util.h
@@ -0,0 +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
+ *
+ * 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_
+
+#include <com32.h>
+
+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..faa80c7d
--- /dev/null
+++ b/com32/gplinclude/disk/write.h
@@ -0,0 +1,28 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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_
+
+#include <disk/geom.h>
+
+int write_sectors(const struct driveinfo*, const unsigned int,
+ const void *, const int);
+int write_verify_sector(struct driveinfo* drive_info,
+ const unsigned int,
+ const void *);
+int write_verify_sectors(struct driveinfo*,
+ const unsigned int,
+ const void *, const int);
+#endif
diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h
index 71372f3e..def0a8ea 100644
--- a/com32/gplinclude/dmi/dmi.h
+++ b/com32/gplinclude/dmi/dmi.h
@@ -14,6 +14,9 @@
#define DMI_H
#include <inttypes.h>
#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
@@ -34,6 +37,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);
@@ -55,16 +59,28 @@ struct dmi_header {
};
typedef struct {
- s_bios bios;
- s_system system;
- s_base_board base_board;
- s_chassis chassis;
- s_processor processor;
- s_battery battery;
- s_memory memory[MAX_DMI_MEMORY_ITEMS];
- s_ipmi ipmi;
- int memory_count;
- dmi_table dmitable;
+ s_bios bios;
+ s_system system;
+ s_base_board base_board;
+ 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;
+ s_cache cache[MAX_DMI_CACHE_ITEMS];
+ int memory_module_count;
+ int memory_count;
+ 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/gplinclude/dmi/dmi_base_board.h b/com32/gplinclude/dmi/dmi_base_board.h
index 9fe35440..ff4dd8a9 100644
--- a/com32/gplinclude/dmi/dmi_base_board.h
+++ b/com32/gplinclude/dmi/dmi_base_board.h
@@ -30,24 +30,29 @@ extern const char *base_board_features_strings[];
/* this struct have BASE_BOARD_NB_ELEMENTS */
/* each bool is associated to the relevant message above */
typedef struct {
- bool hosting;
- bool board_needs_daughter;
- bool removable;
- bool replaceable;
- bool hot_swappable;
+ bool hosting;
+ bool board_needs_daughter;
+ bool removable;
+ bool replaceable;
+ bool hot_swappable;
} __attribute__ ((__packed__)) s_base_board_features;
typedef struct {
- char manufacturer[BASE_BOARD_MANUFACTURER_SIZE];
- char product_name[BASE_BOARD_PRODUCT_NAME_SIZE];
- char version[BASE_BOARD_VERSION_SIZE];
- char serial[BASE_BOARD_SERIAL_SIZE];
- char asset_tag[BASE_BOARD_ASSET_TAG_SIZE];
- char location[BASE_BOARD_LOCATION_SIZE];
- char type[BASE_BOARD_TYPE_SIZE];
- s_base_board_features features;
+ char manufacturer[BASE_BOARD_MANUFACTURER_SIZE];
+ char product_name[BASE_BOARD_PRODUCT_NAME_SIZE];
+ char version[BASE_BOARD_VERSION_SIZE];
+ char serial[BASE_BOARD_SERIAL_SIZE];
+ char asset_tag[BASE_BOARD_ASSET_TAG_SIZE];
+ char location[BASE_BOARD_LOCATION_SIZE];
+ 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;
+ bool filled;
+ struct {
+ char type[16];
+ uint8_t status;
+ char description[10];
+ } devices_information[10];
} s_base_board;
#endif
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 <alan@redhat.com>
+ * (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
+ *
+ * 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 <stdint.h>
+
+#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/gplinclude/dmi/dmi_memory.h b/com32/gplinclude/dmi/dmi_memory.h
index ed4eb6f4..f9c2b561 100644
--- a/com32/gplinclude/dmi/dmi_memory.h
+++ b/com32/gplinclude/dmi/dmi_memory.h
@@ -49,6 +49,17 @@ typedef struct {
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/gplinclude/dmi/dmi_system.h b/com32/gplinclude/dmi/dmi_system.h
index 9c313ebb..28a562de 100644
--- a/com32/gplinclude/dmi/dmi_system.h
+++ b/com32/gplinclude/dmi/dmi_system.h
@@ -22,6 +22,9 @@
#define SYSTEM_SKU_NUMBER_SIZE 32
#define SYSTEM_FAMILY_SIZE 32
+#define SYSTEM_BOOT_STATUS_SIZE 50
+#define SYSTEM_CONFIGURATION_OPTIONS_SIZE 50
+
typedef struct {
char manufacturer[SYSTEM_MANUFACTURER_SIZE];
char product_name[SYSTEM_PRODUCT_NAME_SIZE];
@@ -32,7 +35,19 @@ typedef struct {
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;
+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/gplinclude/memory.h b/com32/gplinclude/memory.h
new file mode 100644
index 00000000..c9f386d4
--- /dev/null
+++ b/com32/gplinclude/memory.h
@@ -0,0 +1,37 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdint.h>
+
+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);
+int detect_memory_e801(int*, int*);
+int detect_memory_88(int*);
+#endif
diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile
index 8e47d93f..fa866dba 100644
--- a/com32/gpllib/Makefile
+++ b/com32/gpllib/Makefile
@@ -8,9 +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 cpuid.o vpd/vpd.o
+GPLDIRS := . disk dmi vpd
+LIBOBJS := $(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
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..d74dda8f
--- /dev/null
+++ b/com32/gpllib/disk/ata.c
@@ -0,0 +1,61 @@
+#include <inttypes.h>
+
+/**
+ * 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/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 <disk/errno_disk.h>
+
+int errno_disk;
diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c
new file mode 100644
index 00000000..1853092b
--- /dev/null
+++ b/com32/gpllib/disk/error.c
@@ -0,0 +1,23 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <disk/errno_disk.h>
+
+/**
+ * get_error - decode a disk error status
+ * @buffer_ptr: Preallocated buffer
+ *
+ * Fill @buffer_ptr with the last errno_disk
+ **/
+void get_error(const char* s)
+{
+ fprintf(stderr, "%s: error %d\n", s, errno_disk);
+}
diff --git a/com32/gpllib/disk/geom.c b/com32/gpllib/disk/geom.c
new file mode 100644
index 00000000..2305ed16
--- /dev/null
+++ b/com32/gpllib/disk/geom.c
@@ -0,0 +1,272 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <com32.h>
+#include <string.h>
+#include <stdio.h>
+#include <disk/geom.h>
+
+#include <stdio.h>
+
+/**
+ * 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;
+
+ /* 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);
+ }
+}
+
+/**
+ * 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 int detect_extensions(struct driveinfo* drive_info)
+{
+ com32sys_t getebios, ebios;
+
+ memset(&getebios, 0, sizeof getebios);
+ memset(&ebios, 0, sizeof ebios);
+
+ getebios.eflags.b[0] = 0x3; /* CF set */
+ getebios.ebx.w[0] = 0x55aa;
+ getebios.edx.b[0] = drive_info->disk;
+ getebios.eax.b[1] = 0x41;
+
+ __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];
+ return 0;
+ } else
+ return -1; /* Drive does not exist? */
+}
+
+/**
+ * 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 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;
+ inreg.eax.b[1] = 0x48;
+
+ __intcall(0x13, &inreg, &outreg);
+
+ /* CF set on error */
+ if ( outreg.eflags.l & EFLAGS_CF )
+ return outreg.eax.b[1];
+
+ memcpy(&drive_info->edd_params, dp, sizeof drive_info->edd_params);
+
+ 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 getparm);
+ memset(&parm, 0, sizeof parm);
+
+ /* 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);
+
+ /* CF set on error */
+ if ( parm.eflags.l & EFLAGS_CF )
+ return parm.eax.b[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->legacy_type = parm.ebx.b[0];
+
+ /* 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->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->legacy_max_cylinder = parm.ecx.b[1] +
+ ((parm.ecx.b[0] & 0xc0) << 2);
+
+ if ( drive_info->legacy_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)
+{
+ int return_code;
+
+ if (detect_extensions(drive_info))
+ return -1;
+
+ 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 return_code;
+}
diff --git a/com32/gpllib/disk/labels.c b/com32/gpllib/disk/labels.c
new file mode 100644
index 00000000..7efe1ad1
--- /dev/null
+++ b/com32/gpllib/disk/labels.c
@@ -0,0 +1,254 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+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;
+ default: strncpy(buffer, "Unknown", buffer_size); break;
+ }
+}
diff --git a/com32/gpllib/disk/msdos.c b/com32/gpllib/disk/msdos.c
new file mode 100644
index 00000000..1d1ef4df
--- /dev/null
+++ b/com32/gpllib/disk/msdos.c
@@ -0,0 +1,167 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdlib.h>
+
+#include <disk/common.h>
+#include <disk/geom.h>
+#include <disk/msdos.h>
+#include <disk/partition.h>
+#include <disk/read.h>
+
+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(const char *ptab)
+{
+ return ( *(uint16_t *)(ptab + 0x1fe) == 0xaa55 );
+}
+
+/**
+ * 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 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,
+ 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 + ebr_offset, 1) == -1)
+ goto abort;
+
+ /* Check msdos magic signature */
+ if (!msdos_magic_present(ebr))
+ goto abort;
+
+ struct part_entry *ptab = (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET);
+
+ for (int i = 0; i < 4; i++) {
+ if (status == -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 = ebr_offset + ptab[i].start_lba;
+
+ /* Last EBR in the extended partition? */
+ if (!logical_partition_start)
+ continue;
+
+ /*
+ * 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;
+
+ nb_part_seen++;
+ callback(drive_info,
+ &ptab[i],
+ partition_offset + logical_partition_start,
+ nb_part_seen);
+ } else
+ status = process_extended_partition(drive_info,
+ partition_offset,
+ ptab[i].start_lba,
+ callback,
+ nb_part_seen);
+ }
+
+ free(ebr);
+ return 0;
+
+abort:
+ free(ebr);
+ return -1;
+}
+
+/**
+ * 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
+ **/
+static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab,
+ p_callback callback)
+{
+ int status = 0;
+
+ for (int i = 0; i < 4; i++) {
+ if (status == -1)
+ return -1;
+
+ if (ptab[i].start_sect > 0) {
+ if (is_extended_partition(&ptab[i])) {
+ callback(drive_info,
+ &ptab[i],
+ ptab[i].start_lba,
+ i+1);
+ status = process_extended_partition(drive_info, ptab[i].start_lba, 0, callback, 4);
+ } else
+ callback(drive_info,
+ &ptab[i],
+ ptab[i].start_lba,
+ i+1);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * parse_partition_table - execute a callback for each partition entry
+ * @d: driveinfo struct describing the drive
+ * @callback: Callback to execute
+ *
+ * The signature of the callback should be the following:
+ *
+ * void callback(struct driveinfo *drive_info,
+ * struct part_entry *ptab,
+ * int offset_root,
+ * int nb_part_seen)
+ **/
+int parse_partition_table(struct driveinfo *d, p_callback callback)
+{
+ char *mbr = malloc(SECTOR * sizeof(char));
+
+ if (read_mbr(d->disk, mbr) == -1)
+ 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);
+ return process_mbr(d, ptab, callback);
+ }
+}
diff --git a/com32/gpllib/disk/read.c b/com32/gpllib/disk/read.c
new file mode 100644
index 00000000..74840829
--- /dev/null
+++ b/com32/gpllib/disk/read.c
@@ -0,0 +1,133 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <com32.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/errno_disk.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <disk/util.h>
+#include <disk/common.h>
+
+/*
+ * TODO: implement file descriptors to cache metadata (geometry, ...)
+ */
+
+/**
+ * read_mbr - return a pointer to a malloced buffer containing the mbr
+ * @drive: Drive number
+ * @buf: Pre-allocated buffer for output
+ *
+ * Return the number of sectors read on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+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, 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
+ *
+ * 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.
+ **/
+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, 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
+ *
+ * Return the number of sectors read on success or -1 on failure.
+ * errno_disk contains the error number.
+ **/
+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;
+ char *bufp = data;
+
+ if (get_drive_parameters(drive_info) == -1)
+ return -1;
+
+ 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) { // XXX errno
+ /* We failed to get the geometry */
+ if (lba)
+ 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 -1;
+
+ 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, &outreg)) {
+ errno_disk = outreg.eax.b[1];
+ return -1; /* Give up */
+ }
+
+ memcpy(bufp, buf, sectors * SECTOR);
+
+ return sectors;
+}
diff --git a/com32/gpllib/disk/swsusp.c b/com32/gpllib/disk/swsusp.c
new file mode 100644
index 00000000..ac9724aa
--- /dev/null
+++ b/com32/gpllib/disk/swsusp.c
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/swsusp.h>
+#include <disk/read.h>
+#include <disk/geom.h>
+
+/**
+ * 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
+ **/
+int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab)
+{
+ struct swsusp_header header_p;
+ int offset;
+ int found;
+
+ /* Read first page of the swap device */
+ offset = ptab->start_lba;
+ 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;
+ }
+}
diff --git a/com32/gpllib/disk/util.c b/com32/gpllib/disk/util.c
new file mode 100644
index 00000000..6faac399
--- /dev/null
+++ b/com32/gpllib/disk/util.c
@@ -0,0 +1,44 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <com32.h>
+#include <stdlib.h>
+#include <string.h>
+#include <disk/geom.h>
+
+#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;
+}
diff --git a/com32/gpllib/disk/write.c b/com32/gpllib/disk/write.c
new file mode 100644
index 00000000..a236f37d
--- /dev/null
+++ b/com32/gpllib/disk/write.c
@@ -0,0 +1,125 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <com32.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <disk/common.h>
+#include <disk/errno_disk.h>
+#include <disk/read.h>
+#include <disk/util.h>
+#include <disk/write.h>
+
+/**
+ * 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)
+ *
+ * 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)
+{
+ com32sys_t inreg, outreg;
+ 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) { // XXX errno
+ /* 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);
+
+ // XXX errno
+ 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, &outreg)) {
+ errno_disk = outreg.eax.b[1];
+ return -1; /* Give up */
+ } else
+ return size;
+}
+
+/**
+ * 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 = malloc(SECTOR * size * sizeof(char));
+ int status;
+
+ if (write_sectors(drive_info, lba, data, size) == -1)
+ return -1; /* Write failure */
+
+ if (read_sectors(drive_info, rb, lba, size) == -1)
+ return -1; /* Readback failure */
+
+ status = memcmp(data, rb, SECTOR * size);
+ free(rb);
+ return status ? -1 : 0;
+}
diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c
index 70ddd455..ebf3c527 100644
--- a/com32/gpllib/dmi/dmi.c
+++ b/com32/gpllib/dmi/dmi.c
@@ -33,7 +33,153 @@
const char *out_of_spec = "<OUT OF SPEC>";
const char *bad_index = "<BAD INDEX>";
-void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi)
+/*
+ * 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; i<count && i<sizeof dmi->base_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)
+ */
+
+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.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)
+ */
+
+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)
+ */
+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[]={
+ "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) {
dmi->bios.runtime_size = code;
@@ -444,155 +590,232 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
break;
case 3: /* 3.3.4 Chassis Information */
// printf("Chassis Information\n");
- if (h->length < 0x09)
- break;
- dmi->chassis.filled = true;
- strcpy(dmi->chassis.manufacturer, dmi_string(h, data[0x04]));
- strcpy(dmi->chassis.type, dmi_chassis_type(data[0x05] & 0x7F));
- strcpy(dmi->chassis.lock, dmi_chassis_lock(data[0x05] >> 7));
- strcpy(dmi->chassis.version, dmi_string(h, data[0x06]));
- strcpy(dmi->chassis.serial, dmi_string(h, data[0x07]));
- strcpy(dmi->chassis.asset_tag, dmi_string(h, data[0x08]));
- if (h->length < 0x0D)
- break;
- strcpy(dmi->chassis.boot_up_state, dmi_chassis_state(data[0x09]));
- strcpy(dmi->chassis.power_supply_state, dmi_chassis_state(data[0x0A]));
- 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));
- if (h->length < 0x15)
- break;
- dmi->chassis.height = data[0x11];
- dmi->chassis.nb_power_cords = data[0x12];
- break;
-
- case 4: /* 3.3.5 Processor Information */
+ if(h->length<0x09) break;
+ dmi->chassis.filled=true;
+ strcpy(dmi->chassis.manufacturer,dmi_string(h,data[0x04]));
+ strcpy(dmi->chassis.type,dmi_chassis_type(data[0x05]&0x7F));
+ strcpy(dmi->chassis.lock,dmi_chassis_lock(data[0x05]>>7));
+ strcpy(dmi->chassis.version,dmi_string(h,data[0x06]));
+ strcpy(dmi->chassis.serial,dmi_string(h,data[0x07]));
+ strcpy(dmi->chassis.asset_tag,dmi_string(h,data[0x08]));
+ if(h->length<0x0D) break;
+ strcpy(dmi->chassis.boot_up_state,dmi_chassis_state(data[0x09]));
+ strcpy(dmi->chassis.power_supply_state,dmi_chassis_state(data[0x0A]));
+ 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",DWORD(data+0x0D));
+ if(h->length<0x15) break;
+ dmi->chassis.height=data[0x11];
+ dmi->chassis.nb_power_cords=data[0x12];
+ break;
+
+ case 4: /* 3.3.5 Processor Information */
// printf("Processor Information\n");
- if (h->length < 0x1A)
- break;
- dmi->processor.filled = true;
- strcpy(dmi->processor.socket_designation, dmi_string(h, data[0x04]));
- strcpy(dmi->processor.type, dmi_processor_type(data[0x05]));
- strcpy(dmi->processor.manufacturer, dmi_string(h, data[0x07]));
- strcpy(dmi->processor.family,
- dmi_processor_family(data[0x06], dmi->processor.manufacturer));
- dmi_processor_id(data[0x06], data + 8, dmi_string(h, data[0x10]), dmi);
- strcpy(dmi->processor.version, dmi_string(h, data[0x10]));
- dmi_processor_voltage(data[0x11], dmi);
- dmi->processor.external_clock = WORD(data + 0x12);
- dmi->processor.max_speed = WORD(data + 0x14);
- dmi->processor.current_speed = WORD(data + 0x16);
- if (data[0x18] & (1 << 6))
- strcpy(dmi->processor.status,
- dmi_processor_status(data[0x18] & 0x07));
- else
- sprintf(dmi->processor.status, "Unpopulated");
- sprintf(dmi->processor.upgrade, dmi_processor_upgrade(data[0x19]));
- if (h->length < 0x20)
- break;
- dmi_processor_cache(WORD(data + 0x1A), "L1", ver,
- dmi->processor.cache1);
- dmi_processor_cache(WORD(data + 0x1C), "L2", ver,
- dmi->processor.cache2);
- dmi_processor_cache(WORD(data + 0x1E), "L3", ver,
- dmi->processor.cache3);
- if (h->length < 0x23)
- break;
- strcpy(dmi->processor.serial, dmi_string(h, data[0x20]));
- 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 */
- if (h->length < 0x15)
- break;
- dmi->memory_count++;
- 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);
- dmi_memory_device_width(WORD(data + 0x08), mem->total_width);
- dmi_memory_device_width(WORD(data + 0x0A), mem->data_width);
- dmi_memory_device_size(WORD(data + 0x0C), mem->size);
- strcpy(mem->form_factor, dmi_memory_device_form_factor(data[0x0E]));
- dmi_memory_device_set(data[0x0F], mem->device_set);
- strcpy(mem->device_locator, dmi_string(h, data[0x10]));
- strcpy(mem->bank_locator, dmi_string(h, data[0x11]));
- strcpy(mem->type, dmi_memory_device_type(data[0x12]));
- dmi_memory_device_type_detail(WORD(data + 0x13), mem->type_detail);
- if (h->length < 0x17)
- break;
- dmi_memory_device_speed(WORD(data + 0x15), mem->speed);
- if (h->length < 0x1B)
- break;
- strcpy(mem->manufacturer, dmi_string(h, data[0x17]));
- strcpy(mem->serial, dmi_string(h, data[0x18]));
- strcpy(mem->asset_tag, dmi_string(h, data[0x19]));
- strcpy(mem->part_number, dmi_string(h, data[0x1A]));
- break;
- case 22: /* 3.3.23 Portable Battery */
- if (h->length < 0x10)
- break;
- dmi->battery.filled = true;
- strcpy(dmi->battery.location, dmi_string(h, data[0x04]));
- strcpy(dmi->battery.manufacturer, dmi_string(h, data[0x05]));
-
- if (data[0x06] || h->length < 0x1A)
- strcpy(dmi->battery.manufacture_date, dmi_string(h, data[0x06]));
-
- if (data[0x07] || h->length < 0x1A)
- strcpy(dmi->battery.serial, dmi_string(h, data[0x07]));
-
- strcpy(dmi->battery.name, dmi_string(h, data[0x08]));
-
- if (data[0x09] != 0x02 || h->length < 0x1A)
- strcpy(dmi->battery.chemistry, dmi_battery_chemistry(data[0x09]));
-
- if (h->length < 0x1A)
- dmi_battery_capacity(WORD(data + 0x0A), 1,
- dmi->battery.design_capacity);
- else
- dmi_battery_capacity(WORD(data + 0x0A), data[0x15],
- dmi->battery.design_capacity);
- dmi_battery_voltage(WORD(data + 0x0C), dmi->battery.design_voltage);
- strcpy(dmi->battery.sbds, dmi_string(h, data[0x0E]));
- dmi_battery_maximum_error(data[0x0F], dmi->battery.maximum_error);
- if (h->length < 0x1A)
- break;
- if (data[0x07] == 0)
- sprintf(dmi->battery.sbds_serial, "%04X", WORD(data + 0x10));
-
- if (data[0x06] == 0)
- sprintf(dmi->battery.sbds_manufacture_date, "%u-%02u-%02u",
- 1980 + (WORD(data + 0x12) >> 9),
- (WORD(data + 0x12) >> 5) & 0x0F, WORD(data + 0x12) & 0x1F);
- if (data[0x09] == 0x02)
- strcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14]));
-
- // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16));
- break;
- case 38: /* 3.3.39 IPMI Device Information */
- if (h->length < 0x10)
- break;
- dmi->ipmi.filled = true;
- snprintf(dmi->ipmi.interface_type, sizeof(dmi->ipmi.interface_type),
- "%s", dmi_ipmi_interface_type(data[0x04]));
- dmi->ipmi.major_specification_version = data[0x05] >> 4;
- dmi->ipmi.minor_specification_version = data[0x05] & 0x0F;
- dmi->ipmi.I2C_slave_address = data[0x06] >> 1;
- if (data[0x07] != 0xFF)
- dmi->ipmi.nv_address = data[0x07];
- else
- dmi->ipmi.nv_address = 0; /* Not Present */
- dmi_ipmi_base_address(data[0x04], data + 0x08, &dmi->ipmi);
- if (h->length < 0x12)
- break;
- if (data[0x11] != 0x00) {
- dmi->ipmi.irq = data[0x11];
- }
- break;
- }
+ if(h->length<0x1A) break;
+ dmi->processor.filled=true;
+ strcpy(dmi->processor.socket_designation,dmi_string(h, data[0x04]));
+ strcpy(dmi->processor.type,dmi_processor_type(data[0x05]));
+ strcpy(dmi->processor.manufacturer,dmi_string(h, data[0x07]));
+ strcpy(dmi->processor.family,dmi_processor_family(data[0x06],dmi->processor.manufacturer));
+ dmi_processor_id(data[0x06], data+8, dmi_string(h, data[0x10]), dmi);
+ strcpy(dmi->processor.version,dmi_string(h, data[0x10]));
+ dmi_processor_voltage(data[0x11],dmi);
+ dmi->processor.external_clock=WORD(data+0x12);
+ dmi->processor.max_speed=WORD(data+0x14);
+ dmi->processor.current_speed=WORD(data+0x16);
+ if(data[0x18]&(1<<6))
+ strcpy(dmi->processor.status,dmi_processor_status(data[0x18]&0x07));
+ else
+ sprintf(dmi->processor.status,"Unpopulated");
+ sprintf(dmi->processor.upgrade,dmi_processor_upgrade(data[0x19]));
+ if(h->length<0x20) break;
+ dmi_processor_cache(WORD(data+0x1A), "L1", ver,dmi->processor.cache1);
+ dmi_processor_cache(WORD(data+0x1C), "L2", ver,dmi->processor.cache2);
+ dmi_processor_cache(WORD(data+0x1E), "L3", ver,dmi->processor.cache3);
+ if(h->length<0x23) break;
+ strcpy(dmi->processor.serial,dmi_string(h, data[0x20]));
+ 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 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 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);
+ break;
+ 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);
+ dmi_memory_device_width(WORD(data + 0x08),mem->total_width);
+ dmi_memory_device_width(WORD(data + 0x0A),mem->data_width);
+ dmi_memory_device_size(WORD(data + 0x0C),mem->size);
+ strcpy(mem->form_factor,dmi_memory_device_form_factor(data[0x0E]));
+ dmi_memory_device_set(data[0x0F],mem->device_set);
+ strcpy(mem->device_locator,dmi_string(h, data[0x10]));
+ strcpy(mem->bank_locator,dmi_string(h, data[0x11]));
+ strcpy(mem->type,dmi_memory_device_type(data[0x12]));
+ dmi_memory_device_type_detail(WORD(data + 0x13),mem->type_detail);
+ if (h->length < 0x17) break;
+ dmi_memory_device_speed(WORD(data + 0x15),mem->speed);
+ if (h->length < 0x1B) break;
+ strcpy(mem->manufacturer, dmi_string(h, data[0x17]));
+ strcpy(mem->serial,dmi_string(h, data[0x18]));
+ strcpy(mem->asset_tag,dmi_string(h, data[0x19]));
+ strcpy(mem->part_number,dmi_string(h, data[0x1A]));
+ break;
+ case 22: /* 3.3.23 Portable Battery */
+ if (h->length < 0x10) break;
+ dmi->battery.filled=true;
+ strcpy(dmi->battery.location,dmi_string(h, data[0x04]));
+ strcpy(dmi->battery.manufacturer,dmi_string(h, data[0x05]));
+
+ if (data[0x06] || h->length < 0x1A)
+ strcpy(dmi->battery.manufacture_date, dmi_string(h, data[0x06]));
+
+ if (data[0x07] || h->length < 0x1A)
+ strcpy(dmi->battery.serial, dmi_string(h, data[0x07]));
+
+ strcpy(dmi->battery.name,dmi_string(h, data[0x08]));
+
+ if (data[0x09] != 0x02 || h->length < 0x1A)
+ strcpy(dmi->battery.chemistry,dmi_battery_chemistry(data[0x09]));
+
+ if (h->length < 0x1A)
+ dmi_battery_capacity(WORD(data + 0x0A), 1,dmi->battery.design_capacity);
+ else
+ dmi_battery_capacity(WORD(data + 0x0A), data[0x15],dmi->battery.design_capacity);
+ dmi_battery_voltage(WORD(data + 0x0C),dmi->battery.design_voltage);
+ strcpy(dmi->battery.sbds,dmi_string(h, data[0x0E]));
+ dmi_battery_maximum_error(data[0x0F],dmi->battery.maximum_error);
+ if (h->length < 0x1A) break;
+ if (data[0x07] == 0)
+ sprintf(dmi->battery.sbds_serial,"%04X", WORD(data + 0x10));
+
+ if (data[0x06] == 0)
+ sprintf(dmi->battery.sbds_manufacture_date,"%u-%02u-%02u",
+ 1980 + (WORD(data + 0x12) >> 9),
+ (WORD(data + 0x12) >> 5) & 0x0F,
+ WORD(data + 0x12) & 0x1F);
+ if (data[0x09] == 0x02)
+ strcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14]));
+
+ // 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 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],
+ dmi->system.system_boot_status);
+ case 38: /* 3.3.39 IPMI Device Information */
+ if (h->length < 0x10) break;
+ dmi->ipmi.filled=true;
+ snprintf(dmi->ipmi.interface_type,sizeof(dmi->ipmi.interface_type),
+ "%s", dmi_ipmi_interface_type(data[0x04]));
+ dmi->ipmi.major_specification_version=data[0x05] >> 4;
+ dmi->ipmi.minor_specification_version=data[0x05] & 0x0F;
+ dmi->ipmi.I2C_slave_address=data[0x06] >> 1;
+ if (data[0x07] != 0xFF)
+ dmi->ipmi.nv_address=data[0x07];
+ else
+ dmi->ipmi.nv_address=0; /* Not Present */
+ dmi_ipmi_base_address(data[0x04], data + 0x08,
+ &dmi->ipmi);
+ if (h->length < 0x12) break;
+ if (data[0x11] != 0x00)
+ {
+ dmi->ipmi.irq=data[0x11];
+ }
+ break;
+ }
}
void parse_dmitable(s_dmi * dmi)
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 <alan@redhat.com>
+ * (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
+ *
+ * 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 <dmi/dmi.h>
+#include <dmi/dmi_cache.h>
+#include <stdio.h>
+
+/*
+ * 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<<i))
+ sprintf(array, "%s%s", sep, types[i]);
+ }
+}
+
+const char *dmi_cache_ec_type(uint8_t code)
+{
+ /* 3.3.8.3 */
+ static const char *type[]={
+ "Other", /* 0x01 */
+ "Unknown",
+ "None",
+ "Parity",
+ "Single-bit ECC",
+ "Multi-bit ECC" /* 0x06 */
+ };
+
+ if(code>=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;
+}
diff --git a/com32/gpllib/dmi/dmi_memory.c b/com32/gpllib/dmi/dmi_memory.c
index b04dabbe..588e4ad6 100644
--- a/com32/gpllib/dmi/dmi_memory.c
+++ b/com32/gpllib/dmi/dmi_memory.c
@@ -168,3 +168,95 @@ void dmi_memory_device_speed(uint16_t code, char *speed)
else
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<<i))
+ sprintf(type, "%s%s", sep, types[i]);
+ }
+}
+
+void dmi_memory_module_connections(uint8_t code, char* connection)
+{
+ if(code==0xFF)
+ sprintf(connection, "%s", "None");
+ else
+ {
+ if((code&0xF0)!=0xF0)
+ sprintf(connection, "%u", code>>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);
+ }
+}
diff --git a/com32/gpllib/memory.c b/com32/gpllib/memory.c
new file mode 100644
index 00000000..6c6e351c
--- /dev/null
+++ b/com32/gpllib/memory.c
@@ -0,0 +1,216 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdint.h>
+#include <com32.h>
+#include <string.h>
+#include <memory.h>
+
+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
+ **/
+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);
+
+ /*
+ * 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++;
+
+ /* Set continuation value */
+ ireg.ebx.l = oreg.ebx.l;
+ } while (ireg.ebx.l && count < size_map);
+
+ *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;
+}
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 <stdio.h>
#include <stdlib.h>
#include <console.h>
-#include <getkey.h>
+#include <disk/geom.h>
+#include <disk/util.h>
#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 <com32io.h>
+#include <disk/geom.h>
#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..4e2994d9
--- /dev/null
+++ b/com32/hdt/hdt-cli-disk.c
@@ -0,0 +1,222 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <disk/errno_disk.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <disk/error.h>
+#include <disk/swsusp.h>
+#include <disk/msdos.h>
+
+#include "hdt-cli.h"
+#include "hdt-common.h"
+#include "hdt-util.h"
+
+/**
+ * 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):
+ *
+ * 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 driveinfo *drive_info,
+ struct part_entry *ptab,
+ int partition_offset,
+ int nb_partitions_seen)
+{
+ char size[9];
+ char *parttype;
+ unsigned int start, end;
+
+ int i = nb_partitions_seen;
+
+ start = partition_offset;
+ end = start + ptab->length - 1;
+
+ if (ptab->length > 0)
+ sectors_to_size(ptab->length, size);
+ 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" : " ",
+ start,
+ end,
+ size,
+ ptab->ostype, parttype);
+
+ /* Extra info */
+ if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab))
+ more_printf("%s", " (Swsusp sig. detected)");
+
+ more_printf("\n");
+
+ free(parttype);
+}
+
+void main_show_disk(int argc, char **argv,
+ struct s_hardware *hardware)
+{
+ 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];
+ char disk_size[9];
+
+ 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"
+ " 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)) {
+ 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");
+ }
+}
+
+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);
+
+ for (int drive = 0x80; drive < 0xff; drive++) {
+ i++;
+ if (!hardware->disk_info[i].cbios)
+ continue; /* Invalid geometry */
+ struct driveinfo *d = &hardware->disk_info[i];
+ char disk_size[9];
+
+ 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, 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));
+ }
+}
+
+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 = list_disk_show_modules,
+ .default_callback = disks_summary,
+};
+
+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-dmi.c b/com32/hdt/hdt-cli-dmi.c
index d395c672..fca94cdc 100644
--- a/com32/hdt/hdt-cli-dmi.c
+++ b/com32/hdt/hdt-cli-dmi.c
@@ -55,12 +55,24 @@ 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 <number>\n");
+ break;
+ }
+ }
if (hardware->dmi.processor.filled == true)
printf("\t%s\n", CLI_DMI_PROCESSOR);
if (hardware->dmi.system.filled == true)
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);
+ 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,
@@ -87,6 +99,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; i<sizeof hardware->dmi.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,
@@ -106,6 +127,34 @@ 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);
+
+ if (strlen(hardware->dmi.system.configuration_options)) {
+ printf("System Configuration Options\n");
+ 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);
}
static void show_dmi_bios(int argc __unused, char** argv __unused,
@@ -120,12 +169,13 @@ 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);
- 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",
@@ -303,7 +353,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;
@@ -354,6 +404,97 @@ 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 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)
{
@@ -374,19 +515,16 @@ 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);
/* 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 +536,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) {
@@ -434,6 +570,34 @@ 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);
+}
+
+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,
@@ -460,6 +624,10 @@ struct cli_callback_descr list_dmi_show_modules[] = {
.exec = show_dmi_memory_bank,
},
{
+ .name = "module",
+ .exec = show_dmi_memory_module,
+ },
+ {
.name = CLI_DMI_PROCESSOR,
.exec = show_dmi_cpu,
},
@@ -468,10 +636,22 @@ struct cli_callback_descr list_dmi_show_modules[] = {
.exec = show_dmi_system,
},
{
+ .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,
},
{
+ .name = CLI_DMI_CACHE,
+ .exec = show_dmi_cache,
+ },
+ {
.name = CLI_DMI_LIST,
.exec = show_dmi_modules,
},
diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c
index 46f3669a..5bebf584 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);
}
@@ -217,8 +221,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);
@@ -285,6 +289,10 @@ struct cli_callback_descr list_hdt_show_modules[] = {
.exec = main_show_cpu,
},
{
+ .name = CLI_DISK,
+ .exec = disks_summary,
+ },
+ {
.name = CLI_PXE,
.exec = main_show_pxe,
},
@@ -305,6 +313,14 @@ struct cli_callback_descr list_hdt_show_modules[] = {
.exec = main_show_hdt,
},
{
+ .name = CLI_VPD,
+ .exec = main_show_vpd,
+ },
+ {
+ .name = CLI_MEMORY,
+ .exec = show_dmi_memory_modules,
+ },
+ {
.name = "modes",
.exec = main_show_modes,
},
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-memory.c b/com32/hdt/hdt-cli-memory.c
new file mode 100644
index 00000000..89f871e1
--- /dev/null
+++ b/com32/hdt/hdt-cli-memory.c
@@ -0,0 +1,116 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <memory.h>
+
+#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");
+ reset_more_printf();
+ 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));
+ }
+}
+
+static void show_memory_e801(int argc __unused, char **argv __unused,
+ struct s_hardware *hardware __unused)
+{
+ int mem_low, mem_high = 0;
+
+ reset_more_printf();
+ 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;
+
+ reset_more_printf();
+ 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 = CLI_DMI_MEMORY_BANK,
+ .exec = show_dmi_memory_bank,
+ },
+ {
+ .name = NULL,
+ .exec = NULL,
+ },
+};
+
+struct cli_module_descr memory_show_modules = {
+ .modules = list_memory_show_modules,
+ .default_callback = show_dmi_memory_modules,
+};
+
+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-pci.c b/com32/hdt/hdt-cli-pci.c
index 1213c326..2de43fe3 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,
@@ -298,10 +310,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-cli.c b/com32/hdt/hdt-cli.c
index 871fd76c..0d38fb2b 100644
--- a/com32/hdt/hdt-cli.c
+++ b/com32/hdt/hdt-cli.c
@@ -43,7 +43,9 @@ struct cli_mode_descr *list_modes[] = {
&cpu_mode,
&pci_mode,
&vesa_mode,
+ &disk_mode,
&vpd_mode,
+ &memory_mode,
NULL,
};
@@ -179,6 +181,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;
case VPD_MODE:
detect_vpd(hardware);
if (!hardware->is_vpd_valid) {
@@ -189,7 +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");
@@ -424,16 +436,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,
- module_len) != 0)
+ strcmp(module_name,
+ modules_list->modules[modules_iter].name) != 0)
modules_iter++;
if (modules_list->modules[modules_iter].name) {
@@ -765,16 +775,23 @@ 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) {
- //fgets(cli_line, sizeof cli_line, stdin);
+ /* Display the cursor */
+ display_cursor(true);
+
+ /* 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();
@@ -967,14 +984,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:
diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h
index 516d2fc8..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 " "
@@ -64,10 +61,12 @@
#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"
#define CLI_VPD "vpd"
+#define CLI_MEMORY "memory"
typedef enum {
INVALID_MODE,
@@ -80,7 +79,9 @@ typedef enum {
KERNEL_MODE,
SYSLINUX_MODE,
VESA_MODE,
+ DISK_MODE,
VPD_MODE,
+ MEMORY_MODE,
} cli_mode_t;
#define PROMPT_SIZE 32
@@ -138,7 +139,9 @@ 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;
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);
@@ -161,9 +164,13 @@ 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_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);
+void show_dmi_memory_bank(int argc, char** argv, struct s_hardware *hardware);
// PCI STUFF
#define CLI_PCI_DEVICE "device"
@@ -173,6 +180,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 disks_summary(int argc, char **argv, struct s_hardware *hardware);
+
// PXE STUFF
void main_show_pxe(int argc, char **argv, struct s_hardware *hardware);
@@ -184,4 +194,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
diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c
index 8cda7f06..80305a3e 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 <disk/util.h>
/* ISOlinux requires a 8.3 format */
void convert_isolinux_filename(char *filename, struct s_hardware *hardware) {
@@ -55,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));
@@ -99,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;
@@ -124,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");
}
@@ -241,18 +250,27 @@ 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++;
- 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;
+
+ 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 print output when drive does not exist or
+ * doesn't support int13 (cdrom, ...)
+ */
+ if (err == -1 || !hardware->disk_info[i].cbios)
+ continue;
+
+ hardware->disks_count++;
+ }
}
int detect_pxe(struct s_hardware *hardware)
@@ -437,11 +455,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 7e3dc7d8..2b67f9ca 100644
--- a/com32/hdt/hdt-common.h
+++ b/com32/hdt/hdt-common.h
@@ -32,12 +32,17 @@
#include <syslinux/pxe.h>
#include "sys/pci.h"
+#include <disk/geom.h>
+
#include "cpuid.h"
#include "dmi/dmi.h"
#include "hdt-ata.h"
#include "../lib/sys/vesa/vesa.h"
#include <vpd/vpd.h>
+/* 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
@@ -55,6 +60,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;
@@ -97,13 +113,14 @@ struct s_hardware {
s_cpu cpu; /* CPU information */
s_vpd vpd; /* VPD 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;
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;
@@ -121,6 +138,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-disk.c b/com32/hdt/hdt-menu-disk.c
index 02f12f75..bd33bdf3 100644
--- a/com32/hdt/hdt-menu-disk.c
+++ b/com32/hdt/hdt-menu-disk.c
@@ -26,133 +26,200 @@
* -----------------------------------------------------------------------
*/
+#include <stdlib.h>
+#include <disk/errno_disk.h>
+#include <disk/geom.h>
+#include <disk/read.h>
+#include <disk/partition.h>
+#include <disk/error.h>
+#include <disk/msdos.h>
+#include <disk/swsusp.h>
+
#include "hdt-menu.h"
+#include "hdt-util.h"
+
+static int dn;
+
+static void show_partition_information(struct driveinfo *drive_info,
+ struct part_entry *ptab __unused,
+ int partition_offset __unused,
+ int nb_partitions_seen)
+{
+ 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",
+ 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
+ * @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,
+ int partition_offset,
+ int nb_partitions_seen)
+{
+ char size[9];
+ char *parttype;
+ unsigned int start, end;
+ char buffer[SUBMENULEN+1];
+ char statbuffer[STATLEN+1];
+ char menu_title[MENULEN + 1];
+ char menu_title_ref[MENULEN + 1];
+
+ 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, 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 = partition_offset;
+ end = start + ptab->length - 1;
+
+ 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",
+ (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",
+ start);
+ snprintf(statbuffer, sizeof statbuffer, "Start: %d",
+ start);
+ add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
+
+ snprintf(buffer, sizeof buffer, "End : %d",
+ end);
+ snprintf(statbuffer, sizeof statbuffer, "End: %d",
+ end);
+ 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);
+
+
+ free(parttype);
+
+ /* Extra info */
+ 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);
+ }
+}
/* Compute the disk submenu */
-int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu,
- struct diskinfo *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];
- /* 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> (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;
- 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++;
+ int previous_size, size;
+ char previous_unit[3], unit[3]; // GB
+ 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);
- /* Compute device size */
- char previous_unit[3], unit[3]; //GB
- int previous_size, size = d[disk_number].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);
- }
- }
- }
-
- snprintf(buffer, sizeof buffer, "Size : %d %s (%d %s)", size,
+ 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);
- 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, "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",
- d[disk_number].interface_type);
+ 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, "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].host_bus_type);
- snprintf(statbuffer, sizeof statbuffer, "Host Bus Type: %s",
- d[disk_number].host_bus_type);
+ 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, "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, "Sectors : %d",
- d[disk_number].sectors);
- snprintf(statbuffer, sizeof statbuffer, "Sectors: %d",
- d[disk_number].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);
- snprintf(statbuffer, sizeof statbuffer, "Heads: %d",
- d[disk_number].heads);
- add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
- menu[nb_sub_disk_menu].items_count++;
-
- snprintf(buffer, sizeof buffer, "Cylinders : %d",
- d[disk_number].cylinders);
- snprintf(statbuffer, sizeof statbuffer, "Cylinders: %d",
- d[disk_number].cylinders);
- 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);
+ 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].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++;
- snprintf(buffer, sizeof buffer, "Port : 0x%X", disk_number);
- snprintf(statbuffer, sizeof statbuffer, "Port: 0x%X", disk_number);
- add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0);
- menu[nb_sub_disk_menu].items_count++;
+ dn=disk_number;
- snprintf(buffer, sizeof buffer, "EDD Version : %s",
- d[disk_number].edd_version);
- snprintf(statbuffer, sizeof statbuffer, "EDD Version: %s",
- d[disk_number].edd_version);
- 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)) {
+ get_error("parse_partition_table");
+ menu[nb_sub_disk_menu].items_count++;
+ }
return 0;
}
/* 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 +228,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-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-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-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 <memory.h>
+#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-pci.c b/com32/hdt/hdt-menu-pci.c
index 74c07107..4e0d5887 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++) {
@@ -117,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++;
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);
}
diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c
index 18158ae3..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), "<M>emory (%2d)\n",
- hdt_menu->memory_menu.items_count);
+ snprintf(menu_item, sizeof(menu_item), "<M>emory\n");
add_item(menu_item, "Memory Menu", OPT_SUBMENU, NULL,
hdt_menu->memory_menu.menu);
hdt_menu->main_menu.items_count++;
@@ -244,7 +243,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("<V>PD","VPD Information Menu", OPT_SUBMENU, NULL,
hdt_menu->vpd_menu.menu);
hdt_menu->main_menu.items_count++;
}
@@ -263,7 +262,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("<K>ernel Modules", "Kernel Modules Menu", OPT_SUBMENU,
NULL, hdt_menu->kernel_menu.menu);
hdt_menu->main_menu.items_count++;
diff --git a/com32/hdt/hdt-menu.h b/com32/hdt/hdt-menu.h
index 70fdb385..1cd2c129 100644
--- a/com32/hdt/hdt-menu.h
+++ b/com32/hdt/hdt-menu.h
@@ -91,9 +91,7 @@ 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 diskinfo *d, int disk_number);
-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);
// DMI Stuff
void compute_motherboard(struct s_my_menu *menu, s_dmi * dmi);
diff --git a/com32/hdt/hdt-util.c b/com32/hdt/hdt-util.c
new file mode 100644
index 00000000..5bc566af
--- /dev/null
+++ b/com32/hdt/hdt-util.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 <stdio.h>
+#include <string.h>
+
+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);
+}
+
+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
new file mode 100644
index 00000000..8c1d6de5
--- /dev/null
+++ b/com32/hdt/hdt-util.h
@@ -0,0 +1,33 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 *);
+void sectors_to_size_dec(char *, int *, char *, int *, int);
+#endif
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);
diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h
index dfcb4368..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.1"
+#define VERSION "0.3.4"
#define NB_CONTRIBUTORS 2
#define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"}
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
diff --git a/com32/include/dirent.h b/com32/include/dirent.h
index d99b21fb..c4aca4f0 100644
--- a/com32/include/dirent.h
+++ b/com32/include/dirent.h
@@ -10,23 +10,7 @@
#include <stddef.h>
#include <sys/types.h>
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-struct dirent {
- long d_ino; /* Inode/File number */
- off_t d_size; /* Size of file */
- mode_t d_mode; /* Type of file */
- 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 */
-} DIR;
+#include <sys/dirent.h>
__extern DIR *opendir(const char *);
__extern struct dirent *readdir(DIR *);
diff --git a/com32/include/netinet/in.h b/com32/include/netinet/in.h
index 582632c9..ccf04750 100644
--- a/com32/include/netinet/in.h
+++ b/com32/include/netinet/in.h
@@ -4,37 +4,47 @@
/* COM32 will be running on an i386 platform */
#include <stdint.h>
+#include <klibc/compiler.h>
-static inline uint16_t __htons(uint16_t v)
+#define __htons_macro(v) ((uint16_t) \
+ (((uint16_t)(v) << 8) | \
+ ((uint16_t)(v) >> 8)))
+
+static inline __constfunc 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) ((uint32_t) \
+ ((((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)
+static inline __constfunc uint32_t __htonl(uint32_t v)
{
- if (__builtin_constant_p(v)) {
- return (((v) & 0x000000ff) << 24) |
- (((v) & 0x0000ff00) << 8) |
- (((v) & 0x00ff0000) >> 8) | (((v) & 0xff000000) >> 24);
- } 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) __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) \
+ (((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);
+ 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;
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 <num_bytes> 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_<chunk> functions are for storing values in the png_info_struct.
* Similarly, the png_get_<chunk> 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 */
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. */
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/include/sys/dirent.h b/com32/include/sys/dirent.h
new file mode 100644
index 00000000..cc2916e1
--- /dev/null
+++ b/com32/include/sys/dirent.h
@@ -0,0 +1,30 @@
+/*
+ * sys/dirent.h
+ */
+
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#include <stdint.h>
+
+#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/include/sys/pci.h b/com32/include/sys/pci.h
index 2c6b5158..aba1f965 100644
--- a/com32/include/sys/pci.h
+++ b/com32/include/sys/pci.h
@@ -17,8 +17,9 @@
typedef uint32_t pciaddr_t;
enum {
- ENOPCIIDS = 100,
- ENOMODULESPCIMAP
+ ENOPCIIDS = 100,
+ ENOMODULESPCIMAP,
+ ENOMODULESALIAS
};
/* a structure for extended pci information */
@@ -145,9 +146,8 @@ void free_pci_domain(struct pci_domain *domain);
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_class_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/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 <stdint.h>
-#include <netinet/in.h>
-#include <klibc/compiler.h>
-
-/* 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/pxe_api.h>
/* 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..fcc4f873
--- /dev/null
+++ b/com32/include/syslinux/pxe_api.h
@@ -0,0 +1,566 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdint.h>
+#include <netinet/in.h>
+#include <klibc/compiler.h>
+#include <com32.h>
+
+/* 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;
+
+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;
+
+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
+#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/com32/lib/MCONFIG b/com32/lib/MCONFIG
index 8e400776..ca8234b6 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)
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 999b4869..2adb59bf 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -15,36 +15,36 @@ LIBPNG_OBJS = \
libpng/pngrio.o libpng/pngwio.o libpng/pngwrite.o \
libpng/pngrtran.o libpng/pngwtran.o libpng/pngmem.o \
libpng/pngerror.o libpng/pngpread.o
-
+
# ZIP library object files
LIBZLIB_OBJS = \
- 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\
\
sys/zfile.o sys/zfopen.o \
\
syslinux/zloadfile.o
-
+
# JPG library object files
LIBJPG_OBJS = \
jpeg/tinyjpeg.o jpeg/jidctflt.o jpeg/decode1.o jpeg/decode3.o \
jpeg/rgb24.o jpeg/bgr24.o jpeg/yuv420p.o jpeg/grey.o \
jpeg/rgba32.o jpeg/bgra32.o
-
+
LIBVESA_OBJS = \
sys/vesacon_write.o sys/vesaserial_write.o \
sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \
sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o
-
+
LIBPCI_OBJS = \
pci/cfgtype.o pci/scan.o \
pci/readb.o pci/readw.o pci/readl.o pci/readbios.o \
pci/writeb.o pci/writew.o pci/writel.o pci/writebios.o
-
+
LIBSYSLINUX_OBJS = \
syslinux/reboot.o syslinux/keyboard.o \
- syslinux/features.o syslinux/config.o \
+ syslinux/features.o syslinux/config.o \
syslinux/ipappend.o syslinux/dsinfo.o syslinux/version.o \
\
syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o \
@@ -78,23 +78,23 @@ LIBENTRY_OBJS = \
sys/openmem.o sys/unread.o \
sys/isatty.o sys/fstat.o \
\
- syslinux/idle.o \
+ syslinux/idle.o \
\
exit.o
-
+
LIBMODULE_OBJS = \
sys/module/common.o sys/module/elf_module.o \
sys/module/shallow_module.o sys/module/elfutils.o \
sys/module/exec.o
-
-
+
+
LIBGCC_OBJS = \
libgcc/__ashldi3.o libgcc/__udivdi3.o \
libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \
libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \
libgcc/__divdi3.o libgcc/__moddi3.o
-
+
LIBCONSOLE_OBJS = \
\
sys/openconsole.o sys/line_input.o \
@@ -122,9 +122,9 @@ LIBOTHER_OBJS = \
perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \
sprintf.o srand48.o sscanf.o strcasecmp.o strcat.o \
strchr.o strcmp.o strcpy.o strdup.o strerror.o strlen.o \
- strnlen.o strpcpy.o \
+ strnlen.o \
strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \
- stpcpy.o stpncpy.o \
+ stpcpy.o stpncpy.o \
strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \
strtoimax.o strtok.o strtol.o strtoll.o strtoul.o strtoull.o \
strtoumax.o vfprintf.o vprintf.o vsnprintf.o vsprintf.o \
@@ -158,7 +158,7 @@ LIBOTHER_OBJS = \
sys/x86_init_fpu.o math/pow.o math/strtod.o \
\
syslinux/memscan.o
-
+
MINLIBOBJS = \
$(LIBOTHER_OBJS) \
$(LIBENTRY_OBJS) \
@@ -167,7 +167,7 @@ MINLIBOBJS = \
$(LIBMODULE_OBJS) \
# $(LIBVESA_OBJS)
-
+
DYNLIBOBJS = \
$(LIBZLIB_OBJS) \
$(LIBPNG_OBJS) \
@@ -176,8 +176,8 @@ DYNLIBOBJS = \
$(LIBVESA_OBJS) \
$(LIBSYSLINUX_OBJS) \
$(DYNENTRY_OBJS)
-
-
+
+
LIBOBJS = \
$(MINLIBOBJS) \
$(DYNLIBOBJS)
@@ -195,7 +195,7 @@ libcom32.a : $(LIBOBJS)
rm -f $@
$(AR) cq $@ $^
$(RANLIB) $@
-
+
$(LIBMODULE_OBJS) : CFLAGS += -DELF_DEBUG
libcom32min.a : $(MINLIBOBJS)
rm -f $@
diff --git a/com32/lib/closedir.c b/com32/lib/closedir.c
index f8bbbabd..b3f55642 100644
--- a/com32/lib/closedir.c
+++ b/com32/lib/closedir.c
@@ -13,17 +13,17 @@
int closedir(DIR * dir)
{
- int rv;
- com32sys_t regs;
- if (dir == NULL) {
- rv = 0;
- } else {
- memset(&regs, 0, sizeof regs); /* ?Needed? */
+ int rv = -1;
+
+ if (dir) {
+ com32sys_t regs;
+ memset(&regs, 0, sizeof regs);
regs.eax.w[0] = 0x0022;
- regs.esi.w[0] = dir->dd_fd;
+ regs.esi.l = (uint32_t)dir;
__com32.cs_intcall(0x22, &regs, &regs);
- free(dir); /* garbage collection? */
+ free(dir);
rv = 0;
}
+
return rv;
}
diff --git a/com32/lib/opendir.c b/com32/lib/opendir.c
index 6fc0f14f..6f91032b 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,16 +23,13 @@ DIR *opendir(const char *pathname)
regs.es = SEG(__com32.cs_bounce);
__com32.cs_intcall(0x22, &regs, &regs);
-
+
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));
+ newdir->dd_dir = (struct file *)regs.eax.l;
}
-
+
/* We're done */
return newdir;
}
diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c
index f24a5cd8..82a7c844 100644
--- a/com32/lib/pci/scan.c
+++ b/com32/lib/pci/scan.c
@@ -78,100 +78,89 @@ static int hex_to_int(char *hexa)
int get_module_name_from_pcimap(struct pci_domain *domain,
char *modules_pcimap_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; i < MAX_KERNEL_MODULES_PER_PCI_DEVICE; i++) {
- strlcpy(dev->dev_info->linux_kernel_module[i], "unknown", 7);
- }
+ 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;
}
-
- /* Opening the modules.pcimap (of a linux kernel) from the boot device */
- f = fopen(modules_pcimap_path, "r");
- if (!f)
- return -ENOMODULESPCIMAP;
-
- strcpy(vendor_id, "0000");
- strcpy(product_id, "0000");
- strcpy(sub_product_id, "0000");
- strcpy(sub_vendor_id, "0000");
- 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] == '#') || (line[0] == ' ') || (line[0] == 10))
- continue;
-
- char *result = NULL;
- int field = 0;
-
- /* looking for the next field */
- result = strtok(line, delims);
- while (result != NULL) {
- /* if the column is larger than 1 char */
- /* multiple spaces generates some empty fields */
- if (strlen(result) > 1) {
- switch (field) {
- case 0:
- strcpy(module_name, result);
- break;
- case 1:
- strcpy(vendor_id, result);
- break;
- case 2:
- strcpy(product_id, result);
- break;
- case 3:
- strcpy(sub_vendor_id, result);
- break;
- case 4:
- strcpy(sub_product_id, result);
- break;
- }
- field++;
- }
- /* Searching the next field */
- result = strtok(NULL, delims);
- }
- 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++;
- }
- }
+ for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) {
+ if (strlen(dev->dev_info->linux_kernel_module[i])==0)
+ strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7);
}
- fclose(f);
- return 0;
+ }
+
+ /* Opening the modules.pcimap (of a linux kernel) from the boot device */
+ f=fopen(modules_pcimap_path, "r");
+ if (!f)
+ return -ENOMODULESPCIMAP;
+
+ strcpy(vendor_id,"0000");
+ strcpy(product_id,"0000");
+ strcpy(sub_product_id,"0000");
+ strcpy(sub_vendor_id,"0000");
+ 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] == '#') || (line[0] == ' ') || (line[0] == 10))
+ continue;
+
+ char *result = NULL;
+ int field=0;
+
+ /* looking for the next field */
+ result = strtok(line, delims);
+ while( result != NULL ) {
+ /* if the column is larger than 1 char */
+ /* multiple spaces generates some empty fields */
+ if (strlen(result)>1) {
+ switch (field) {
+ case 0:strcpy(module_name,result); break;
+ case 1:strcpy(vendor_id,result); break;
+ case 2:strcpy(product_id,result); break;
+ case 3:strcpy(sub_vendor_id,result); break;
+ case 4:strcpy(sub_product_id,result); break;
+ }
+ field++;
+ }
+ /* Searching the next field */
+ result = strtok( NULL, delims );
+ }
+ 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;
}
/* Try to match any pci device to the appropriate class name */
@@ -595,3 +584,129 @@ 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;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) {
+ if (strlen(dev->dev_info->linux_kernel_module[i])==0)
+ strlcpy(dev->dev_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;
+}
diff --git a/com32/lib/readdir.c b/com32/lib/readdir.c
index 2ec7c7b3..07ca3955 100644
--- a/com32/lib/readdir.c
+++ b/com32/lib/readdir.c
@@ -15,40 +15,12 @@ struct dirent *readdir(DIR * dir)
{
struct dirent *newde;
com32sys_t regs;
-
- newde = NULL;
- if ((dir != NULL) && (dir->dd_fd != 0) && (dir->dd_stat >= 0)) {
- memset(__com32.cs_bounce, 0, 32);
- memset(&regs, 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);
-
- __com32.cs_intcall(0x22, &regs, &regs);
-
- /* 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;
- }
-
+
+ memset(&regs, 0, sizeof(regs));
+ regs.eax.w[0] = 0x0021;
+ regs.esi.l = (uint32_t)dir;
+ __com32.cs_intcall(0x22, &regs, &regs);
+ newde = (struct dirent *)(regs.eax.l);
+
return newde;
}
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 <string.h>
-
-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/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 <stdio.h>
-#include "zlib.h"
-
-#ifdef STDC
-# include <string.h>
-# include <stdlib.h>
-#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/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 <stdio.h>
-
-#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:%d>", 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 <stdarg.h>
-
-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); */
-}
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 <stdio.h>
-#include "zlib.h"
-
-#ifdef STDC
-# include <string.h>
-# include <stdlib.h>
-#else
- extern void exit OF((int));
-#endif
-
-#ifdef USE_MMAP
-# include <sys/types.h>
-# include <sys/mman.h>
-# include <sys/stat.h>
-#endif
-
-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-# include <fcntl.h>
-# include <io.h>
-# 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 <unix.h> /* 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 <malbrech@eso.org> */
-
-/* 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;
-}
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';
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index 3af630f8..b2d81017 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();
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index e3155bd5..68e50571 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -18,10 +18,10 @@
topdir = ../..
include ../MCONFIG
-MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
+MODULES = chain.c32 config.c32 ethersel.c32 dmitest.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
+ 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..913c2ca7
--- /dev/null
+++ b/com32/modules/dir.c
@@ -0,0 +1,35 @@
+/*
+ * A dir test module
+ */
+#include <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <com32.h>
+#include <dirent.h>
+
+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/modules/disk.c b/com32/modules/disk.c
new file mode 100644
index 00000000..e94a36bf
--- /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 <stdio.h>
+#include <console.h>
+#include <stdlib.h>
+#include <string.h>
+#include <disk/geom.h>
+#include <disk/util.h>
+
+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;
+}
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 <stdio.h>
+#include <console.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <com32.h>
+
+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, &regs, &regs);
+
+ 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/com32/rosh/rosh.c b/com32/rosh/rosh.c
index 9a4edae2..2221bb0a 100644
--- a/com32/rosh/rosh.c
+++ b/com32/rosh/rosh.c
@@ -389,12 +389,12 @@ 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)) {
+ 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,19 +423,18 @@ 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' %8d %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 +444,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 +455,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/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/Makefile b/core/Makefile
index 17dac944..b9963657 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -33,24 +33,28 @@ CODEPAGE = cp865
# The targets to build in this directory...
BTARGET = kwdhash.gen \
+ extlinux.bin extlinux.bss extlinux.sys \
ldlinux.bss ldlinux.sys ldlinux.bin \
- pxelinux.0 isolinux.bin isolinux-debug.bin \
- extlinux.bin extlinux.bss extlinux.sys
+ isolinux.bin isolinux-debug.bin pxelinux.0
# All primary source files for the main syslinux files
NASMSRC := $(wildcard *.asm)
NASMHDR := $(wildcard *.inc)
-CSRC := $(wildcard *.c */*.c)
-SSRC := $(wildcard *.S lzo/*.S)
-CHDR := $(wildcard *.h */*.h)
+CSRC := $(wildcard *.c */*.c */*/*.c)
+SSRC := $(wildcard *.S */*.S */*/*.S)
+CHDR := $(wildcard *.h */*.h */*/*.h)
OTHERSRC := keywords
ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(SSRC) $(CHDR) $(OTHERSRC)
COBJ := $(patsubst %.c,%.o,$(CSRC))
SOBJ := $(patsubst %.S,%.o,$(SSRC))
+#
+# Note: libcore.a should *NOT* be --whole-archive, since it contains all
+# the filesystems...
+#
LIB = libcore.a
-LIBS = --whole-archive $(LIB) $(com32)/lib/libcom32min.a
+LIBS = $(LIB) --whole-archive $(com32)/lib/libcom32min.a
# --no-whole-archive $(LIBGCC)
LIBDEP = $(filter-out -% %start%,$(LIBS))
LIBOBJS = $(COBJ) $(SOBJ)
@@ -131,8 +135,9 @@ netinstall: installer
tidy dist:
rm -f codepage.cp *.o *.elf *.a stupid.* patch.offset .depend .*.d
- rm -f *.sym *.lsr *.lst *.map *.sec *.raw
- rm -f */*.o */*.lst */.*.d
+ rm -f *.elf.tmp *.sym
+ rm -f *.lsr *.lst *.map *.sec *.raw
+ rm -f */*.o */*/*.o */*.lst */*/*.lst */.*.d */*/.*.d
rm -f $(OBSOLETE)
clean: tidy
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/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/cache.c b/core/cache.c
new file mode 100644
index 00000000..c55f1603
--- /dev/null
+++ b/core/cache.c
@@ -0,0 +1,155 @@
+#include "core.h"
+#include "cache.h"
+#include <stdio.h>
+#include <string.h>
+
+
+/**
+ * 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.
+ */
+
+/**
+ * cache_init:
+ *
+ * Initialize the cache data structres.
+ * regs->eax.l stores the block size(in bits not bytes)
+ *
+ */
+void cache_init(struct device *dev, int block_size_shift)
+{
+ struct cache_struct *prev, *cur;
+ 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_head.prev = &cache[dev->cache_entries-1];
+ cache_head.prev->next = &cache_head;
+ prev = &cache_head;
+
+ for (i = 0; i < dev->cache_entries; i++) {
+ cur = &cache[i];
+ cur->block = 0;
+ cur->prev = prev;
+ prev->next = cur;
+ cur->data = data;
+ data += dev->cache_block_size;
+ prev = cur++;
+ }
+}
+
+
+/**
+ * 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.
+ *
+ * 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
+ *
+ */
+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 = head->prev;
+ int i;
+ static int total_read;
+ static int missed;
+
+#if 0
+ printf("we are looking for cache of %d\n", block);
+#endif
+
+ 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)
+ goto out;
+
+ for (i = 0; i < dev->cache_entries; i ++) {
+ if (cs->block == block)
+ break;
+ else
+ cs = cs->prev;
+ }
+
+ /* missed, so we need to load it */
+ if (i == dev->cache_entries) {
+ /* store it at the head of real cache */
+ cs = head->next;
+ cs->block = block;
+ getoneblk(dev->disk, cs->data, block, dev->cache_block_size);
+
+ missed ++;
+ }
+
+ /* remove cs from current position in list */
+ cs->prev->next = cs->next;
+ cs->next->prev = cs->prev;
+
+ /* add to just before head node */
+ last->next = cs;
+ cs->prev = last;
+ head->prev = cs;
+ 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)
+ 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/call16.c b/core/call16.c
index 1e369e29..86d70461 100644
--- a/core/call16.c
+++ b/core/call16.c
@@ -19,6 +19,8 @@
#include <stddef.h>
#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/comboot.inc b/core/comboot.inc
index 079b4761..f01ff646 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
@@ -126,7 +126,7 @@ is_comboot_image:
mov bx,100h ; Load at <seg>: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
@@ -517,9 +517,9 @@ comapi_open:
mov ds,P_ES
mov si,P_SI
mov di,InitRD
- call mangle_name
+ pm_call mangle_name
pop ds
- call searchdir
+ pm_call searchdir
jz comapi_err
mov P_EAX,eax
mov P_CX,SECTOR_SIZE
@@ -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
@@ -547,7 +547,7 @@ comapi_read:
;
comapi_close:
mov si,P_SI
- call close_file
+ pm_call close_file
clc
ret
@@ -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
@@ -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
@@ -748,9 +749,9 @@ comapi_runkernel:
mov ds,P_DS
mov si,P_SI
mov di,KernelName
- call mangle_name
+ pm_call mangle_name
pop ds
- call searchdir
+ pm_call searchdir
jz comapi_err
; The kernel image was found, so we can load it...
@@ -900,21 +901,14 @@ comapi_getcwd:
;
%if IS_SYSLINUX
comapi_opendir:
- push ds
- mov ds,P_ES
+ mov es,P_ES
mov si,P_SI
mov di,InitRD
- call mangle_name
- pop ds
- call searchdir
- jnz comapi_err ; Didn't find a directory
+ pm_call vfs_opendir
+ jz comapi_err ; Didn't find a directory
cmp eax,0
jz comapi_err ; Found nothing
- ;ZF is unset
- call alloc_fill_dir
- mov P_EAX,eax
- mov P_CX,SECTOR_SIZE
- mov P_SI,si
+ mov P_EAX,eax
clc
ret
%else
@@ -926,14 +920,9 @@ comapi_opendir equ comapi_err
;
%if IS_SYSLINUX
comapi_readdir:
- mov es,P_ES
- mov di,P_DI
- mov si,P_SI
- call 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 vfs_readdir
+ mov P_EAX,eax ; The address of newly read dirent structure
ret
%else
comapi_readdir equ comapi_err
@@ -942,15 +931,10 @@ comapi_readdir equ comapi_err
;
; INT 22h AX=0022h Close directory
;
-%if IS_SYSLINUX
comapi_closedir:
- mov si,P_SI
- call close_dir
- clc
+ mov esi,P_ESI ; The address of DIR structure
+ pm_call vfs_closedir
ret
-%else
-comapi_closedir equ comapi_err
-%endif
;
; INT 22h AX=0023h Query shuffler size
@@ -1051,5 +1035,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/config.inc b/core/config.inc
index 5a3d1c5a..269e13ec 100644
--- a/core/config.inc
+++ b/core/config.inc
@@ -32,6 +32,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
;
%include "../version.gen"
diff --git a/core/conio.inc b/core/conio.inc
index 5209af1c..835359fb 100644
--- a/core/conio.inc
+++ b/core/conio.inc
@@ -207,8 +207,8 @@ msg_viewimage:
mov byte [si],0 ; Zero-terminate filename
mov si,VGAFileBuf
mov di,VGAFileMBuf
- call mangle_name
- call open
+ pm_call mangle_name
+ call core_open
jz msg_putcharnext ; Not there
call vgadisplayfile
; Fall through
diff --git a/core/dir.c b/core/dir.c
new file mode 100644
index 00000000..d745a32f
--- /dev/null
+++ b/core/dir.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <fs.h>
+#include <core.h>
+
+extern struct fs_info *this_fs;
+
+/*
+ * open dir, return the file structure pointer in _eax_, or NULL if failed
+ */
+void vfs_opendir(com32sys_t *regs)
+{
+ this_fs->fs_ops->opendir(regs);
+ regs->eax.l = (uint32_t)handle_to_file(regs->esi.w[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 vfs_readdir(com32sys_t *regs)
+{
+ 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;
+
+ /* Return the newly read de in _eax_ register */
+ regs->eax.l = (uint32_t)de;
+}
+
+void vfs_closedir(com32sys_t *regs)
+{
+ DIR *dir = (DIR *)regs->esi.l;
+ _close_file(dir->dd_dir);
+}
+
+
diff --git a/core/diskfs.inc b/core/diskfs.inc
new file mode 100644
index 00000000..b8d03762
--- /dev/null
+++ b/core/diskfs.inc
@@ -0,0 +1,182 @@
+; -*- 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.
+;
+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
+
+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
+
+;
+; 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"
+
+;
+;
+; 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/diskio.c b/core/diskio.c
new file mode 100644
index 00000000..c51f7225
--- /dev/null
+++ b/core/diskio.c
@@ -0,0 +1,352 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <klibc/compiler.h>
+#include "core.h"
+#include "fs.h"
+#include "disk.h"
+
+#define RETRY_COUNT 6
+
+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)
+{
+ char *ptr = buf;
+ char *tptr;
+ size_t chunk, freeseg;
+ int sector_shift = disk->sector_shift;
+ 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;
+ 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;
+
+ /* 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;
+ ireg.eax.b[0] = chunk;
+ 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_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);
+
+ lba += disk->part_start;
+ 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 = chunk == 1 ? 0 : ((chunk+1) >> 1);
+ if (chunk) {
+ MaxTransfer = chunk;
+ retry = RETRY_COUNT;
+ pkt.blocks = chunk;
+ continue;
+ }
+ /*** XXX: Consider falling back to CHS here?! ***/
+ printf("reading sectors error(EDD)\n");
+ 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));
+}
+
+static 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 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);
+ 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");
+ 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,
+ 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;
+
+#if 0
+ dump_disk(&disk);
+#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 */
+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);
+ 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/diskstart.inc b/core/diskstart.inc
index d7279028..36d513ed 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
@@ -252,6 +253,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)
@@ -453,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
@@ -487,6 +490,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
@@ -709,6 +713,21 @@ expand_super:
stosd ; Store expanded byte
loop .loop
+
;
-; Fall through to the mainline code...
+; Common initialization code
;
+%include "init.inc"
+%include "cpuinit.inc"
+
+
+ pushad
+ 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]
+ pm_call fs_init
+ popad
diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc
deleted file mode 100644
index 7b632378..00000000
--- a/core/dnsresolv.inc
+++ /dev/null
@@ -1,389 +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
-;
-; 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.
-;
-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
- 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
-
-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
-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
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/extern.inc b/core/extern.inc
index bc3ffef5..0c127805 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -15,4 +15,15 @@
; elflink/load_env32.c
extern load_env32
+ ; fs.c
+ extern fs_init, searchdir, getfssec, mangle_name, load_config
+ extern unmangle_name, close_file
+
+ ; dir.c
+ extern vfs_opendir, vfs_readdir, vfs_closedir
+%if IS_PXELINUX
+ ; pxe.c
+ extern unload_pxe, reset_pxe
+%endif
+
%endif ; EXTERN_INC
diff --git a/core/extlinux.asm b/core/extlinux.asm
index 503bbf7e..1f5423b2 100644
--- a/core/extlinux.asm
+++ b/core/extlinux.asm
@@ -18,909 +18,13 @@
%define IS_EXTLINUX 1
%include "head.inc"
-%include "ext2_fs.inc"
;
; 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)
+ extern ext2_fs_ops
+ROOT_FS_OPS equ ext2_fs_ops
-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
-; 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
-
-;
-; 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
-; ---------------------------------------------------------------------------
-
-;
-; Memory below this point is reserved for the BIOS and the MBR
-;
- section .earlybss
-trackbufsize equ 8192
-trackbuf resb trackbufsize ; Track buffer goes here
- ; ends at 2800h
-
- section .bss16
-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
-Files resb MAX_OPEN*open_file_t_size
-
-;
-; Common bootstrap code for disk-based derivatives
-;
-%include "diskstart.inc"
-
-;
-; Common initialization code
-;
-%include "init.inc"
-%include "cpuinit.inc"
-
-;
-; Load the real (ext2) superblock; 1024 bytes long at offset 1024
-;
- mov bx,SuperBlock
- mov eax,1024 >> SECTOR_SHIFT
- mov bp,ax
- call getlinsecsr
-
-;
-; 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
-
-;
-; Initialize the metadata cache
-;
- call initcache
-
-;
-; 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
-;
-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
- pm_call load_env32
-
- call open
- jz no_config_file
-
-;
-; Now we have the config file open. Parse the config file and
-; run the user interface.
-;
-%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 getlinsecsr ; 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
-
-;
-; 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
- call getcachesector ; 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
-
- call getcachesector
- 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
-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
-
-;
-; 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
-
- 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
-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
-;
-; 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.
-;
-; 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
-
-
-;
-; 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
- call getcachesector ; 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
- call getcachesector
- 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
- call getcachesector
- 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
- call getcachesector
- 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
-;
-; 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.
-;
-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
- 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
- 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
-
-; -----------------------------------------------------------------------------
-; 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 "cache.inc" ; Metadata disk cache
-%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/fs.c b/core/fs.c
new file mode 100644
index 00000000..a3407cfe
--- /dev/null
+++ b/core/fs.c
@@ -0,0 +1,190 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include "fs.h"
+#include "cache.h"
+
+/* The currently mounted filesystem */
+struct fs_info *this_fs = NULL;
+struct fs_info fs;
+
+/* Actual file structures (we don't have malloc yet...) */
+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;
+ file++;
+ }
+
+ return NULL;
+}
+
+/*
+ * Close and free a file structure
+ */
+static inline void free_file(struct file *file)
+{
+ memset(file, 0, sizeof *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
+ */
+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(void)
+{
+ 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)
+{
+ 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);
+}
+
+
+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 */
+ regs->edi.w[0] = OFFS_WRT(dst, regs->es);
+}
+
+
+void getfssec(com32sys_t *regs)
+{
+ int sectors;
+ bool have_more;
+ uint32_t bytes_read;
+ char *buf;
+ struct file *file;
+ uint16_t handle;
+
+ sectors = regs->ecx.w[0];
+
+ 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 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;
+}
+
+
+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
+
+ 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:
+ * set up the vfs fs structure;
+ * initialize the device structure;
+ * invoke the fs-specific init function;
+ * finally, initialize the cache
+ *
+ */
+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;
+
+ /* 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]);
+
+ this_fs = &fs;
+
+ /* invoke the fs-specific init code */
+ 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);
+}
diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c
new file mode 100644
index 00000000..8c44b3ae
--- /dev/null
+++ b/core/fs/ext2/ext2.c
@@ -0,0 +1,736 @@
+#include <stdio.h>
+#include <string.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include "ext2_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
+ */
+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 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;
+
+/*
+ * just like the function strcpy(), except it returns non-zero if overflow.
+ *
+ */
+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 a file structure, if successful return the file pointer, or 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);
+}
+
+/**
+ * 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 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 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<<ClustShift) + (block_off>>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;
+}
+
+
+
+
+/**
+ * Search the root directory for a pre-mangle filename in FILENAME.
+ *
+ * @param: filename, the filename we want to search.
+ *
+ * @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)
+{
+ 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
+
+}
+
+/* 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(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ call16(core_open, &regs, &regs);
+
+ return !!(regs.eflags.l & EFLAGS_ZF);
+}
+
+
+/*
+ * 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;
+
+ /* 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 = generic_mangle_name,
+ .unmangle_name = generic_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 <stdint.h>
+
+#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..e7931b0f
--- /dev/null
+++ b/core/fs/fat/fat.c
@@ -0,0 +1,895 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include "fat_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) */
+ 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;
+
+/*
+ * 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 = Files;
+ int i = 0;
+
+ for (; i < MAX_OPEN; i ++) {
+ if (file->file_sector == 0) /* found it */
+ return file;
+ file ++;
+ }
+
+ return NULL; /* not found */
+}
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * 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);
+}
+
+
+/**
+ * Advance a cluster pointer in clust_num to the next cluster
+ * 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)
+{
+ 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;
+}
+
+
+
+/*
+ * 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);
+}
+
+
+
+/**
+ * get multiple sectors from a file
+ *
+ * @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
+ *
+ */
+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 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, const char *src)
+{
+ char *p = dst;
+ char c;
+ int i = FILENAME_MAX -1;
+
+ /*
+ * Copy the filename, converting backslash to slash and
+ * collapsing duplicate separators.
+ */
+ while (not_whitespace(c = *src)) {
+ if (c == '\\')
+ c = '/';
+
+ if (c == '/') {
+ if (src[1] == '/' || src[1] == '\\') {
+ src++;
+ i--;
+ continue;
+ }
+ }
+ i--;
+ *dst++ = *src++;
+ }
+
+ /* Strip terminal slashes or whitespace */
+ while (1) {
+ if (dst == p)
+ break;
+ if (*(dst-1) == '/' && dst-1 == p) /* it's the '/' case */
+ break;
+ if ((*(dst-1) != '/') && (*(dst-1) != '.'))
+ break;
+
+ dst--;
+ i++;
+ }
+
+ i++;
+ for (; i > 0; i --)
+ *dst++ = '\0';
+}
+
+/*
+ * 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!
+ */
+/**
+ * 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];
+ }
+}
+
+/*
+ * 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 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
+ *
+ */
+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;
+}
+
+
+
+/**
+ * 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;
+
+ 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) {
+ 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;
+}
+
+/*
+ * 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 the newly read de structure
+ */
+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 */
+ uint8_t id = 1;
+ uint8_t init_id, next_id;
+ uint8_t checksum = 0;
+ uint8_t entries_left;
+ int i;
+ 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;
+
+ sector = file->file_sector;
+ sec_off = file->file_bytesleft;
+ if (!sector)
+ return NULL;
+ entries_left = (SECTOR_SIZE - sec_off) >> 5;
+ 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) {
+ sector = nextsector(fs, sector);
+ if (!sector)
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, sector);
+ fat_dir = (struct fat_dir_entry *)cs->data;
+ }
+
+ if (fat_dir->name[0] == 0)
+ 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;
+ init_id = id = long_dir->id & 0x3f;
+ id--;
+ } else {
+ next_id = (long_dir->id & 0x3f) - 1;
+ id--;
+ if (id != next_id || long_dir->checksum != checksum)
+ goto next_entry;
+ }
+
+ 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
+ */
+
+ } else {
+ /* it's a short entry */
+
+ if (!id) {
+ /* 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;
+
+ for(i = 0; i < 8; i ++) {
+ if (fat_dir->name[i] == ' ')
+ break;
+ *de_name++ = fat_dir->name[i];
+ }
+ *de_name++ = '.';
+ for (i = 8; i < 11; i ++) {
+ if (fat_dir->name[i] == ' ')
+ break;
+ *de_name ++ = fat_dir->name[i];
+ }
+ /* check if we have got an extention */
+ if (*(de_name - 1) == '.')
+ *(de_name - 1) = '\0';
+ else
+ *de_name = '\0';
+
+ break;
+ }
+
+ next_entry:
+ 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 */
+ entries_left--;
+ 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;
+}
+
+/* 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";
+ const char * const syslinux_cfg[] =
+ { syslinux_cfg1, syslinux_cfg2, syslinux_cfg3 };
+ com32sys_t regs;
+ 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
+ */
+ memset(&regs, 0, sizeof regs);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ for (; i < 3; i++) {
+ strcpy(ConfigName, syslinux_cfg[i]);
+ call16(core_open, &regs, &regs);
+
+ /* if zf flag set, then failed; try another */
+ if (! (regs.eflags.l & EFLAGS_ZF))
+ break;
+ }
+ if (i == 3) {
+ printf("no config file found\n");
+ 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)
+{
+ 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 = generic_unmangle_name,
+ .load_config = vfat_load_config,
+ .opendir = vfat_opendir,
+ .readdir = vfat_readdir
+};
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 <stdint.h>
+
+#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..e060b13d
--- /dev/null
+++ b/core/fs/iso9660/iso9660.c
@@ -0,0 +1,536 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include "iso9660_fs.h"
+
+#define DEBUG 1
+
+#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 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 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, const char *src)
+{
+ char *p = dst;
+ int i = FILENAME_MAX - 1;
+
+ while (not_whitespace(*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 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.
+ * @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);
+}
+
+/**
+ * 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 file *gfile, char *buf,
+ int sectors, bool *have_more)
+{
+ uint32_t bytes_read = sectors << ISO_SECTOR_SHIFT;
+ 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;
+}
+
+
+
+/*
+ * 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;
+ 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;
+ bool have_more;
+
+ file = allocate_file();
+ if ( !file )
+ return 0;
+
+ file->file_left = dir->dir_clust;
+ file->file_sector = dir->dir_lba;
+
+ 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 )
+ return 0;
+
+ 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++;
+ if ( offset ) {
+ if ( !have_more )
+ return 0;
+ 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
+ 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;
+ }
+}
+
+
+/*
+ * 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
+}
+
+/* Load the config file, return 1 if failed, or 0 */
+static int iso_load_config(void)
+{
+ char *config_name = "isolinux.cfg";
+ com32sys_t regs;
+
+ memset(&regs, 0, sizeof regs);
+ strcpy(ConfigName, config_name);
+ regs.edi.w[0] = OFFS_WRT(ConfigName, 0);
+ call16(core_open, &regs, &regs);
+
+ return !!(regs.eflags.l & EFLAGS_ZF);
+}
+
+
+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 = generic_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 <stdint.h>
+
+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/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 <string.h>
+#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/dhcp_option.c b/core/fs/pxe/dhcp_option.c
new file mode 100644
index 00000000..7935f8ba
--- /dev/null
+++ b/core/fs/pxe/dhcp_option.c
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <sys/cpu.h>
+#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)
+{
+ if (opt_len != 4)
+ return;
+ net_mask = *(uint32_t *)data;
+}
+
+static void router(void *data, int opt_len)
+{
+ if (opt_len != 4)
+ return;
+ gate_way = *(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++) {
+ 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)
+{
+ char *p = (char *)data + opt_len;
+ char *ld = LocalDomain;
+ char end = *p;
+
+ *p = '\0'; /* Zero-terminate option */
+ dns_mangle(&ld, data);
+ *p = end; /* Restore 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;
+ over_load = *(uint8_t *)data;
+}
+
+
+static void server(void *data, int opt_len)
+{
+ uint32_t ip;
+
+ if (opt_len != 4)
+ return;
+
+ if (server_ip)
+ return;
+
+ ip = *(uint32_t *)data;
+ if (ip_ok(ip))
+ server_ip = ip;
+}
+
+static void client_identifier(void *data, int opt_len)
+{
+ if (opt_len > MAC_MAX || opt_len < 2 ||
+ MAC_len != (opt_len >> 8) ||
+ *(uint8_t *)data != MAC_type)
+ return;
+
+ opt_len --;
+ 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(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 | have_uuid))
+ return;
+
+ have_uuid = 1;
+ uuid_type = 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(path_prefix, data, opt_len);
+ path_prefix[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
+ ; 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
+ ; MAC_len, MAC - Client identifier, if MAC_len == 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;
+
+ over_load = 0;
+ if (ip_ok(dhcp->yip))
+ MyIP = dhcp->yip;
+
+ if (ip_ok(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 (over_load & 1)
+ parse_dhcp_options(&dhcp->bootfile, 128, 0);
+ else if (dhcp->bootfile[0])
+ strcpy(boot_file, dhcp->bootfile);
+
+ 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
new file mode 100644
index 00000000..98bc960e
--- /dev/null
+++ b/core/fs/pxe/dnsresolv.c
@@ -0,0 +1,341 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#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
+ */
+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, *dst is updated.
+ */
+int dns_mangle(char **dst, const char *p)
+{
+ char *q = *dst;
+ char *count_ptr;
+ char c;
+ int dots = 0;
+
+ count_ptr = q;
+ *q++ = 0;
+
+ while (1) {
+ c = *p++;
+ if (c == 0 || c == ':')
+ break;
+ if (c == '.') {
+ dots++;
+ count_ptr = q;
+ *q++ = 0;
+ continue;
+ }
+
+ *count_ptr += 1;
+ *q++ = c;
+ }
+
+ if (*count_ptr)
+ *q++ = 0;
+
+ /* update the strings */
+ *dst = q;
+ return dots;
+}
+
+
+/*
+ * 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 void *s1, const void *s2, const void *buf)
+{
+ const uint8_t *q = s1;
+ const uint8_t *p = s2;
+ 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 */
+ 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;
+ }
+ }
+}
+
+/*
+ * Skip past a DNS label set in DS:SI
+ */
+static char *dns_skiplabel(char *label)
+{
+ uint8_t c;
+
+ while (1) {
+ c = *label++;
+ if (c >= 0xc0)
+ return ++label; /* pointer is two bytes */
+ if (c == 0)
+ return label;
+ label += 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(const char *name)
+{
+ static char __lowmem DNSSendBuf[PKTBUF_SIZE];
+ static char __lowmem DNSRecvBuf[PKTBUF_SIZE];
+ 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 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 */
+ 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(TYPE_A);
+ query->qclass = htons(CLASS_IN);
+ p += sizeof(struct dnsquery);
+
+ /* Now send it to name server */
+ timeout_ptr = TimeoutTable;
+ 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 */
+ udp_write.status = 0;
+ udp_write.ip = srv;
+ 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;
+ udp_write.buffer = FAR_PTR(DNSSendBuf);
+ err = pxe_call(PXENV_UDP_WRITE, &udp_write);
+ if (err || udp_write.status != 0)
+ continue;
+
+ oldtime = BIOS_timer;
+ while (1) {
+ 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 = FAR_PTR(DNSRecvBuf);
+ err = pxe_call(PXENV_UDP_READ, &udp_read);
+ if (err || udp_read.status)
+ continue;
+
+ /* Got a packet, deal with it... */
+ if (hd2->id == hd1->id)
+ break;
+
+ 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;
+
+ 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(DNSSendBuf + sizeof(struct dnshdr),
+ p, DNSRecvBuf);
+ p = dns_skiplabel(p);
+ rr = (struct dnsrr *)p;
+ 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;
+ }
+
+ 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 */
+
+ again:
+ continue;
+ }
+
+ return 0;
+}
+
+
+/*
+ * the one should be called from ASM file
+ */
+void pxe_dns_resolv(com32sys_t *regs)
+{
+ const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
+
+ regs->eax.l = dns_resolv(name);
+}
diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c
new file mode 100644
index 00000000..73379fe6
--- /dev/null
+++ b/core/fs/pxe/idle.c
@@ -0,0 +1,109 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <fs.h>
+#include <minmax.h>
+#include <sys/cpu.h>
+#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 = FAR_PTR(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
new file mode 100644
index 00000000..f3c9bf30
--- /dev/null
+++ b/core/fs/pxe/pxe.c
@@ -0,0 +1,1549 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include <fs.h>
+#include <minmax.h>
+#include <sys/cpu.h>
+#include "pxe.h"
+
+#define GPXE 1
+
+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 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,
+ 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 */
+};
+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 in _file_.
+ */
+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 _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 */
+ (ip & 0xff) == 0 || /* Refuse network zero */
+ (ip & 0xff) == 0xff || /* Refuse loopback */
+ (ip & 0xf0) == 0xe0 ) /* Refuse class D */
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * 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.
+ *
+ */
+static 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 const char *parse_dotquad(const char *ip_str, uint32_t *res)
+{
+ const 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 regs;
+
+#if 0
+ printf("pxe_call op %04x data %p\n", opcode, data);
+#endif
+
+ memset(&regs, 0, sizeof regs);
+ regs.ebx.w[0] = opcode;
+ regs.es = SEG(data);
+ regs.edi.w[0] = OFFS(data);
+ call16(pxenv, &regs, &regs);
+
+ return regs.eflags.l & EFLAGS_CF; /* CF SET if 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 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) & net_mask) ? gate_way : 0;
+ udp_write.buffer = FAR_PTR(ack_packet_buf);
+ udp_write.buffer_size = 4;
+
+ err = pxe_call(PXENV_UDP_WRITE, &udp_write);
+#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 s_PXENV_GET_CACHED_INFO get_cached_info;
+ printf(" %02x", type);
+
+ get_cached_info.Status = 0;
+ get_cached_info.PacketType = type;
+ get_cached_info.BufferSize = 8192;
+ 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);
+ kaboom();
+ }
+
+ return get_cached_info.BufferSize;
+}
+
+
+
+#if GPXE
+
+/*
+ * Return 1 if and only if the buffer pointed to by
+ * url is a URL (contains ://)
+ *
+ */
+static int is_url(const 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 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;
+
+ 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, &api_check);
+ if (err || api_check.Magic != 0xe9c17b20)
+ printf("%s\n", gpxe_warning_msg);
+ else
+ has_gpxe = (~api_check.Provider & 0xffff) & 0x4b ? 0 : 1;
+
+ if (!has_gpxe)
+ printf("%s\n", gpxe_warning_msg);
+ }
+
+ return has_gpxe == 1;
+}
+
+/**
+ * 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 s_PXENV_FILE_READ file_read;
+ int err;
+
+ while (1) {
+ 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 (file_read.Status != PXENV_STATUS_TFTP_OPEN)
+ kaboom();
+ }
+
+ file->tftp_bytesleft = file_read.BufferSize;
+ file->tftp_filepos += file_read.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, &file_read);
+}
+#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, const char *src)
+{
+ const char *p = src;
+ uint32_t ip = server_ip;
+ int i = 0;
+
+#if GPXE
+ if (is_url(src)) {
+ ip = -1;
+ goto store;
+ }
+#endif
+
+ 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 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)) {
+ p += 2;
+ } else {
+ ip = dns_resolv(p);
+ if (ip && (p = strchr(p, ':')) && p[1] == ':') {
+ p += 2;
+ } else {
+ /* no ip, too */
+ p = src;
+ ip = 0;
+ }
+ }
+ }
+
+ store:
+ *(uint32_t *)dst = ip;
+ dst += 4;
+ i = FILENAME_MAX - 5;
+
+ do {
+ if (!not_whitespace(*p))
+ break;
+ *dst++ = *p++;
+ } while (i--);
+
+ i++;
+ while (i) {
+ *dst++ = 0;
+ i--;
+ }
+}
+
+
+/*
+ * 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.
+ */
+static char *pxe_unmangle_name(char *dst, const 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;
+ return stpcpy(dst, 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!
+ */
+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 s_PXENV_UDP_READ udp_read;
+
+ 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) {
+ 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;
+
+ BIOS_timer = old_time;
+ timeout--; /* decrease one timer tick */
+ if (!timeout) {
+ timeout = *timeout_ptr++;
+ if (!timeout)
+ break;
+ }
+ continue;
+ }
+
+ if (udp_read.buffer_size < 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)
+ kaboom();
+
+ 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 = udp_read.buffer_size - 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;
+}
+
+
+/**
+ * Open a TFTP connection to the server
+ *
+ * @param:filename, the file we wanna open
+ *
+ * @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)
+{
+ static __lowmem char tftp_proto_err[32];
+ char *buf = packet_buf;
+ char *p = filename;
+ char *options;
+ char *data;
+ struct open_file_t *open_file;
+ 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;
+ 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:
+ udp_write.buffer.offs = OFFS_WRT(buf, 0);
+ udp_write.buffer.seg = 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, path_prefix);
+ buf += strlen(path_prefix);
+ ip = server_ip; /* 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)) {
+ 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 = file_open.FileHandle;
+ get_file_size.FileHandle = file_open.FileHandle;
+
+#if 0
+ err = pxe_call(PXENV_GET_FILE_SIZE, &get_file_size);
+ if (!err)
+ open_file->tftp_filesize = get_file_size.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) */
+ udp_write.ip = ip;
+ udp_write.gw = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+ udp_write.src_port = tid;
+ 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);
+ 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
+ * 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;
+ 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;
+ timeout --; /* Decrease one timer tick */
+ if (!timeout)
+ goto failure;
+ }
+
+ /* Make sure the packet actually came from the server */
+ if (udp_read.src_ip == open_file->tftp_remoteip)
+ break;
+ }
+
+ /* Got packet; reset timeout */
+ timeout_ptr = TimeoutTable;
+ 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 = udp_read.buffer_size - 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:
+ /* 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 = 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");
+ kaboom();
+
+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(path_prefix, boot_file);
+ len = strlen(path_prefix);
+ p = &path_prefix[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("TFTP prefix: %s\n", path_prefix);
+ strcpy(CurrentDirName, path_prefix);
+}
+
+ /*
+ * try to load a config file, if found, return 1, or return 0
+ *
+ */
+static int try_load(char *config_name)
+{
+ com32sys_t regs;
+
+ printf("Trying to load: %-50s ", config_name);
+ pxe_mangle_name(KernelName, config_name);
+
+ memset(&regs, 0, sizeof regs);
+ 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 the config file, return 1 if failed, or 0 */
+static int pxe_load_config(void)
+{
+ const char *cfgprefix = "pxelinux.cfg/";
+ const char *default_str = "default";
+ char *config_file;
+ char *last;
+ char *p;
+ uint8_t *uuid_ptr;
+ int tries = 8;
+
+ get_prefix();
+ if (DHCPMagic & 0x02) {
+ /* We got a DHCP option, try it first */
+ if (try_load(boot_file))
+ return 0;
+ }
+
+ /*
+ * 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;
+ 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';
+ if (try_load(ConfigName))
+ return 0;
+ }
+
+ /* Try loading by MAC address */
+ strcpy(config_file, MAC_str);
+ 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 */
+ if (try_load(ConfigName))
+ return 0;
+ last--; /* Drop one character */
+ tries--;
+ };
+
+ /* Final attempt: "default" string */
+ strcpy(config_file, default_str);
+ if (try_load(ConfigName))
+ return 0;
+
+ printf("Unable to locate configuration file\n");
+ kaboom();
+}
+
+/*
+ * Generate the botif string, and the hardware-based config string
+ */
+static void make_bootif_string(void)
+{
+ 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;
+ src += 1;
+ *dst++ = '-';
+ }
+ *(dst - 1) = 0; /* Drop the last '-' and null-terminate string */
+ strcat(BOOTIFStr, "BOOTIF=");
+ strcat(BOOTIFStr, MAC_str);
+
+#if 0
+ printf("%s\n", BOOTIFStr);
+#endif
+}
+/*
+ * Generate an ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
+ * option into IPOption based on a DHCP packet in trackbuf.
+ *
+ */
+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, server_ip);
+ p += ip_len;
+ *p++ = ':';
+
+ ip_len = gendotquad(p, gate_way);
+ p += ip_len;
+ *p++ = ':';
+
+ ip_len = gendotquad(p, net_mask);
+}
+
+
+/* Generate ip= option and print the ip adress */
+static void ip_init(void)
+{
+ uint32_t ip = MyIP;
+
+ genipopt();
+ gendotquad(dot_quad_buf, ip);
+
+ ip = ntohl(ip);
+ printf("My IP address seems to be %08X %s\n", ip, dot_quad_buf);
+ 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.
+ *
+ * return the corresponding pxe structure if found, or NULL;
+ */
+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(&regs, 0, sizeof regs);
+ regs.eax.w[0] = 0x5650;
+ call16(pxe_int1a, &regs, &regs);
+ 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("No !PXE or PXENV+ API found; we're dead...\n");
+ kaboom();
+
+ 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);
+
+ real_base_mem = max(code_seg,data_seg) >> 6; /* Convert to kilobytes */
+}
+
+/*
+ * Initialize UDP stack
+ *
+ */
+static void udp_init(void)
+{
+ int err;
+ 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", udp_open.status);
+ kaboom();
+ }
+}
+
+
+/*
+ * 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("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.
+ */
+ *(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
+ */
+ 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
+ * 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();
+
+ /* Initialize network-card-specific idle handling */
+ pxe_idle_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;
+
+ pxe_idle_cleanup();
+
+ 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 (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 >= real_base_mem || int_addr < BIOS_fbm) {
+ BIOS_fbm = real_base_mem;
+ 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",
+ .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..8a2b190c
--- /dev/null
+++ b/core/fs/pxe/pxe.h
@@ -0,0 +1,225 @@
+/* -----------------------------------------------------------------------
+ *
+ * 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 <syslinux/pxe_api.h>
+#include "fs.h" /* For MAX_OPEN, should go away */
+
+/*
+ * Some basic defines...
+ */
+#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'))
+#define major_ver(v) (((v) >> 8) && 0xff)
+
+/*
+ * 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
+
+/* 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
+ */
+
+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));
+
+/*
+ * 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 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
+ */
+
+/* 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 **, 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/getc.inc b/core/getc.inc
index a8d54c7f..48b9f774 100644
--- a/core/getc.inc
+++ b/core/getc.inc
@@ -60,8 +60,9 @@ getc_file_lg2 equ 4 ; Size of getc_file as a power of 2
;
; close: Output: CF set if nothing open
;
-open:
- call searchdir
+ global core_open
+core_open:
+ pm_call searchdir
jz openfd.ret
openfd:
push bx
@@ -82,11 +83,11 @@ openfd:
.ret: ret
.stack_full:
- call close_file
+ pm_call close_file
xor ax,ax ; ZF <- 1
pop bx
ret
-
+
getc:
push bx
push si
@@ -135,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
@@ -177,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/hello.c b/core/hello.c
index a4fff7ad..a1591111 100644
--- a/core/hello.c
+++ b/core/hello.c
@@ -1,5 +1,8 @@
#include <stddef.h>
#include <com32.h>
+#include <stdio.h>
+#include <string.h>
+
void myputchar(int c)
{
@@ -21,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/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/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 <stdint.h>
+#include <com32.h>
+#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/core.h b/core/include/core.h
index e61bf998..c13aa16f 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -6,13 +6,42 @@
extern char core_xfer_buf[65536];
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);
+
+/* 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);
+extern const com32sys_t zero_regs;
void call16(void (*)(void), const com32sys_t *, com32sys_t *);
+/*
+ * __lowmem is in the low 1 MB; __bss16 in the low 64K
+ */
#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()
+
#endif /* CORE_H */
diff --git a/core/include/disk.h b/core/include/disk.h
new file mode 100644
index 00000000..91f7a57a
--- /dev/null
+++ b/core/include/disk.h
@@ -0,0 +1,40 @@
+#ifndef DISK_H
+#define DISK_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define SECTOR_SHIFT 9
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+
+typedef uint64_t sector_t;
+typedef uint64_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(struct disk *, 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
new file mode 100644
index 00000000..df103023
--- /dev/null
+++ b/core/include/fs.h
@@ -0,0 +1,100 @@
+#ifndef FS_H
+#define FS_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <com32.h>
+#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)
+
+#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;
+};
+
+struct open_file_t; /* Filesystem private structure */
+struct dirent; /* Directory entry structure */
+
+struct file {
+ 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 */
+ const char *fs_name;
+ enum fs_flags fs_flags;
+
+ int (*fs_init)(struct fs_info *);
+ void (*searchdir)(char *, struct file *);
+ uint32_t (*getfssec)(struct file *, char *, int, bool *);
+ void (*close_file)(struct file *);
+ void (*mangle_name)(char *, const char *);
+ char * (*unmangle_name)(char *, const char *);
+ int (*load_config)();
+
+ /* the _dir_ stuff */
+ void (*opendir)(com32sys_t *);
+ struct dirent * (*readdir)(struct file *);
+};
+
+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:
+ * the pointer points to the disk structure,
+ * the cache stuff.
+ */
+struct device {
+ struct disk *disk;
+
+ /* the cache stuff */
+ char* cache_data;
+ void* cache_head;
+ uint16_t cache_block_size;
+ uint16_t cache_entries;
+ uint32_t cache_size;
+};
+
+/*
+ * Our definition of "not whitespace"
+ */
+static inline bool not_whitespace(char c)
+{
+ return (unsigned char)c > ' ';
+}
+
+/*
+ * functions
+ */
+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 */
diff --git a/core/init.inc b/core/init.inc
index ec8c7b3b..5617a697 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -34,19 +34,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
;
call comboot_setup_api
diff --git a/core/isolinux.asm b/core/isolinux.asm
index bbbee72a..b67bdc19 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -26,14 +26,10 @@
; 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?
%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)
@@ -72,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
; ---------------------------------------------------------------------------
@@ -86,6 +76,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
@@ -94,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)
@@ -190,10 +177,6 @@ dsp_dummy: resb 1 ; Scratch, safe to overwrite
_spec_end equ $
_spec_len equ _spec_end - _spec_start
- section .bss16
- 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
@@ -767,6 +750,7 @@ getonesec:
; ES:BX - Target buffer
; BP - Sector count
;
+ global getlinsec
getlinsec: jmp word [cs:GetlinsecPtr]
%ifndef DEBUG_MESSAGES
@@ -1099,6 +1083,7 @@ bios_ebios: dw getlinsec_ebios, bios_ebios_str
%endif
; Maximum transfer size
+ global MaxTransfer
MaxTransfer dw 127 ; Hard disk modes
MaxTransferCD dw 32 ; CD mode
@@ -1160,96 +1145,23 @@ 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]
+ cmp word [BIOSType],bios_cdrom
+ sete dh ; 1 for cdrom, 0 for hybrid mode
+ mov ecx,[bsHidden]
+ mov ebx,[bsHidden+4]
+ mov si,[bsHeads]
+ mov di,[bsSecPerTrack]
+ pm_call fs_init
+ popad
;
; Locate the configuration file
;
-load_config:
- pm_call load_env32
-%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
-
-%ifdef DEBUG_MESSAGES
- mov si,dbg_configok_msg
- call writemsg
-%endif
+ pm_call load_config
;
; Now we have the config file open. Parse the config file and
@@ -1290,7 +1202,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
@@ -1387,350 +1299,7 @@ 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
-; 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
-
-;
-; 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
@@ -1745,21 +1314,8 @@ getfssec:
; -----------------------------------------------------------------------------
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/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");
+}
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
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index c08799f4..20f0ee94 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -22,1398 +22,15 @@
;
; ****************************************************************************
-%ifndef IS_MDSLINUX
%define IS_SYSLINUX 1
-%endif
%include "head.inc"
;
; 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 equ (1<<FILENAME_MAX_LG2) ; Max mangled filename size
-NULLFILE equ 0 ; First char space == null 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)
+ extern vfat_fs_ops
+ROOT_FS_OPS equ vfat_fs_ops
-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
-; 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
-
-;
-; 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
-; ---------------------------------------------------------------------------
-
-;
-; Memory below this point is reserved for the BIOS and the MBR
-;
- section .earlybss
-trackbufsize equ 8192
-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
-
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
-
-;
-; Common bootstrap code for disk-based derivatives
-;
-%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
-;
- call initcache
-
-;
-; 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
-;
- 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 open
- pop di
- jnz .config_open
- mov di,syslinux_cfg2
- push di
- call open
- pop di
- jnz .config_open
- mov di,syslinux_cfg3
- push di
- call open
- pop di
- 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
-; run the user interface.
-;
-%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
- call getcachesector
- ; 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:
-; Deallocates a directory structure (pointer in SI)
-; Assumes CS == DS.
-;
-close_dir:
- and si,si
- jz .closed
- mov dword [si],0 ; First dword == file_sector
- 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 ; <A> 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 ; <A> 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:
- call getcachesector
-.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
-
-;
-;
-; 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
-
-;
-; 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
-; 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
-
-;
-; 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
- jmp getcachesector
-
-; -----------------------------------------------------------------------------
-; Common modules
-; -----------------------------------------------------------------------------
-
-%include "common.inc" ; Universal modules
-%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
-
-; -----------------------------------------------------------------------------
-; 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
-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
-;
-%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"
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 ; <C> 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 ; <C> Target buffer
pushf ; <C> EOF status
lea ebx,[edi+ecx] ; End of data
diff --git a/core/parsecmd.inc b/core/parsecmd.inc
index 7dfe1eb6..ab5a7df9 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/parseconfig.inc b/core/parseconfig.inc
index 02bc4bf8..af7d514f 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,8 +147,8 @@ pc_setint16:
pc_filecmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
- call mangle_name
- call searchdir
+ pm_call mangle_name
+ pm_call searchdir
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
@@ -160,8 +160,8 @@ pc_filecmd: push ax ; Function to tailcall
pc_opencmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
- call mangle_name
- call open
+ pm_call mangle_name
+ call core_open
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
@@ -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]
@@ -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/pxeidle.inc b/core/pxeidle.inc
deleted file mode 100644
index ef3e1b7f..00000000
--- a/core/pxeidle.inc
+++ /dev/null
@@ -1,122 +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 .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 f51e7cd6..5512e843 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -29,23 +29,10 @@
; 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
%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)
@@ -58,29 +45,6 @@ SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
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
-
-;
; 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
@@ -98,60 +62,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
@@ -161,57 +71,36 @@ 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
- section .bss16
- alignb open_file_t_size
-Files resb MAX_OPEN*open_file_t_size
+ ; These fields save information from before the time
+ ; .bss is zeroed... must be in .earlybss
+ global InitStack
+InitStack resd 1
+ section .bss16
alignb FILENAME_MAX
-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
-InitStack resd 1 ; Pointer to reset stack (SS:SP)
PXEStack resd 1 ; Saved stack during PXE call
alignb 4
+ global DHCPMagic, RebootTime, APIVer
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
-OverLoad resb 1 ; Set if DHCP packet uses "overloading"
DHCPMagic resb 1 ; PXELINUX magic flags
; The relative position of these fields matter!
-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!
-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
alignb 16
packet_buf resb 2048 ; Transfer packet
packet_buf_size equ $-packet_buf
@@ -277,329 +166,11 @@ _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
-
-;
-; 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+
-;
-; 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
-
- ; Plan C: PXENV+ structure via INT 1Ah AX=5650h
- inc byte [plan]
- 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
-
- 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:
+ extern pxe_fs_ops
+ mov eax,pxe_fs_ops
+ pm_call fs_init
;
; Common initialization code
@@ -607,9 +178,8 @@ udp_init:
%include "cpuinit.inc"
;
-; Detect NIC type and initialize the idle mechanism
+; Initialize the idle mechanism
;
- call pxe_detect_nic_type
call reset_idle
;
@@ -627,145 +197,9 @@ udp_init:
;
;
-; 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
@@ -775,7 +209,7 @@ config_scan:
; Unload PXE stack
%define HAVE_UNLOAD_PREP
%macro UNLOAD_PREP 0
- call unload_pxe
+ pm_call unload_pxe
%endmacro
;
@@ -814,6 +248,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 kaboom
kaboom:
RESET_STACK_AND_SEGS AX
.patch: mov si,bailmsg
@@ -848,759 +283,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:
- ; 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.
- cmp byte [si],0
- je .done_pkt
-
- 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 .done_pkt ; Ignore runt option
-.got_opt_name: ; si -> option value
- dec cx ; bytes left in pkt
- jz .done_pkt ; Option w/o value, ignore
-
- ; 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
- ; Non-negotiated option returned, no idea what it means...
- jmp .err_reply
-
-.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: ; TFTP protocol 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_proto_err
- mov word [pxe_udp_write_pkt.buffersize],tftp_proto_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
-; 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
- call gendotquad
- mov ax,'::'
- stosw
-.noip:
- call strcpy
- dec di ; Point to final null byte
- pop eax
- ret
;
; pxenv
@@ -1613,6 +295,7 @@ unmangle_name:
;
; While we're at it, save and restore all registers.
;
+ global pxenv
pxenv:
pushfd
pushad
@@ -1647,906 +330,32 @@ 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 ; <D> 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 ; <E> Timeout
- push dx ; <F> 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 ; <F> Old time
- pop cx ; <E> Timeout
- cmp ax,dx ; Same time -> don't advance timeout
- je .wait_data ; Same clock tick
- loop .wait_data ; Decrease timeout
-
- pop bx ; <D> Didn't get any, send another ACK
- inc bx
- cmp bx,TimeoutTableEnd
- jb .send_ack
- jmp kaboom ; Forget it...
-
-.recv_ok: pop dx ; <F>
- pop cx ; <E>
-
- 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 ; <D> 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)
-;
-; 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
-;
-; 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:
-;
-; 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
-
-;
-; 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
+; Invoke INT 1Ah on the PXE stack. This is used by the "Plan C" method
+; for finding the PXE entry point.
;
-; 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
+ 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
- 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=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
-; 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
@@ -2557,8 +366,6 @@ genipopt:
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
@@ -2571,36 +378,9 @@ 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
;
@@ -2619,144 +399,20 @@ 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_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
-
-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
-
-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
-
-%endif ; GPXE
-
-;
; Misc initialized (data) variables
;
section .data16
alignz 4
+ global BaseStack, KeepPXE
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?
;
-; 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
-;
-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
-ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet
-
-;
; IP information (initialized to "unknown" values)
-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
;
diff --git a/core/runkernel.inc b/core/runkernel.inc
index 8d0f2968..68ab9fac 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 ; <A> file pointer
- call getfssec
+ pm_call getfssec
cmp cx,1024
jb kernel_corrupt
cmp word [es:bs_bootsign],0AA55h
@@ -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
@@ -585,11 +585,11 @@ 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
- call searchdir ; Look for it in directory
+ pm_call searchdir ; Look for it in directory
pop edi
jz .notthere
diff --git a/core/syslinux.ld b/core/syslinux.ld
index 46017148..92ad3aa3 100644
--- a/core/syslinux.ld
+++ b/core/syslinux.ld
@@ -364,15 +364,17 @@ SECTIONS
/*
* We don't need .rel.dyn so put it here where we can simply
- * remove it.
+ * remove it. Putting it in /DISCARD/ doesn't work because it
+ * is linker-generated.
*/
.rel.dyn : {
*(.rel.dyn)
}
- /* No "interpreter" applicable */
+ /* Stuff we don't need... */
/DISCARD/ : {
*(.interp)
+ *(.eh_frame)
}
}
diff --git a/core/ui.inc b/core/ui.inc
index 3e42a97d..87d0c647 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
@@ -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
@@ -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
@@ -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
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:
diff --git a/extlinux/main.c b/extlinux/main.c
index 06306b39..0ab47539 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;
}
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"
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) */