Hi again, Here is a small update: The valloc() issue exists for other users of DJGPP, but with the patch I developed flashrom is not affected.
I'm attaching two patches, first is for the flashrom (fix_dos.patch) the only change from last time is fixed URL to the Pciutils-3.5.6.patch which someone needs to put on wiki. The old patch can be removed (http://flashrom.org/File:Pciutils.patch.gz) While at it, please also fix the "DOS" compilation page, or just point to README, where are the latest information. The second patch is a update for latest pciutils, it also fixes wrong endianess detection I had in the last patch. The lspci.exe now prints everything correctly, even with human readable strings ;) (if you put the pci.ids to :\share directory). I'm also disabling the interrupts while doing the PCI I/O, which I think is good idea. I will try to get Pciutils-3.5.6.patch patch into pciutils. The signed-off-line is for fix_dos.patch, the Pciutils-3.5.6.patch has its own. Signed-off-by: Rudolf Marek <[email protected]> Fix the documentation and DOS port. Update the DOS cross-compile documentation, and workaround issue with valloc() with the latest DJGPP. Thanks Rudolf
diff --git a/README b/README index ab761f7..0fbdd2d 100644 --- a/README +++ b/README @@ -95,30 +95,47 @@ To cross-compile on Linux for DOS: Get packages of the DJGPP cross compiler and install them: djgpp-filesystem djgpp-gcc djgpp-cpp djgpp-runtime djgpp-binutils As an alternative, the DJGPP web site offers packages for download as well: - djcross-binutils-2.19.1-10ap.i386.rpm - djcross-gcc-4.3.2-8ap.i686.rpm - djcrx-2.04pre_20090725-13ap.i386.rpm + djcross-binutils-2.29.1-1ap.x86_64.rpm + djcross-gcc-7.2.0-1ap.x86_64.rpm + djcrx-2.05-5.x86_64.rpm The cross toolchain packages for your distribution may have slightly different names (look for packages named *djgpp*). - You will need the following library source trees containing their compiled - static libraries either in the parent directory of the flashrom source or - specify the base folder on compile time with the LIBS_BASE parameter. - The default as described above is equal to calling - 'make djgpp-dos LIBS_BASE=..' + Alternatively, you could use a script to build it from scratch: + https://github.com/andrewwutw/build-djgpp + + You will need the libpci and libgetopt library source trees containing + their compiled static libraries and header files installed in some + directory say libpci-libgetopt/, which will be later specified with + LIBS_BASE parameter during flashrom compilation. Easiest way to + handle it is to put pciutils, libgetopt and flashrom directories + in one subdirectory. There will be extra subdirectory libpci-libgetopt + created, which will contain compiled libpci and libgetopt. + + Download pciutils 3.5.6 and apply http://flashrom.org/File:Pciutils-3.5.6.patch + Compile pciutils, using following command line: + + make ZLIB=no DNS=no HOST=i386-djgpp-djgpp CROSS_COMPILE=i586-pc-msdosdjgpp- \ + PREFIX=/ DESTDIR=$PWD/../libpci-libgetopt \ + STRIP="--strip-program=i586-pc-msdosdjgpp-strip -s" install install-lib + + Download and compile with 'make' http://flashrom.org/File:Libgetopt.tar.gz + + Copy the libgetopt.a to ../libpci-libgetopt/lib and + getopt.h to ../libpci-libgetopt/include - To get and build said libraries... - Download pciutils 3.1.5 and apply http://flashrom.org/File:Pciutils.patch.gz - Compile pciutils, see README.DJGPP for instructions. - Download and compile http://flashrom.org/File:Libgetopt.tar.gz Enter the flashrom directory. - Run either (change settings where appropriate) - make CC=i586-pc-msdosdjgpp-gcc STRIP=i586-pc-msdosdjgpp-strip - or (above settings hardcoded) - make djgpp-dos + + make CC=i586-pc-msdosdjgpp-gcc STRIP=i586-pc-msdosdjgpp-strip LIBS_BASE=../libpci-libgetopt/ strip + + If you like can compress the resulting executable with UPX: + + upx -9 flashrom.exe + To run flashrom.exe, download http://flashrom.org/File:Csdpmi7b.zip and unpack CWSDPMI.EXE into the current directory or one in PATH. + To cross-compile on Linux for Windows: Get packages of the MinGW cross compiler and install them: diff --git a/physmap.c b/physmap.c index a261ccd..3338b62 100644 --- a/physmap.c +++ b/physmap.c @@ -38,29 +38,40 @@ #ifdef __DJGPP__ #include <dpmi.h> +#include <malloc.h> #include <sys/nearptr.h> +#define ONE_MEGABYTE (1024 * 1024) #define MEM_DEV "dpmi" -static void *realmem_map; +static void *realmem_map_aligned; static void *map_first_meg(uintptr_t phys_addr, size_t len) { - if (realmem_map) - return realmem_map + phys_addr; + void *realmem_map; + size_t pagesize; - realmem_map = valloc(1024 * 1024); + if (realmem_map_aligned) + return realmem_map_aligned + phys_addr; + + /* valloc() from DJGPP 2.05 does not work properly */ + pagesize = getpagesize(); + + realmem_map = malloc(ONE_MEGABYTE + pagesize); if (!realmem_map) return ERROR_PTR; - if (__djgpp_map_physical_memory(realmem_map, (1024 * 1024), 0)) { + realmem_map_aligned = (void *)(((size_t) realmem_map + + (pagesize - 1)) & ~(pagesize - 1)); + + if (__djgpp_map_physical_memory(realmem_map_aligned, ONE_MEGABYTE, 0)) { free(realmem_map); - realmem_map = NULL; + realmem_map_aligned = NULL; return ERROR_PTR; } - return realmem_map + phys_addr; + return realmem_map_aligned + phys_addr; } static void *sys_physmap(uintptr_t phys_addr, size_t len) @@ -72,7 +83,7 @@ static void *sys_physmap(uintptr_t phys_addr, size_t len) if (!__djgpp_nearptr_enable()) return ERROR_PTR; - if ((phys_addr + len - 1) < (1024 * 1024)) { + if ((phys_addr + len - 1) < ONE_MEGABYTE) { /* We need to use another method to map first 1MB. */ return map_first_meg(phys_addr, len); } @@ -97,8 +108,8 @@ void sys_physunmap_unaligned(void *virt_addr, size_t len) /* There is no known way to unmap the first 1 MB. The DPMI server will * do this for us on exit. */ - if ((virt_addr >= realmem_map) && - ((virt_addr + len) <= (realmem_map + (1024 * 1024)))) { + if ((virt_addr >= realmem_map_aligned) && + ((virt_addr + len) <= (realmem_map_aligned + ONE_MEGABYTE))) { return; }
From 10436832ed28bf1cd43fb423367f00f7006f4e8a Mon Sep 17 00:00:00 2001 From: Rudolf Marek <[email protected]> Date: Fri, 29 Dec 2017 21:26:31 +0100 Subject: [PATCH] Add the support for a DOS/DJGPP environment * Add DJGPP as an OS target * Stop if endianess macros are not defined * Introduce new intel_io_lock/unclock function to synchronize I/O operations. Signed-off-by: Rudolf Marek <[email protected]> --- README | 1 + lib/configure | 6 +++++- lib/i386-io-beos.h | 8 ++++++++ lib/i386-io-cygwin.h | 8 ++++++++ lib/i386-io-djgpp.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ lib/i386-io-haiku.h | 8 ++++++++ lib/i386-io-hurd.h | 8 ++++++++ lib/i386-io-linux.h | 8 ++++++++ lib/i386-io-sunos.h | 8 ++++++++ lib/i386-io-windows.h | 8 ++++++++ lib/i386-ports.c | 49 ++++++++++++++++++++++++++++++++++++------------- lib/sysdep.h | 10 ++++++++++ lspci.h | 2 +- 13 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 lib/i386-io-djgpp.h diff --git a/README b/README index cd30a84..847d02c 100644 --- a/README +++ b/README @@ -27,6 +27,7 @@ In runs on the following systems: BeOS (via syscalls) Haiku (via /dev/misc/poke) Darwin (via IOKit) + DOS/DJGPP (via i386 ports) It should be very easy to add support for other systems as well (volunteers wanted; if you want to try that, I'll be very glad to see the patches and diff --git a/lib/configure b/lib/configure index 363f5b4..ff63816 100755 --- a/lib/configure +++ b/lib/configure @@ -120,7 +120,11 @@ case $sys in echo >>$m 'WITH_LIBS+=-lpci' LIBRESOLV= ;; - gnu) + gnu) + echo_n " i386-ports" + echo >>$c '#define PCI_HAVE_PM_INTEL_CONF' + ;; + djgpp) echo_n " i386-ports" echo >>$c '#define PCI_HAVE_PM_INTEL_CONF' ;; diff --git a/lib/i386-io-beos.h b/lib/i386-io-beos.h index a107a4e..a0ee6c9 100644 --- a/lib/i386-io-beos.h +++ b/lib/i386-io-beos.h @@ -57,3 +57,11 @@ outl (u32 value, u16 port) { write_isa_io(0, (void *)(u32)port, sizeof(value), value); } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-cygwin.h b/lib/i386-io-cygwin.h index 4af2f81..1602248 100644 --- a/lib/i386-io-cygwin.h +++ b/lib/i386-io-cygwin.h @@ -20,3 +20,11 @@ intel_cleanup_io(struct pci_access *a UNUSED) iopl(3); return -1; } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-djgpp.h b/lib/i386-io-djgpp.h new file mode 100644 index 0000000..41885db --- /dev/null +++ b/lib/i386-io-djgpp.h @@ -0,0 +1,45 @@ +/* + * The PCI Library -- Access to i386 I/O ports on DJGPP + * + * Copyright (c) 2010, 2017 Rudolf Marek <[email protected]> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include <pc.h> +#include <dos.h> +#define outb(x,y) outportb(y, x) +#define outw(x,y) outportw(y, x) +#define outl(x,y) outportl(y, x) + +#define inb inportb +#define inw inportw +#define inl inportl + +static int irq_enabled; + +static int +intel_setup_io(struct pci_access *a UNUSED) +{ + return 1; +} + +static inline int +intel_cleanup_io(struct pci_access *a UNUSED) +{ + return 1; +} + +static inline void intel_io_lock(void) +{ + asm volatile("" : : : "memory"); + irq_enabled = disable(); +} + +static inline void intel_io_unlock(void) +{ + asm volatile("" : : : "memory"); + if (irq_enabled) { + enable(); + } +} diff --git a/lib/i386-io-haiku.h b/lib/i386-io-haiku.h index 2a824f9..2bbe592 100644 --- a/lib/i386-io-haiku.h +++ b/lib/i386-io-haiku.h @@ -122,3 +122,11 @@ outl (u32 value, u16 port) port_io_args args = { POKE_SIGNATURE, port, sizeof(u32), value }; ioctl(poke_driver_fd, POKE_PORT_WRITE, &args, sizeof(args)); } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-hurd.h b/lib/i386-io-hurd.h index b61d656..d6df909 100644 --- a/lib/i386-io-hurd.h +++ b/lib/i386-io-hurd.h @@ -25,3 +25,11 @@ intel_cleanup_io(struct pci_access *a UNUSED) return -1; } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-linux.h b/lib/i386-io-linux.h index 1e52d73..b39b4eb 100644 --- a/lib/i386-io-linux.h +++ b/lib/i386-io-linux.h @@ -20,3 +20,11 @@ intel_cleanup_io(struct pci_access *a UNUSED) iopl(3); return -1; } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-sunos.h b/lib/i386-io-sunos.h index 3e08e73..6221d13 100644 --- a/lib/i386-io-sunos.h +++ b/lib/i386-io-sunos.h @@ -64,3 +64,11 @@ outl (u32 value, u16 port) { __asm__ __volatile__ ("outl (%w1)": :"a" (value), "Nd" (port)); } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-io-windows.h b/lib/i386-io-windows.h index 6e3dec0..d5823ee 100644 --- a/lib/i386-io-windows.h +++ b/lib/i386-io-windows.h @@ -67,3 +67,11 @@ intel_cleanup_io(struct pci_access *a UNUSED) //TODO: DeInitializeWinIo! return 1; } + +static inline void intel_io_lock(void) +{ +} + +static inline void intel_io_unlock(void) +{ +} diff --git a/lib/i386-ports.c b/lib/i386-ports.c index 421bbfd..0b1677a 100644 --- a/lib/i386-ports.c +++ b/lib/i386-ports.c @@ -26,6 +26,8 @@ #include "i386-io-haiku.h" #elif defined(PCI_OS_BEOS) #include "i386-io-beos.h" +#elif defined(PCI_OS_DJGPP) +#include "i386-io-djgpp.h" #else #error Do not know how to access I/O ports on this OS. #endif @@ -106,12 +108,16 @@ conf1_detect(struct pci_access *a) a->debug("...no I/O permission"); return 0; } + + intel_io_lock(); outb (0x01, 0xCFB); tmp = inl (0xCF8); outl (0x80000000, 0xCF8); if (inl (0xCF8) == 0x80000000) res = 1; outl (tmp, 0xCF8); + intel_io_unlock(); + if (res) res = intel_sanity_check(a, &pm_intel_conf1); return res; @@ -121,10 +127,12 @@ static int conf1_read(struct pci_dev *d, int pos, byte *buf, int len) { int addr = 0xcfc + (pos&3); + int res = 1; if (pos >= 256) return 0; + intel_io_lock(); outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8); switch (len) @@ -139,19 +147,23 @@ conf1_read(struct pci_dev *d, int pos, byte *buf, int len) ((u32 *) buf)[0] = cpu_to_le32(inl(addr)); break; default: - return pci_generic_block_read(d, pos, buf, len); + res = pci_generic_block_read(d, pos, buf, len); } - return 1; + + intel_io_unlock(); + return res; } static int conf1_write(struct pci_dev *d, int pos, byte *buf, int len) { int addr = 0xcfc + (pos&3); + int res = 1; if (pos >= 256) return 0; + intel_io_lock(); outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8); switch (len) @@ -166,9 +178,10 @@ conf1_write(struct pci_dev *d, int pos, byte *buf, int len) outl(le32_to_cpu(((u32 *) buf)[0]), addr); break; default: - return pci_generic_block_write(d, pos, buf, len); + res = pci_generic_block_write(d, pos, buf, len); } - return 1; + intel_io_unlock(); + return res; } /* @@ -178,6 +191,8 @@ conf1_write(struct pci_dev *d, int pos, byte *buf, int len) static int conf2_detect(struct pci_access *a) { + int res = 0; + if (!conf12_setup_io(a)) { a->debug("...no I/O permission"); @@ -186,18 +201,20 @@ conf2_detect(struct pci_access *a) /* This is ugly and tends to produce false positives. Beware. */ + intel_io_lock(); outb(0x00, 0xCFB); outb(0x00, 0xCF8); outb(0x00, 0xCFA); if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) - return intel_sanity_check(a, &pm_intel_conf2); - else - return 0; + res = intel_sanity_check(a, &pm_intel_conf2); + intel_io_unlock(); + return res; } static int conf2_read(struct pci_dev *d, int pos, byte *buf, int len) { + int res = 1; int addr = 0xc000 | (d->dev << 8) | pos; if (pos >= 256) @@ -206,6 +223,8 @@ conf2_read(struct pci_dev *d, int pos, byte *buf, int len) if (d->dev >= 16) /* conf2 supports only 16 devices per bus */ return 0; + + intel_io_lock(); outb((d->func << 1) | 0xf0, 0xcf8); outb(d->bus, 0xcfa); switch (len) @@ -220,16 +239,17 @@ conf2_read(struct pci_dev *d, int pos, byte *buf, int len) ((u32 *) buf)[0] = cpu_to_le32(inl(addr)); break; default: - outb(0, 0xcf8); - return pci_generic_block_read(d, pos, buf, len); + res = pci_generic_block_read(d, pos, buf, len); } outb(0, 0xcf8); - return 1; + intel_io_unlock(); + return res; } static int conf2_write(struct pci_dev *d, int pos, byte *buf, int len) { + int res = 1; int addr = 0xc000 | (d->dev << 8) | pos; if (pos >= 256) @@ -237,6 +257,8 @@ conf2_write(struct pci_dev *d, int pos, byte *buf, int len) if (d->dev >= 16) d->access->error("conf2_write: only first 16 devices exist."); + + intel_io_lock(); outb((d->func << 1) | 0xf0, 0xcf8); outb(d->bus, 0xcfa); switch (len) @@ -251,11 +273,12 @@ conf2_write(struct pci_dev *d, int pos, byte *buf, int len) outl(le32_to_cpu(* (u32 *) buf), addr); break; default: - outb(0, 0xcf8); - return pci_generic_block_write(d, pos, buf, len); + res = pci_generic_block_write(d, pos, buf, len); } + outb(0, 0xcf8); - return 1; + intel_io_unlock(); + return res; } struct pci_methods pm_intel_conf1 = { diff --git a/lib/sysdep.h b/lib/sysdep.h index b864e90..f3756b6 100644 --- a/lib/sysdep.h +++ b/lib/sysdep.h @@ -68,6 +68,16 @@ typedef u16 word; #endif #endif +#ifdef PCI_OS_DJGPP + #define BIG_ENDIAN 4321 + #define LITTLE_ENDIAN 1234 + #define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) +#error "BYTE_ORDER not defined for your platform" +#endif + #if BYTE_ORDER == BIG_ENDIAN #define cpu_to_le16 swab16 #define cpu_to_le32 swab32 diff --git a/lspci.h b/lspci.h index 9ef0919..bcd007e 100644 --- a/lspci.h +++ b/lspci.h @@ -14,7 +14,7 @@ * This increases our memory footprint, but only slightly since we don't * use alloca() much. */ -#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__DragonFly__) +#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__DragonFly__) || defined (__DJGPP__) /* alloca() is defined in stdlib.h */ #elif defined(__GNUC__) && !defined(PCI_OS_WINDOWS) #include <alloca.h> -- 2.7.4
_______________________________________________ flashrom mailing list [email protected] https://mail.coreboot.org/mailman/listinfo/flashrom
