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