aboutsummaryrefslogtreecommitdiffstats
path: root/libinstaller
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-20 15:21:05 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-20 15:21:05 -0700
commit8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa (patch)
tree3216feb1bbdae64b1ae471bbec982a667049017e /libinstaller
parent5b0d97899242fda7218db813bb2a8b9ebfbe4637 (diff)
downloadsyslinux-8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa.tar.gz
syslinux-8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa.tar.xz
syslinux-8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa.zip
Reduce sector 1 space pressure; further merge installer codesyslinux-4.00-pre52
Reduce sector 1 space pressure by moving objects that aren't needed by Sector 1 proper into an "extended patch area". While we're mucking with the installer code, make the syslxint and extlinux installer code even more similar. It should now be pretty straightforward to outright merge the code. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'libinstaller')
-rw-r--r--libinstaller/syslxint.h77
-rw-r--r--libinstaller/syslxmod.c162
2 files changed, 99 insertions, 140 deletions
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 53aa05dc..3af7c3d7 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -105,6 +105,56 @@ static inline void set_64(uint64_t *p, uint64_t v)
#endif
}
+/*
+ * Special handling for the MS-DOS derivative: syslinux_ldlinux
+ * is a "far" object...
+ */
+#ifdef __MSDOS__
+
+extern uint16_t ldlinux_seg; /* Defined in dos/syslinux.c */
+
+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 = ldlinux_seg + ((size_t) p >> 4);
+ asm volatile ("movw %0,%%fs"::"rm" (seg));
+ return (void *)((size_t) p & 0xf);
+}
+
+uint8_t get_8_sl(const uint8_t * p);
+uint16_t get_16_sl(const uint16_t * p);
+uint32_t get_32_sl(const uint32_t * p);
+uint64_t get_64_sl(const uint64_t * p);
+void set_8_sl(uint8_t * p, uint8_t v);
+void set_16_sl(uint16_t * p, uint16_t v);
+void set_32_sl(uint32_t * p, uint32_t v);
+void set_64_sl(uint64_t * p, uint64_t v);
+void memcpy_to_sl(void *dst, const void *src, size_t len);
+
+#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 get_64_sl(x) get_64(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)
+#define set_64_sl(x,y) set_64(x,y)
+#define memcpy_to_sl(d,s,l) memcpy(d,s,l)
+
+#endif
+
#define LDLINUX_MAGIC 0x3eb202fe
/* Patch area for disk-based installers */
@@ -116,13 +166,21 @@ struct patch_area {
uint32_t dwords;
uint32_t checksum;
uint16_t maxtransfer;
- uint16_t advptroffset;
- uint16_t diroffset;
- uint16_t dirlen;
- uint16_t subvoloffset;
- uint16_t subvollen;
- uint16_t secptroffset;
- uint16_t secptrcnt;
+ uint16_t epaoffset; /* Pointer to the extended patch area */
+};
+
+struct ext_patch_area {
+ uint16_t advptroffset; /* ADV pointers */
+ uint16_t diroffset; /* Current directory field */
+ uint16_t dirlen; /* Length of current directory field */
+ uint16_t subvoloffset; /* Subvolume field */
+ uint16_t subvollen; /* Length of subvolume field */
+ uint16_t secptroffset; /* Sector extent pointers */
+ uint16_t secptrcnt; /* Number of sector extent pointers */
+
+ uint16_t sect1ptr0; /* Boot sector offset of sector 1 ptr LSW */
+ uint16_t sect1ptr1; /* Boot sector offset of sector 1 ptr MSW */
+ uint16_t raidpatch; /* Boot sector RAID mode patch pointer */
};
/* Sector extent */
@@ -156,7 +214,7 @@ struct boot_sector {
uint32_t VolumeID;
char VolumeLabel[11];
char FileSysType[8];
- uint8_t Code[440];
+ uint8_t Code[448];
} __attribute__ ((packed)) bs16;
struct {
uint32_t FATSz32;
@@ -172,11 +230,10 @@ struct boot_sector {
uint32_t VolumeID;
char VolumeLabel[11];
char FileSysType[8];
- uint8_t Code[412];
+ uint8_t Code[420];
} __attribute__ ((packed)) bs32;
} __attribute__ ((packed));
- uint64_t NextSector; /* Pointer to the first unused sector */
uint16_t bsSignature;
} __attribute__ ((packed));
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index def4aaba..6f5adca5 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -129,115 +129,6 @@ const char *syslinux_check_bootsect(const void *bs)
}
/*
- * Special handling for the MS-DOS derivative: syslinux_ldlinux
- * is a "far" object...
- */
-#ifdef __MSDOS__
-
-#define __noinline __attribute__((noinline))
-
-extern uint16_t ldlinux_seg; /* Defined in dos/syslinux.c */
-
-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 = ldlinux_seg + ((size_t) p >> 4);
- asm volatile ("movw %0,%%fs"::"rm" (seg));
- return (void *)((size_t) p & 0xf);
-}
-
-#if 0 /* unused */
-static __noinline 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;
-}
-#endif
-
-static __noinline 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 __noinline 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;
-}
-
-#if 0 /* unused */
-static __noinline uint64_t get_64_sl(const uint64_t * p)
-{
- uint32_t v0, v1;
- const uint32_t *pp = (const uint32_t *)set_fs(p);
-
- asm volatile("movl %%fs:%1,%0" : "=r" (v0) : "m" (pp[0]));
- asm volatile("movl %%fs:%1,%0" : "=r" (v1) : "m" (pp[1]));
- return v0 + ((uint64_t)v1 << 32);
-}
-#endif
-
-#if 0 /* unused */
-static __noinline void set_8_sl(uint8_t * p, uint8_t v)
-{
- p = set_fs(p);
- asm volatile("movb %1,%%fs:%0":"=m" (*p):"qi"(v));
-}
-#endif
-
-static __noinline 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 __noinline void set_32_sl(uint32_t * p, uint32_t v)
-{
- p = set_fs(p);
- asm volatile("movl %1,%%fs:%0":"=m" (*p):"ri"(v));
-}
-
-static __noinline void set_64_sl(uint64_t * p, uint64_t v)
-{
- uint32_t *pp = (uint32_t *)set_fs(p);
- asm volatile("movl %1,%%fs:%0" : "=m" (pp[0]) : "ri"((uint32_t)v));
- asm volatile("movl %1,%%fs:%0" : "=m" (pp[1]) : "ri"((uint32_t)(v >> 32)));
-}
-
-#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 get_64_sl(x) get_64(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)
-#define set_64_sl(x,y) set_64(x,y)
-
-#endif
-
-/*
* Generate sector extents
*/
static void generate_extents(struct syslinux_extent *ex, int nptrs,
@@ -285,6 +176,14 @@ static void generate_extents(struct syslinux_extent *ex, int nptrs,
}
/*
+ * Form a pointer based on a 16-bit patcharea/epa field
+ */
+static inline void *ptr(void *img, uint16_t *offset_p)
+{
+ return (char *)img + get_16_sl(offset_p);
+}
+
+/*
* 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
@@ -301,33 +200,35 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
int stupid, int raid_mode, const char *subdir)
{
struct patch_area *patcharea;
+ struct ext_patch_area *epa;
struct syslinux_extent *ex;
uint32_t *wp;
int nsect = ((boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT) + 2;
uint32_t csum;
int i, dw, nptrs;
struct boot_sector *sbs = (struct boot_sector *)boot_sector;
- size_t diroffset, dirlen;
- int secptroffset;
uint64_t *advptrs;
if (nsectors < nsect)
return -1; /* The actual file is too small for content */
- /* Handle RAID mode, write proper bsSignature */
- i = get_16(&sbs->bsSignature);
- if (raid_mode)
- set_16((uint16_t *) ((char *)sbs + i), 0x18CD); /* INT 18h */
- set_16(&sbs->bsSignature, 0xAA55);
-
- /* First sector need pointer in boot sector */
- set_64(&sbs->NextSector, *sectp++);
-
/* Search for LDLINUX_MAGIC to find the patch area */
for (wp = (uint32_t *)boot_image; get_32_sl(wp) != LDLINUX_MAGIC;
wp++)
;
patcharea = (struct patch_area *)wp;
+ epa = ptr(boot_image, &patcharea->epaoffset);
+
+ /* First sector need pointer in boot sector */
+ set_32(ptr(sbs, &epa->sect1ptr0), sectp[0]);
+ set_32(ptr(sbs, &epa->sect1ptr1), sectp[0] >> 32);
+ sectp++;
+
+ /* Handle RAID mode */
+ if (raid_mode) {
+ /* Patch in INT 18h = CD 18 */
+ set_16(ptr(sbs, &epa->raidpatch), 0x18CD);
+ }
/* Set up the totals */
dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
@@ -338,13 +239,12 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
/* Handle Stupid mode */
if (stupid) {
/* Access only one sector at a time */
- set_16(&patcharea->maxtransfer, 1);
+ set_16_sl(&patcharea->maxtransfer, 1);
}
/* Set the sector extents */
- secptroffset = get_16_sl(&patcharea->secptroffset);
- ex = (struct syslinux_extent *) ((char *)boot_image + secptroffset);
- nptrs = get_16_sl(&patcharea->secptrcnt);
+ ex = ptr(boot_image, &epa->secptroffset);
+ nptrs = get_16_sl(&epa->secptrcnt);
if (nsect > nptrs) {
/* Not necessarily an error in this case, but a general problem */
@@ -356,20 +256,18 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
generate_extents(ex, nptrs, sectp, nsect-1-2);
/* ADV pointers */
- advptrs = (uint64_t *)((char *)boot_image +
- get_16_sl(&patcharea->advptroffset));
+ advptrs = ptr(boot_image, &epa->advptroffset);
set_64_sl(&advptrs[0], sectp[nsect-1-2]);
set_64_sl(&advptrs[1], sectp[nsect-1-1]);
/* Poke in the base directory path */
if (subdir) {
- diroffset = get_16(&patcharea->diroffset);
- dirlen = get_16(&patcharea->dirlen);
- if (dirlen <= strlen(subdir)) {
+ int sublen = strlen(subdir) + 1;
+ if (get_16_sl(&epa->dirlen) < sublen) {
fprintf(stderr, "Subdirectory path too long... aborting install!\n");
exit(1);
}
- memcpy((char *)boot_image + diroffset, subdir, strlen(subdir) + 1);
+ memcpy_to_sl(ptr(boot_image, &epa->diroffset), subdir, sublen);
}
/* Now produce a checksum */
@@ -381,5 +279,9 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
set_32_sl(&patcharea->checksum, csum);
+ /*
+ * Assume all bytes modified. This can be optimized at the expense
+ * of keeping track of what the highest modified address ever was.
+ */
return dw << 2;
}