diff options
Diffstat (limited to 'appl/cmd/disk/mbr.b')
| -rw-r--r-- | appl/cmd/disk/mbr.b | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/appl/cmd/disk/mbr.b b/appl/cmd/disk/mbr.b new file mode 100644 index 00000000..9d51c945 --- /dev/null +++ b/appl/cmd/disk/mbr.b @@ -0,0 +1,134 @@ +implement Mbr; + +# +# install new master boot record boot code on PC disk. +# + +include "sys.m"; + sys: Sys; + +include "draw.m"; + +include "disks.m"; + disks: Disks; + Disk, PCpart, Toffset: import disks; + +include "arg.m"; + +Mbr: module +{ + init: fn(nil: ref Draw->Context, nil: list of string); +}; + + + +# +# Default boot block prints an error message and reboots. +# +ndefmbr := Toffset; +defmbr := array[512] of { + byte 16rEB, byte 16r3C, byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, + byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, byte 16r00, +16r03E => byte 16rFA, byte 16rFC, byte 16r8C, byte 16rC8, byte 16r8E, byte 16rD8, byte 16r8E, byte 16rD0, + byte 16rBC, byte 16r00, byte 16r7C, byte 16rBE, byte 16r77, byte 16r7C, byte 16rE8, byte 16r19, + byte 16r00, byte 16r33, byte 16rC0, byte 16rCD, byte 16r16, byte 16rBB, byte 16r40, byte 16r00, + byte 16r8E, byte 16rC3, byte 16rBB, byte 16r72, byte 16r00, byte 16rB8, byte 16r34, byte 16r12, + byte 16r26, byte 16r89, byte 16r07, byte 16rEA, byte 16r00, byte 16r00, byte 16rFF, byte 16rFF, + byte 16rEB, byte 16rD6, byte 16rAC, byte 16r0A, byte 16rC0, byte 16r74, byte 16r09, byte 16rB4, + byte 16r0E, byte 16rBB, byte 16r07, byte 16r00, byte 16rCD, byte 16r10, byte 16rEB, byte 16rF2, + byte 16rC3, byte 'N', byte 'o', byte 't', byte ' ', byte 'a', byte ' ', byte 'b', + byte 'o', byte 'o', byte 't', byte 'a', byte 'b', byte 'l', byte 'e', byte ' ', + byte 'd', byte 'i', byte 's', byte 'c', byte ' ', byte 'o', byte 'r', byte ' ', + byte 'd', byte 'i', byte 's', byte 'c', byte ' ', byte 'e', byte 'r', byte 'r', + byte 'o', byte 'r', byte '\r', byte '\n', byte 'P', byte 'r', byte 'e', byte 's', + byte 's', byte ' ', byte 'a', byte 'l', byte 'm', byte 'o', byte 's', byte 't', + byte ' ', byte 'a', byte 'n', byte 'y', byte ' ', byte 'k', byte 'e', byte 'y', + byte ' ', byte 't', byte 'o', byte ' ', byte 'r', byte 'e', byte 'b', byte 'o', + byte 'o', byte 't', byte '.', byte '.', byte '.', byte 16r00, byte 16r00, byte 16r00, +}; + +init(nil: ref Draw->Context, args: list of string) +{ + flag9 := 0; + mbrfile: string; + sys = load Sys Sys->PATH; + disks = load Disks Disks->PATH; + + sys->pctl(Sys->FORKFD, nil); + disks->init(); + + arg := load Arg Arg->PATH; + arg->init(args); + arg->setusage("disk/mbr [-m mbrfile] disk"); + while((o := arg->opt()) != 0) + case o { + '9' => + flag9 = 1; + 'm' => + mbrfile = arg->earg(); + * => + arg->usage(); + } + args = arg->argv(); + if(len args != 1) + arg->usage(); + arg = nil; + + disk := Disk.open(hd args, Sys->ORDWR, 0); + if(disk == nil) + fatal(sys->sprint("opendisk %s: %r", hd args)); + + if(disk.dtype == "floppy") + fatal(sys->sprint("will not install mbr on floppy")); + if(disk.secsize != 512) + fatal(sys->sprint("secsize %d invalid: must be 512", disk.secsize)); + + secsize := disk.secsize; + mbr := array[secsize*disk.s] of {* => byte 0}; + + # + # Start with initial sector from disk. + # + if(sys->seek(disk.fd, big 0, 0) < big 0) + fatal(sys->sprint("seek to boot sector: %r\n")); + if(sys->read(disk.fd, mbr, secsize) != secsize) + fatal(sys->sprint("reading boot sector: %r")); + + nmbr: int; + if(mbrfile == nil){ + nmbr = ndefmbr; + mbr[0:] = defmbr; + } else { + buf := array[secsize*(disk.s+1)] of {* => byte 0}; + if((sysfd := sys->open(mbrfile, Sys->OREAD)) == nil) + fatal(sys->sprint("open %s: %r", mbrfile)); + if((nmbr = sys->read(sysfd, buf, secsize*(disk.s+1))) < 0) + fatal(sys->sprint("read %s: %r", mbrfile)); + if(nmbr > secsize*disk.s) + fatal(sys->sprint("master boot record too large %d > %d", nmbr, secsize*disk.s)); + if(nmbr < secsize) + nmbr = secsize; + sysfd = nil; + buf[Toffset:] = mbr[Toffset:secsize]; + mbr[0:] = buf[0:nmbr]; + } + + if(flag9){ + for(i := Toffset; i < secsize; i++) + mbr[i] = byte 0; + mbr[Toffset:] = PCpart(0, Disks->Type9, big 0, big disk.s, disk.secs-big disk.s).bytes(disk); + } + mbr[secsize-2] = byte Disks->Magic0; + mbr[secsize-1] = byte Disks->Magic1; + nmbr = (nmbr+secsize-1)&~(secsize-1); + if(sys->seek(disk.wfd, big 0, 0) < big 0) + fatal(sys->sprint("seek to MBR sector: %r\n")); + if(sys->write(disk.wfd, mbr, nmbr) != nmbr) + fatal(sys->sprint("writing MBR: %r")); +} + +fatal(s: string) +{ + sys->fprint(sys->fildes(2), "disk/mbr: %s\n", s); + raise "fail:error"; +} |
