aboutsummaryrefslogtreecommitdiffstats
path: root/libinstaller
diff options
context:
space:
mode:
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;
}