diff --git a/boot/Makefile b/boot/Makefile index 759fc5d5b..8aa0f3f6e 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -36,9 +36,16 @@ 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 $@ \ + $(LD86) -o bootexec \ boothead.s boot.o bootimage.o rawfs86.o $(LIBS) - install -S 8kb boot + install -S 12kb 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 edparams.o: boot.c ln -f boot.c edparams.c @@ -112,5 +119,5 @@ $(BIN)/edparams: edparams clean: rm -f *.bak *.o - rm -f bootblock addaout installboot boot masterboot jumpboot edparams + rm -f bootblock addaout installboot boot masterboot jumpboot edparams rm -f dosboot boot.com mkfile mkfile.com diff --git a/boot/boot.c b/boot/boot.c index 70fe45254..24dfb52b4 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -122,6 +122,44 @@ char *bios_err(int err) return "Unknown error"; } +/* CD's are addressed in 2048-byte sectors. + * In order to be able to read CD's but maintain the same interface of 512-byte + * sector addressing, we check if the device is a CD in readsectors() and if so, + * read it into our own buffer first + */ +int readsectors(u32_t bufaddr, u32_t sector, U8_t count) +{ +#define CDSECTOR_SIZE 2048 + static char cdbuf[CDSECTOR_SIZE]; + static i32_t cdbuf_sec = -1; + i32_t cdsec; + + if(device != cddevice) { + return biosreadsectors(bufaddr, sector, count); + } + + while(count > 0) { + u32_t offset; +#define FACTOR (CDSECTOR_SIZE/SECTOR_SIZE) + cdsec = sector / FACTOR; + offset = (sector % FACTOR) * SECTOR_SIZE; + if(cdsec != cdbuf_sec) { + int r; + if((r=biosreadsectors(mon2abs(cdbuf), cdsec, 1)) != 0) { + printf("error %d\n", r); + return r; + } + cdbuf_sec = cdsec; + } + raw_copy(bufaddr, mon2abs(cdbuf) + offset, SECTOR_SIZE); + bufaddr += SECTOR_SIZE; + count--; + sector++; + } + + return 0; +} + char *unix_err(int err) /* Translate the few errors rawfs can give. */ { @@ -515,6 +553,12 @@ void initialize(void) } #endif + /* If we were booted from CD, remember what device it was. */ + if(cdbooted) + cddevice = device; + else + cddevice = 0xff; /* Invalid. */ + /* Set the new caddr for relocate. */ caddr= newaddr; @@ -564,6 +608,14 @@ void initialize(void) readerr(masterpos, r); exit(1); } + /* If we're a CD, we know what we want. */ + if(device == cddevice) { + p = 1; /* We know this is the root FS. */ + lowsec = table[p]->lowsec; + bootdev.primary = p; + break; /* Found! */ + } + /* See if you can find "lowsec" back. */ for (p= 0; p < NR_PARTITIONS; p++) { if (lowsec - table[p]->lowsec < table[p]->size) break; @@ -590,12 +642,17 @@ void initialize(void) bootdev.primary= p; masterpos= table[p]->lowsec; } - strcpy(bootdev.name, "d0p0"); - bootdev.name[1] += (device - 0x80); - bootdev.name[3] += bootdev.primary; - if (bootdev.secondary >= 0) { - strcat(bootdev.name, "s0"); - bootdev.name[5] += bootdev.secondary; + + if(device == cddevice) { + strcpy(bootdev.name, CDNAME); + } else { + strcpy(bootdev.name, "d0p0"); + bootdev.name[1] += (device - 0x80); + bootdev.name[3] += bootdev.primary; + if (bootdev.secondary >= 0) { + strcat(bootdev.name, "s0"); + bootdev.name[5] += bootdev.secondary; + } } /* Find out about the video hardware. */ @@ -1087,7 +1144,7 @@ dev_t name2dev(char *name) n= name; if (strncmp(n, "/dev/", 5) == 0) n+= 5; - if (strcmp(n, "ram") == 0) { + if (strcmp(n, "ram") == 0 || strcmp(n, CDNAME) == 0) { dev= DEV_RAM; } else if (n[0] == 'f' && n[1] == 'd' && numeric(n+2)) { @@ -1879,7 +1936,6 @@ void monitor(void) void boot(void) /* Load Minix and start it, among other things. */ { - /* Initialize tables. */ initialize(); @@ -1928,8 +1984,7 @@ void main(int argc, char **argv) fatal(bootdev.name); /* Check if it is a bootable Minix device. */ - if (readsectors(mon2abs(bootcode), lowsec, 1) != 0 - || memcmp(bootcode, boot_magic, sizeof(boot_magic)) != 0) { + if (readsectors(mon2abs(bootcode), lowsec, 1) != 0) { fprintf(stderr, "edparams: %s: not a bootable Minix device\n", bootdev.name); exit(1); diff --git a/boot/boot.h b/boot/boot.h index 8148f20dc..b651dae1e 100644 --- a/boot/boot.h +++ b/boot/boot.h @@ -58,6 +58,9 @@ EXTERN u32_t caddr, daddr; /* Code and data address of the boot program. */ EXTERN u32_t runsize; /* Size of this program. */ EXTERN u16_t device; /* Drive being booted from. */ +EXTERN u16_t cddevice; /* Drive that is CD if known. */ + +#define CDNAME "cd" /* Name of the CD device. */ typedef struct { /* One chunk of free memory. */ u32_t base; /* Start byte. */ @@ -66,6 +69,7 @@ typedef struct { /* One chunk of free memory. */ EXTERN memory mem[3]; /* List of available memory. */ EXTERN int mon_return; /* Monitor stays in memory? */ +EXTERN int cdbooted; /* Did we boot from CD? (Set by boothead.s.) */ typedef struct bios_env { @@ -101,6 +105,9 @@ int readsectors(u32_t bufaddr, u32_t sector, U8_t count); /* Read 1 or more sectors from "device". */ int writesectors(u32_t bufaddr, u32_t sector, U8_t count); /* Write 1 or more sectors to "device". */ + +int biosreadsectors(u32_t bufaddr, u32_t sector, U8_t count); + int getch(void); /* Read a keypress. */ void scan_keyboard(void); diff --git a/boot/boothead.s b/boot/boothead.s index 5a3bf7d35..8644799ee 100644 --- a/boot/boothead.s +++ b/boot/boothead.s @@ -41,19 +41,30 @@ .extern _rem_part ! To pass partition info .extern _k_flags ! Special kernel flags .extern _mem ! Free memory list +.extern _cdbooted ! Whether we booted from CD +.extern _cddevice ! Whether we booted from CD .text -! 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. +! 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 - 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) + ! Set cs right + ! (skip short a.out header plus 16 byte preefix) + jmpf boot, LOADSEG+3 + .space 11 + + ! entry point when booting from CD + jmpf cdboot, LOADSEG+3 + .space 11 +cdboot: + mov bx, #1 + jmp commonboot boot: - mov ax, #LOADSEG + mov bx, #0 +commonboot: + mov ax, #LOADSEG+1 mov ds, ax ! ds = header movb al, a_flags @@ -96,6 +107,7 @@ sepID: mov _device, dx ! Boot device (probably 0x00 or 0x80) mov _rem_part+0, si ! Remote partition table offset pop _rem_part+2 ! and segment (saved es) + mov _cdbooted, bx ! Booted from CD? (bx set above) ! Remember the current video mode for restoration on exit. movb ah, #0x0F ! Get current video mode @@ -117,7 +129,7 @@ sepID: mov _daddr+0, ax mov _daddr+2, dx push ds - mov ax, #LOADSEG + mov ax, #LOADSEG+1 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 @@ -416,6 +428,8 @@ _dev_open: push es push di ! Save registers used by BIOS calls movb dl, _device ! The default device + cmpb dl, _cddevice + je cdopen cmpb dl, #0x80 ! Floppy < 0x80, winchester >= 0x80 jae winchester floppy: @@ -463,6 +477,10 @@ winchester: jc geoerr ! No such drive? andb cl, #0x3F ! cl = max sector number (1-origin) incb dh ! dh = 1 + max head number (0-origin) + jmp geoboth +cdopen: + movb cl, #0x3F ! Think up geometry for CD's + movb dh, #0x2 geoboth: movb sectors, cl ! Sectors per track movb al, cl ! al = sectors per track @@ -515,20 +533,20 @@ _dev_boundary: neg ax ! ax = (sector % sectors) == 0 ret -! int readsectors(u32_t bufaddr, u32_t sector, u8_t count) +! int biosreadsectors(u32_t bufaddr, u32_t sector, u8_t count) ! int writesectors(u32_t bufaddr, u32_t sector, u8_t count) ! Read/write several sectors from/to disk or floppy. The buffer must ! be between 64K boundaries! Count must fit in a byte. The external ! variables _device, sectors and secspcyl describe the disk and its ! geometry. Returns 0 for success, otherwise the BIOS error code. ! -.define _readsectors, _writesectors +.define _biosreadsectors, _writesectors _writesectors: push bp mov bp, sp movb 13(bp), #0x03 ! Code for a disk write jmp rwsec -_readsectors: +_biosreadsectors: push bp mov bp, sp movb 13(bp), #0x02 ! Code for a disk read @@ -555,6 +573,9 @@ more: mov ax, 8(bp) mov dx, 10(bp) ! dx:ax = abs sector. Divide it by sectors/cyl cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit? jae bigdisk + mov si, _device + cmp si, _cddevice ! Is it a CD? + je bigdisk ! CD's need extended read. div secspcyl ! ax = cylinder, dx = sector within cylinder xchg ax, dx ! ax = sector within cylinder, dx = cylinder movb ch, dl ! ch = low 8 bits of cylinder @@ -1512,5 +1533,3 @@ p_mcs_desc: .comm bus, 2 ! Saved return value of _get_bus .comm unchar, 2 ! Char returned by ungetch(c) .comm line, 2 ! Serial line I/O port to copy console I/O to. - - diff --git a/boot/installboot.c b/boot/installboot.c index 4b8ae4a61..ccaf31dea 100644 --- a/boot/installboot.c +++ b/boot/installboot.c @@ -496,7 +496,8 @@ void make_bootable(enum howto how, char *device, char *bootblock, boothdr.a_magic[0]= !A_MAGIC0; } else { readblock(addr, buf, block_size); - memcpy(&boothdr, buf, sizeof(struct exec)); + /* Must skip 16 bytes of 'boot' as that contains code. */ + memcpy(&boothdr, buf + 16, sizeof(struct exec)); } bootf= nil; dummy.process= boothdr; diff --git a/commands/simple/writeisofs.c b/commands/simple/writeisofs.c index 1274cfe9f..c0816aeee 100644 --- a/commands/simple/writeisofs.c +++ b/commands/simple/writeisofs.c @@ -108,6 +108,7 @@ struct bc_validation { #define INDICATE_BOOTABLE 0x88 +#define BOOTMEDIA_UNSPECIFIED -1 #define BOOTMEDIA_NONE 0 #define BOOTMEDIA_120M 1 #define BOOTMEDIA_144M 2 @@ -160,7 +161,8 @@ struct node { }; int n_reserved_pathtableentries = 0, n_used_pathtableentries = 0; -int harddisk_emulation = 0; +int bootmedia = BOOTMEDIA_UNSPECIFIED; +unsigned long bootseg = 0; int system_type = 0; int get_system_type(int fd); @@ -736,15 +738,17 @@ writebootcatalog(int fd, int *currentsector, int imagesector, int imagesectors) memset(&initial, 0, sizeof(initial)); initial.indicator = INDICATE_BOOTABLE; - if (harddisk_emulation) + initial.media = bootmedia; + initial.seg = (u_int16_t) (bootseg & 0xFFFF); + initial.sectors = 1; + if (bootmedia == BOOTMEDIA_HARDDISK) { - initial.media = BOOTMEDIA_HARDDISK; initial.type = system_type; } - else - initial.media = BOOTMEDIA_144M; - /* initial.sectors = imagesectors; */ - initial.sectors = 1; + if (bootmedia == BOOTMEDIA_NONE) + { + initial.sectors = imagesectors; + } initial.startsector = imagesector; written += Write(fd, &initial, sizeof(initial)); @@ -857,10 +861,24 @@ main(int argc, char *argv[]) return 1; } - while ((ch = getopt(argc, argv, "Rb:hl:")) != -1) { + while ((ch = getopt(argc, argv, "b:s:Rb:hl:nf")) != -1) { switch(ch) { + case 's': + if(optarg[0] != '0' || optarg[1] != 'x') { + fprintf(stderr, "%s: -s\n", + argv[0]); + return 1; + } + bootseg = strtoul(optarg+2, NULL, 16); + break; case 'h': - harddisk_emulation= 1; + bootmedia= BOOTMEDIA_HARDDISK; + break; + case 'n': + bootmedia= BOOTMEDIA_NONE; + break; + case 'f': + bootmedia= BOOTMEDIA_144M; break; case 'l': label = optarg; @@ -881,8 +899,23 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; + /* Args check */ + if(argc != 2) { - fprintf(stderr, "usage: %s [-l