fix the DOS port problems

Message ID 3669ee86-d690-d905-0ea5-803de68aaeb8@assembler.cz
State New
Headers show
Series
  • fix the DOS port problems
Related show

Commit Message

Rudolf Marek Dec. 29, 2017, 11:55 a.m.
Hi,

Attaching a patch which works around the valloc() issue in the DJGPP. 
Please apply before the flashrom 1.0. 

In the meanwhile, it would be great if someone could test it too,
if needed I will distribute the executable for a test to Rayer (on CC).

I will also try to get some help on DJGPP list, as this issue happens 
even with the official RPMs of DJGPP 2.05.

Signed-off-by: Rudolf Marek <r.marek@assembler.cz>

Fix the documentation and DOS port.

Update the DOS cross-compile documentation,
and workaround issue with valloc() with the
latest DJGPP.

Thanks
Rudolf

Comments

Rudolf Marek Dec. 29, 2017, 8:49 p.m. | #1
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 <r.marek@assembler.cz>

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 <r.marek@assembler.cz>
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 <r.marek@assembler.cz>
---
 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 <r.marek@assembler.cz>
+ *
+ *	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>
Nico Huber Dec. 29, 2017, 9:25 p.m. | #2
Hi Rudolf!

On 29.12.2017 21:49, Rudolf Marek wrote:
> 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.

I've pushed your original patch to gerrit [1] you can update it there or
I'll do it later. I've also uploaded the pciutils patch to the wiki,
though gzipped, like the old one [2].

For build tests, I've added a Docker image for djgpp [3], your README
update was much helpful ;) I'll try to review your DOS patch later.

> The old patch can be removed
> (http://flashrom.org/File:Pciutils.patch.gz)

Hmm, are you sure it's not useful anymore? I'd leave it there otherwise,
because a lot of older README checkouts point to it oO

Nico

[1] https://review.coreboot.org/23039/
[2] https://flashrom.org/File:Pciutils-3.5.6.patch.gz
[3] https://review.coreboot.org/23042/
Rudolf Marek Jan. 1, 2018, 7:33 p.m. | #3
Hi Nico,

Dne 29.12.2017 v 22:25 Nico Huber napsal(a):
>> The old patch can be removed
>> (http://flashrom.org/File:Pciutils.patch.gz)
> 
> Hmm, are you sure it's not useful anymore? I'd leave it there otherwise,
> because a lot of older README checkouts point to it oO

Ok, lets leave it as is.

In the meanwhile the DJGPP/DOS patch was accepted to pciutils tree.

https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/commit/?id=5c5ce19215cdfa54c878e09211e3cd3bc8344b82

Maybe we can just provide a link to that git or 3.5.7 once is out.

Thanks
Rudolf

Patch

diff --git a/README b/README
index ab761f7..b23b315 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.
 
- 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
+ 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
+
  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;
 	}