From a131085a5bee10224241bfe9b46f85abe983b03f Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 26 Apr 2010 22:07:21 +0000 Subject: [PATCH] cd boot workaround for bioses that didn't want to boot >4 image sectors. boot is a normal binary with a.out again. use 'cdbootblock,' a CDBOOT variant of bootblock, both from bootblock.s, as the first boot image that then loads boot, exactly like the bootblock loads boot when booting from harddisk. the sector numbers (2048 byte iso sectors) are patched in by writeisofs, like installboot does for bootblock. bootblock unchanged. --- boot/Makefile | 19 +++--- boot/bootblock.s | 33 ++++++++-- boot/boothead.s | 26 ++++---- boot/installboot.c | 3 +- commands/simple/writeisofs.c | 117 +++++++++++++++++++++++++++++------ tools/release.sh | 15 ++++- 6 files changed, 164 insertions(+), 49 deletions(-) diff --git a/boot/Makefile b/boot/Makefile index 9ed477181..7c525438e 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -11,12 +11,15 @@ LD86 = $(CC86) -.o BIN = /usr/bin MDEC = /usr/mdec -all: bootblock boot edparams masterboot jumpboot installboot addaout +all: bootblock cdbootblock boot edparams masterboot jumpboot installboot addaout dos: boot.com mkfile.com bootblock: bootblock.s $(LD86) -com -o $@ bootblock.s +cdbootblock: bootblock.s + $(LD86) -com -o $@ bootblock.s -DCDBOOT + masterboot: masterboot.s $(LD86) -com -o $@ masterboot.s @@ -36,16 +39,8 @@ rawfs86.o: rawfs.c rawfs.o -cmp -s rawfs.o rawfs86.o && ln -f rawfs.o rawfs86.o boot: boothead.s boot.o bootimage.o rawfs86.o - $(LD86) -o bootexec \ - boothead.s boot.o bootimage.o rawfs86.o $(LIBS) - install -S 22kb bootexec - # This is code that is executed when used on a bootable - # CD, as its entry point is the start of the file then. - # It jumps over the a.out header into the part of the - # code in boothead.s where the code knows it's booting - # from CD if entered there. - ( printf '\xeb\x3e ' ; cat bootexec ) >boot - chmod 755 boot + $(LD86) -o boot boothead.s boot.o bootimage.o rawfs86.o $(LIBS) + install -S 22kb boot edparams.o: boot.c ln -f boot.c edparams.c @@ -119,5 +114,5 @@ $(BIN)/edparams: edparams clean: rm -f *.bak *.o - rm -f bootblock addaout installboot boot masterboot jumpboot edparams + rm -f cdbootblock bootblock addaout installboot boot masterboot jumpboot edparams rm -f dosboot boot.com mkfile mkfile.com diff --git a/boot/bootblock.s b/boot/bootblock.s index 77b187073..1c2b9edba 100644 --- a/boot/bootblock.s +++ b/boot/bootblock.s @@ -1,3 +1,4 @@ +# ! Bootblock 1.5 - Minix boot block. Author: Kees J. Bot ! 21 Dec 1991 ! @@ -18,15 +19,21 @@ LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded BOOTSEG = 0x1000 ! Secondary boot code segment. +#ifdef CDBOOT + BOOTOFF = 0x0050 ! Offset into /boot above header +#else BOOTOFF = 0x0030 ! Offset into /boot above header +#endif BUFFER = 0x0600 ! First free memory +#ifndef CDBOOT /* just constants, but make no sense for CDs */ LOWSEC = 8 ! Offset of logical first sector in partition ! table ! Variables addressed using bp register - device = 0 ! The boot device lowsec = 2 ! Offset of boot partition within drive secpcyl = 6 ! Sectors per cylinder = heads * sectors +#endif + device = 0 ! The boot device .text @@ -51,18 +58,21 @@ boot: mov di, #LOADOFF+sectors ! char *di = sectors; +#ifndef CDBOOT testb dl, dl ! Winchester disks if dl >= 0x80 jge floppy +#endif winchester: +#ifndef CDBOOT ! Get the offset of the first sector of the boot partition from the partition ! table. The table is found at es:si, the lowsec parameter at offset LOWSEC. eseg les ax, LOWSEC(si) ! es:ax = LOWSEC+2(si):LOWSEC(si) - mov lowsec+0(bp), ax ! Low 16 bits of partition's first sector - mov lowsec+2(bp), es ! High 16 bits of partition's first sector + mov lowsec+0(bp), ax ! Low 16 bits of partitions first sector + mov lowsec+2(bp), es ! High 16 bits of partitions first sector ! Get the drive parameters, the number of sectors is bluntly written into the ! floppy disk sectors/track array. @@ -72,8 +82,10 @@ winchester: andb cl, #0x3F ! cl = max sector number (1-origin) movb (di), cl ! Number of sectors per track incb dh ! dh = 1 + max head number (0-origin) +#endif jmp loadboot +#ifndef CDBOOT ! Floppy: ! Execute three read tests to determine the drive type. Test for each floppy ! type by reading the last sector on the first track. If it fails, try a type @@ -101,13 +113,16 @@ floppy: xorb ah, ah ! Reset drive jc next ! Error, try the next floppy type success:movb dh, #2 ! Load number of heads for multiply +#endif loadboot: ! Load /boot from the boot device +#ifndef CDBOOT movb al, (di) ! al = (di) = sectors per track mulb dh ! dh = heads, ax = heads * sectors mov secpcyl(bp), ax ! Sectors per cylinder = heads * sectors +#endif mov ax, #BOOTSEG ! Segment to load /boot into mov es, ax @@ -117,6 +132,7 @@ load: mov ax, 1(si) ! Get next sector number: low 16 bits movb dl, 3(si) ! Bits 16-23 for your up to 8GB partition xorb dh, dh ! dx:ax = sector within partition +#ifndef CDBOOT add ax, lowsec+0(bp) adc dx, lowsec+2(bp)! dx:ax = sector within drive cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit? @@ -136,13 +152,14 @@ load: movb al, (di) ! Sectors per track - Sector number (0-origin) subb al, ah ! = Sectors left on this track cmpb al, (si) ! Compare with # sectors to read - jbe read ! Can't read past the end of a cylinder? + jbe read ! Cant read past the end of a cylinder? movb al, (si) ! (si) < sectors left on this track read: push ax ! Save al = sectors to read movb ah, #0x02 ! Code for disk read (all registers in use now!) int 0x13 ! Call the BIOS for a read pop cx ! Restore al in cl jmp rdeval +#endif bigdisk: movb cl, (si) ! Number of sectors to read push si ! Save si @@ -161,6 +178,14 @@ rdeval: movb al, cl ! Restore al = sectors read addb bh, al ! bx += 2 * al * 256 (add bytes read) addb bh, al ! es:bx = where next sector must be read +#ifdef CDBOOT + addb bh, al ! For CDs, a sector is 2048 bytes, so + addb bh, al ! do this 6 more times to get byte count. + addb bh, al + addb bh, al + addb bh, al + addb bh, al +#endif add 1(si), ax ! Update address by sectors read adcb 3(si), ah ! Don't forget bits 16-23 (add ah = 0) subb (si), al ! Decrement sector count by sectors read diff --git a/boot/boothead.s b/boot/boothead.s index 8644799ee..03955aee3 100644 --- a/boot/boothead.s +++ b/boot/boothead.s @@ -46,25 +46,29 @@ .text -! We assume boot is always linked with a short (32 byte) a.out header and has -! 16 bytes of its own prefix, so 48 bytes to skip. bootblock jumps into us -! at offset 0x30, cd boot code at 0x40 - ! Set cs right - ! (skip short a.out header plus 16 byte preefix) - jmpf boot, LOADSEG+3 - .space 11 +! Set segment registers and stack pointer using the programs own header! +! The header is either 32 bytes (short form) or 48 bytes (long form). The +! bootblock will jump to address 0x10030 in both cases, calling one of the +! two jmpf instructions below. +! +! CD bootblock jumps to address 0x10050 in both cases. - ! entry point when booting from CD + jmpf boot, LOADSEG+3 ! Set cs right (skipping long a.out header) + .space 11 ! jmpf + 11 = 16 bytes + jmpf boot, LOADSEG+2 ! Set cs right (skipping short a.out header) + .space 11 ! jmpf + 11 = 16 bytes jmpf cdboot, LOADSEG+3 - .space 11 + .space 11 + jmpf cdboot, LOADSEG+2 + .space 11 cdboot: mov bx, #1 jmp commonboot boot: mov bx, #0 commonboot: - mov ax, #LOADSEG+1 + mov ax, #LOADSEG mov ds, ax ! ds = header movb al, a_flags @@ -129,7 +133,7 @@ sepID: mov _daddr+0, ax mov _daddr+2, dx push ds - mov ax, #LOADSEG+1 + mov ax, #LOADSEG mov ds, ax ! Back to the header once more mov ax, a_total+0 mov dx, a_total+2 ! dx:ax = data + bss + heap + stack diff --git a/boot/installboot.c b/boot/installboot.c index 5b334bf68..17dc4f952 100644 --- a/boot/installboot.c +++ b/boot/installboot.c @@ -495,8 +495,7 @@ void make_bootable(enum howto how, char *device, char *bootblock, boothdr.a_magic[0]= !A_MAGIC0; } else { readblock(addr, buf, block_size); - /* Must skip 16 bytes of 'boot' as that contains code. */ - memcpy(&boothdr, buf + 16, sizeof(struct exec)); + memcpy(&boothdr, buf, sizeof(struct exec)); } bootf= NULL; dummy.process= boothdr; diff --git a/commands/simple/writeisofs.c b/commands/simple/writeisofs.c index 426f57e7e..0a66d9d95 100644 --- a/commands/simple/writeisofs.c +++ b/commands/simple/writeisofs.c @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include @@ -38,6 +40,7 @@ typedef unsigned long int u_int32_t; #define ISO_SECTOR 2048 #define VIRTUAL_SECTOR 512 +#define ROUNDUP(v, n) (((v)+(n)-1)/(n)) #define CURRENTDIR "." #define PARENTDIR ".." @@ -755,7 +758,7 @@ writebootcatalog(int fd, int *currentsector, int imagesector, int imagesectors) /* fill out the rest of the sector with 0's */ - if((rest = ISO_SECTOR - (written % 2048))) { + if((rest = ISO_SECTOR - (written % ISO_SECTOR))) { memset(buf, 0, sizeof(buf)); written += Write(fd, buf, rest); } @@ -766,23 +769,80 @@ writebootcatalog(int fd, int *currentsector, int imagesector, int imagesectors) } int -writebootimage(char *bootimage, int bootfd, int fd, int *currentsector) +writebootimage(char *bootimage, int bootfd, int fd, int *currentsector, + char *appendsectorinfo, struct node *root) { - static char buf[1024*64]; - ssize_t chunk, written = 0, rest; - int virtuals; + static unsigned char buf[1024*64], *addr; + ssize_t written = 0, rest; + int virtuals, rem; + struct exec hdr; + struct bap { + off_t sector; + int length; + } bap[2]; - while((chunk=read(bootfd, buf, sizeof(buf))) > 0) - written += Write(fd, buf, chunk); + bap[1].length = bap[1].sector = 0; - if(chunk < 0) { - perror("read boot image"); + Read(bootfd, &hdr, A_MINHDR); + + if(hdr.a_magic[0] != A_MAGIC0) { + fprintf(stderr, "bad magic in a.out of boot image.\n"); exit(1); } - virtuals = written / VIRTUAL_SECTOR; + if(hdr.a_hdrlen > sizeof(hdr)) { + fprintf(stderr, "surprisingly large header in boot image.\n"); + exit(1); + } - if((rest = ISO_SECTOR - (written % 2048))) { + /* read rest of a.out header. */ + Read(bootfd, (char *) &hdr + A_MINHDR, hdr.a_hdrlen - A_MINHDR); + + /* copy text+data */ + rem = hdr.a_text + hdr.a_data; + + while(rem > 0) { + int want; + want = rem < sizeof(buf) ? rem : sizeof(buf); + Read(bootfd, buf, want); + written += Write(fd, buf, want); + rem -= want; + } + + if(appendsectorinfo) { + struct node *n; + for(n = root->firstchild; n; n = n ->nextchild) { + if(!strcasecmp(appendsectorinfo, n->name)) { + bap[0].sector = n->startsector; + bap[0].length = ROUNDUP(n->bytesize, ISO_SECTOR); + break; + } + } + if(!n) { + fprintf(stderr, "%s not found in root.\n", + appendsectorinfo); + exit(1); + } + + fprintf(stderr, " * appended sector info: 0x%lx len 0x%lx\n", + bap[0].sector, bap[0].length); + } + + addr = buf; + addr[0] = bap[0].length; assert(addr[0] > 0); + addr[1] = (bap[0].sector >> 0) & 0xFF; + addr[2] = (bap[0].sector >> 8) & 0xFF; + addr[3] = (bap[0].sector >> 16) & 0xFF; + addr[4] = 0; + addr[5] = 0; + + /* Always save space for sector info after the boot image. */ + written += Write(fd, addr, 6); + + virtuals = ROUNDUP(written, VIRTUAL_SECTOR); + assert(virtuals * VIRTUAL_SECTOR >= written); + + if((rest = ISO_SECTOR - (written % ISO_SECTOR))) { memset(buf, 0, sizeof(buf)); written += Write(fd, buf, rest); } @@ -847,6 +907,7 @@ main(int argc, char *argv[]) int pvdsector; int bigpath, littlepath, pathbytes = 0, dirsector, filesector, enddir; int bootvolumesector, bootcatalogsector; + char *appendsectorinfo = NULL; prog = argv[0]; @@ -861,7 +922,7 @@ main(int argc, char *argv[]) return 1; } - while ((ch = getopt(argc, argv, "b:s:Rb:hl:nf")) != -1) { + while ((ch = getopt(argc, argv, "a:b:s:Rb:hl:nf")) != -1) { switch(ch) { case 's': if(optarg[0] != '0' || optarg[1] != 'x') { @@ -880,6 +941,10 @@ main(int argc, char *argv[]) case 'f': bootmedia= BOOTMEDIA_144M; break; + case 'a': + if(!(appendsectorinfo = strdup(optarg))) + exit(1); + break; case 'l': label = optarg; break; @@ -902,7 +967,7 @@ main(int argc, char *argv[]) /* Args check */ if(argc != 2) { - fprintf(stderr, "usage: %s [-l