aboutsummaryrefslogtreecommitdiffstats
path: root/extlinux
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 /extlinux
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 'extlinux')
-rw-r--r--extlinux/main.c127
1 files changed, 70 insertions, 57 deletions
diff --git a/extlinux/main.c b/extlinux/main.c
index 6ce3b605..cf9840dd 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -210,8 +210,8 @@ static void generate_extents(struct syslinux_extent *ex, int nptrs,
}
if (len) {
- set_64(&ex->lba, lba);
- set_16(&ex->len, len);
+ set_64_sl(&ex->lba, lba);
+ set_16_sl(&ex->len, len);
ex++;
}
@@ -225,13 +225,21 @@ static void generate_extents(struct syslinux_extent *ex, int nptrs,
}
if (len) {
- set_64(&ex->lba, lba);
- set_16(&ex->len, len);
+ set_64_sl(&ex->lba, lba);
+ set_16_sl(&ex->len, len);
ex++;
}
}
/*
+ * 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);
+}
+
+/*
* Query the device geometry and put it into the boot sector.
* Map the file and put the map in the boot sector and file.
* Stick the "current directory" inode number into the file.
@@ -246,12 +254,12 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
uint64_t totalbytes, totalsectors;
int nsect;
uint32_t *wp;
- struct boot_sector *bs;
+ struct boot_sector *sbs;
struct patch_area *patcharea;
+ struct ext_patch_area *epa;
struct syslinux_extent *ex;
int i, dw, nptrs;
uint32_t csum;
- int secptroffset, diroffset, dirlen, subvoloffset, subvollen;
char *dirpath, *subpath, *xdirpath, *xsubpath;
uint64_t *advptrs;
@@ -310,28 +318,20 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
early bootstrap share code with the FAT version. */
dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
- bs = (struct boot_sector *)boot_block;
+ sbs = (struct boot_sector *)boot_block;
totalsectors = totalbytes >> SECTOR_SHIFT;
if (totalsectors >= 65536) {
- set_16(&bs->bsSectors, 0);
+ set_16(&sbs->bsSectors, 0);
} else {
- set_16(&bs->bsSectors, totalsectors);
+ set_16(&sbs->bsSectors, totalsectors);
}
- set_32(&bs->bsHugeSectors, totalsectors);
+ set_32(&sbs->bsHugeSectors, totalsectors);
- set_16(&bs->bsBytesPerSec, SECTOR_SIZE);
- set_16(&bs->bsSecPerTrack, geo.sectors);
- set_16(&bs->bsHeads, geo.heads);
- set_32(&bs->bsHiddenSecs, geo.start);
-
- /* If we're in RAID mode then patch the appropriate instruction;
- either way write the proper boot signature */
- i = get_16(&bs->bsSignature);
- if (opt.raid_mode)
- set_16((uint16_t *) (boot_block + i), 0x18CD); /* INT 18h */
-
- set_16(&bs->bsSignature, 0xAA55);
+ set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
+ set_16(&sbs->bsSecPerTrack, geo.sectors);
+ set_16(&sbs->bsHeads, geo.heads);
+ set_32(&sbs->bsHiddenSecs, geo.start);
/* Construct the boot file */
@@ -351,27 +351,39 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
*(sectp + i) = BTRFS_EXTLINUX_OFFSET/SECTOR_SIZE + i;
}
- /* First sector need pointer in boot sector */
- set_64(&bs->NextSector, *sectp++);
-
/* Search for LDLINUX_MAGIC to find the patch area */
- for (wp = (uint32_t *) boot_image; get_32(wp) != LDLINUX_MAGIC; wp++) ;
+ 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 (opt.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 */
- set_16(&patcharea->data_sectors, nsect - 2); /* -2 for the ADVs */
- set_16(&patcharea->adv_sectors, 2);
- set_32(&patcharea->dwords, dw);
+ set_16_sl(&patcharea->data_sectors, nsect - 2); /* Not including ADVs */
+ set_16_sl(&patcharea->adv_sectors, 2); /* ADVs need 2 sectors */
+ set_32_sl(&patcharea->dwords, dw);
/* Stupid mode? */
- if (opt.stupid_mode)
- set_16(&patcharea->maxtransfer, 1);
+ if (opt.stupid_mode) {
+ /* Access only one sector at a time */
+ set_16_sl(&patcharea->maxtransfer, 1);
+ }
/* Set the sector extents */
- secptroffset = get_16(&patcharea->secptroffset);
- ex = (struct syslinux_extent *) ((char *)boot_image + secptroffset);
- nptrs = get_16(&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 */
@@ -383,38 +395,39 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
generate_extents(ex, nptrs, sectp, nsect-1-2);
/* ADV pointers */
- advptrs = (uint64_t *)((char *)boot_image +
- get_16(&patcharea->advptroffset));
- set_64(&advptrs[0], sectp[nsect-1-2]);
- set_64(&advptrs[1], sectp[nsect-1-1]);
+ 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 */
- diroffset = get_16(&patcharea->diroffset);
- dirlen = get_16(&patcharea->dirlen);
- if (dirlen <= strlen(subpath)) {
- fprintf(stderr, "Subdirectory path too long... aborting install!\n");
- exit(1);
+ if (subpath) {
+ int sublen = strlen(subpath) + 1;
+ if (get_16_sl(&epa->dirlen) < sublen) {
+ fprintf(stderr, "Subdirectory path too long... aborting install!\n");
+ exit(1);
+ }
+ memcpy_to_sl(ptr(boot_image, &epa->diroffset), subpath, sublen);
}
- strncpy((char *)boot_image + diroffset, subpath, dirlen);
free(dirpath);
- /* write subvol info if we have */
- subvoloffset = get_16(&patcharea->subvoloffset);
- subvollen = get_16(&patcharea->subvollen);
- if (subvollen <= strlen(subvol)) {
- fprintf(stderr, "Subvol name too long... aborting install!\n");
- exit(1);
+ /* Poke in the subvolume information */
+ if (1 /* subvol */) {
+ int sublen = strlen(subvol) + 1;
+ if (get_16_sl(&epa->subvollen) < sublen) {
+ fprintf(stderr, "Subvol name too long... aborting install!\n");
+ exit(1);
+ }
+ memcpy_to_sl(ptr(boot_image, &epa->subvoloffset), subvol, sublen);
}
- strncpy((char *)boot_image + subvoloffset, subvol, subvollen);
/* Now produce a checksum */
- set_32(&patcharea->checksum, 0);
+ set_32_sl(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
for (i = 0, wp = (uint32_t *) boot_image; 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);
/*
* Assume all bytes modified. This can be optimized at the expense
@@ -490,9 +503,9 @@ int install_bootblock(int fd, const char *device)
return 1;
}
if (fs_type == VFAT) {
- struct boot_sector *bs = (struct boot_sector *)extlinux_bootsect;
- if (xpwrite(fd, &bs->bsHead, bsHeadLen, 0) != bsHeadLen ||
- xpwrite(fd, &bs->bsCode, bsCodeLen,
+ struct boot_sector *sbs = (struct boot_sector *)extlinux_bootsect;
+ if (xpwrite(fd, &sbs->bsHead, bsHeadLen, 0) != bsHeadLen ||
+ xpwrite(fd, &sbs->bsCode, bsCodeLen,
offsetof(struct boot_sector, bsCode)) != bsCodeLen) {
perror("writing fat bootblock");
return 1;