aboutsummaryrefslogtreecommitdiffstats
path: root/libinstaller
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-05-19 16:30:09 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-05-19 16:30:09 -0700
commit0fa4369624b4637a7e36ed22e89a759031f08327 (patch)
tree4aa1cf5c87d36153cee3c727d5f77498c0042983 /libinstaller
parentc9ad266f64f9ee81a859bdf70c1190ee0cc1bc19 (diff)
downloadlwip-0fa4369624b4637a7e36ed22e89a759031f08327.tar.gz
lwip-0fa4369624b4637a7e36ed22e89a759031f08327.tar.xz
lwip-0fa4369624b4637a7e36ed22e89a759031f08327.zip
FAT: change DOS installer to EXE; additional 32K limit fixes
Additional fixes for the 32K limits in the installers. In the case of the DOS installer, that means changing it from COM format to EXE format (since COM format has a 63K hard limit); retain the name syslinux.com for user compatibility, though (DOS doesn't care what the extension except for pathname search; if it finds an MZ EXE header it will use it.) With the change to EXE means having to handle more than one segment. Since we don't have a real DOS compiler we have to wing it a bit. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'libinstaller')
-rwxr-xr-xlibinstaller/bin2c.pl4
-rw-r--r--libinstaller/syslinux.h22
-rw-r--r--libinstaller/syslxint.h36
-rw-r--r--libinstaller/syslxmod.c120
4 files changed, 140 insertions, 42 deletions
diff --git a/libinstaller/bin2c.pl b/libinstaller/bin2c.pl
index 5a60ca9e..07c11ddb 100755
--- a/libinstaller/bin2c.pl
+++ b/libinstaller/bin2c.pl
@@ -69,10 +69,10 @@ if ($align != 0) {
}
}
-printf "\n};\n\nunsigned int %s_len = %u;\n", $table_name, $total_len;
+printf "\n};\n\nconst unsigned int %s_len = %u;\n", $table_name, $total_len;
@st = stat STDIN;
-printf "\nint %s_mtime = %d;\n", $table_name, $st[9];
+printf "\nconst int %s_mtime = %d;\n", $table_name, $st[9];
exit 0;
diff --git a/libinstaller/syslinux.h b/libinstaller/syslinux.h
index efffb7c0..e0554255 100644
--- a/libinstaller/syslinux.h
+++ b/libinstaller/syslinux.h
@@ -17,17 +17,21 @@
#include "advconst.h"
/* The standard boot sector and ldlinux image */
-extern unsigned char syslinux_bootsect[];
-extern unsigned int syslinux_bootsect_len;
-extern int syslinux_bootsect_mtime;
+extern unsigned char syslinux_bootsect[];
+extern const unsigned int syslinux_bootsect_len;
+extern const int syslinux_bootsect_mtime;
-extern unsigned char syslinux_ldlinux[];
-extern unsigned int syslinux_ldlinux_len;
-extern int syslinux_ldlinux_mtime;
+extern unsigned char syslinux_ldlinux[];
+extern const unsigned int syslinux_ldlinux_len;
+extern const int syslinux_ldlinux_mtime;
-extern unsigned char syslinux_mbr[];
-extern unsigned int syslinux_mbr_len;
-extern int syslinux_mbr_mtime;
+extern unsigned char syslinux_mbr[];
+extern const unsigned int syslinux_mbr_len;
+extern const int syslinux_mbr_mtime;
+
+/* Sector size assumptions... */
+#define SECTOR_BITS 9
+#define SECTOR_SIZE (1 << SECTOR_BITS)
/* This takes a boot sector and merges in the syslinux fields */
void syslinux_make_bootsect(void *);
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 3f50e32c..fc3932b2 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -20,16 +20,17 @@
*/
static inline uint8_t get_8(const uint8_t *p)
{
- return *(const uint8_t *)p;
+ return *p;
}
static inline uint16_t get_16(const uint16_t *p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint16_t *)p;
+ return *p;
#else
- return (uint16_t)p[0] + ((uint16_t)p[1] << 8);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint16_t)pp[0] + ((uint16_t)pp[1] << 8);
#endif
}
@@ -37,21 +38,28 @@ static inline uint32_t get_32(const uint32_t *p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
- return *(const uint32_t *)p;
+ return *p;
#else
- return (uint32_t)p[0] + ((uint32_t)p[1] << 8) +
- ((uint32_t)p[2] << 16) + ((uint32_t)p[3] << 24);
+ const uint8_t *pp = (const uint8_t *)p;
+ return (uint32_t)pp[0] + ((uint32_t)pp[1] << 8) +
+ ((uint32_t)pp[2] << 16) + ((uint32_t)pp[3] << 24);
#endif
}
+static inline void set_8(uint8_t *p, uint8_t v)
+{
+ *p = v;
+}
+
static inline void set_16(uint16_t *p, uint16_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
*(uint16_t *)p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
+ uint8_t *pp = (uint8_t *)p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
#endif
}
@@ -61,16 +69,14 @@ static inline void set_32(uint32_t *p, uint32_t v)
/* Littleendian and unaligned-capable */
*(uint32_t *)p = v;
#else
- p[0] = (v & 0xff);
- p[1] = ((v >> 8) & 0xff);
- p[2] = ((v >> 16) & 0xff);
- p[3] = ((v >> 24) & 0xff);
+ uint8_t *pp = (uint8_t *)p;
+ pp[0] = (v & 0xff);
+ pp[1] = ((v >> 8) & 0xff);
+ pp[2] = ((v >> 16) & 0xff);
+ pp[3] = ((v >> 24) & 0xff);
#endif
}
-#define SECTOR_SHIFT 9 /* 512-byte sectors */
-#define SECTOR_SIZE (1 << SECTOR_SHIFT)
-
#define LDLINUX_MAGIC 0x3eb202fe
/* Patch area for disk-based installers */
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index 1766de2b..78e226c4 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -121,6 +121,88 @@ const char *syslinux_check_bootsect(const void *bs)
}
/*
+ * Special handling for the MS-DOS derivative: syslinux_ldlinux
+ * is a "far" object...
+ */
+#ifdef __MSDOS__
+
+extern const char __payload_sseg[]; /* Symbol from linker */
+
+static inline __attribute__((const)) uint16_t ds(void)
+{
+ uint16_t v;
+ asm("movw %%ds,%0" : "=rm" (v));
+ return v;
+}
+
+static inline void *set_fs(const void *p)
+{
+ uint16_t seg;
+
+ seg = ds() + (size_t)__payload_sseg;
+ seg += (size_t)p >> 4;
+ asm volatile("movw %0,%%fs" : : "rm" (seg));
+ return (void *)((size_t)p & 0xf);
+}
+
+static inline uint8_t get_8_sl(const uint8_t *p)
+{
+ uint8_t v;
+
+ p = set_fs(p);
+ asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*p));
+ return v;
+}
+
+static inline uint16_t get_16_sl(const uint16_t *p)
+{
+ uint16_t v;
+
+ p = set_fs(p);
+ asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*p));
+ return v;
+}
+
+static inline uint32_t get_32_sl(const uint32_t *p)
+{
+ uint32_t v;
+
+ p = set_fs(p);
+ asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*p));
+ return v;
+}
+
+static inline void set_8_sl(uint8_t *p, uint8_t v)
+{
+ p = set_fs(p);
+ asm volatile("movb %1,%%fs:%0" : "=m" (*p) : "qi" (v));
+}
+
+static inline void set_16_sl(uint16_t *p, uint16_t v)
+{
+ p = set_fs(p);
+ asm volatile("movw %1,%%fs:%0" : "=m" (*p) : "ri" (v));
+}
+
+static inline void set_32_sl(uint32_t *p, uint32_t v)
+{
+ p = set_fs(p);
+ asm volatile("movl %1,%%fs:%0" : "=m" (*p) : "ri" (v));
+}
+
+#else
+
+/* Sane system ... */
+#define get_8_sl(x) get_8(x)
+#define get_16_sl(x) get_16(x)
+#define get_32_sl(x) get_32(x)
+#define set_8_sl(x,y) set_8(x,y)
+#define set_16_sl(x,y) set_16(x,y)
+#define set_32_sl(x,y) set_32(x,y)
+
+#endif
+
+/*
* This patches the boot sector and the beginning of ldlinux.sys
* based on an ldlinux.sys sector map passed in. Typically this is
* handled by writing ldlinux.sys, mapping it, and then overwrite it
@@ -128,7 +210,8 @@ const char *syslinux_check_bootsect(const void *bs)
* an OS which does block reallocation, then overwrite it with
* direct access since the location is known.
*
- * Return 0 if successful, otherwise -1.
+ * Returns the number of modified bytes in ldlinux.sys if successful,
+ * otherwise -1.
*/
int syslinux_patch(const uint32_t *sectors, int nsectors,
int stupid, int raid_mode)
@@ -137,7 +220,7 @@ int syslinux_patch(const uint32_t *sectors, int nsectors,
uint32_t *wp;
int nsect = (syslinux_ldlinux_len+511) >> 9;
uint32_t csum;
- int i, dw, nptrs;
+ int i, dw, nptrs, rv;
if ( nsectors < nsect )
return -1;
@@ -157,33 +240,38 @@ int syslinux_patch(const uint32_t *sectors, int nsectors,
set_32(&sbs->NextSector, *sectors++);
/* Search for LDLINUX_MAGIC to find the patch area */
- for (wp = (uint32_t *)syslinux_ldlinux; get_32(wp) != LDLINUX_MAGIC; wp++)
+ for (wp = (uint32_t *)syslinux_ldlinux; get_32_sl(wp) != LDLINUX_MAGIC; wp++)
;
patcharea = (struct patch_area *)wp;
/* Set up the totals */
dw = syslinux_ldlinux_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16(&patcharea->data_sectors, nsect); /* Not including ADVs */
- set_16(&patcharea->adv_sectors, 0); /* ADVs not supported yet */
- set_32(&patcharea->dwords, dw);
- set_32(&patcharea->currentdir, 0);
+ set_16_sl(&patcharea->data_sectors, nsect); /* Not including ADVs */
+ set_16_sl(&patcharea->adv_sectors, 0); /* ADVs not supported yet */
+ set_32_sl(&patcharea->dwords, dw);
+ set_32_sl(&patcharea->currentdir, 0);
/* Set the sector pointers */
- wp = (uint32_t *)((char *)syslinux_ldlinux+get_16(&patcharea->secptroffset));
- nptrs = get_16(&patcharea->secptrcnt);
+ wp = (uint32_t *)((char *)syslinux_ldlinux+get_16_sl(&patcharea->secptroffset));
+ nptrs = get_16_sl(&patcharea->secptrcnt);
+
+ while (nsect--) {
+ set_32_sl(wp++, *sectors++);
+ nptrs--;
+ }
+ while (nptrs--)
+ set_32_sl(wp++, 0);
- memset(wp, 0, nptrs*4);
- while ( nsect-- )
- set_32(wp++, *sectors++);
+ rv = (char *)wp - (char *)syslinux_ldlinux;
/* Now produce a checksum */
- set_32(&patcharea->checksum, 0);
+ set_32_sl(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
for (i = 0, wp = (uint32_t *)syslinux_ldlinux; i < dw; i++, wp++)
- csum -= get_32(wp); /* Negative checksum */
+ csum -= get_32_sl(wp); /* Negative checksum */
- set_32(&patcharea->checksum, csum);
+ set_32_sl(&patcharea->checksum, csum);
- return 0;
+ return rv;
}