17dd7cddfSDavid du Colombier /* 27dd7cddfSDavid du Colombier * install new master boot record boot code on PC disk. 37dd7cddfSDavid du Colombier */ 47dd7cddfSDavid du Colombier 57dd7cddfSDavid du Colombier #include <u.h> 67dd7cddfSDavid du Colombier #include <libc.h> 77dd7cddfSDavid du Colombier #include <disk.h> 87dd7cddfSDavid du Colombier 97dd7cddfSDavid du Colombier enum { 107dd7cddfSDavid du Colombier Toffset = 0x1BE /* offset of partition table */ 117dd7cddfSDavid du Colombier }; 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier /* 147dd7cddfSDavid du Colombier * Default boot block prints an error message and reboots. 157dd7cddfSDavid du Colombier */ 167dd7cddfSDavid du Colombier static int ndefmbr = Toffset; 177dd7cddfSDavid du Colombier static char defmbr[512] = { 187dd7cddfSDavid du Colombier [0x000] 0xEB, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 197dd7cddfSDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 207dd7cddfSDavid du Colombier [0x03E] 0xFA, 0xFC, 0x8C, 0xC8, 0x8E, 0xD8, 0x8E, 0xD0, 217dd7cddfSDavid du Colombier 0xBC, 0x00, 0x7C, 0xBE, 0x77, 0x7C, 0xE8, 0x19, 227dd7cddfSDavid du Colombier 0x00, 0x33, 0xC0, 0xCD, 0x16, 0xBB, 0x40, 0x00, 237dd7cddfSDavid du Colombier 0x8E, 0xC3, 0xBB, 0x72, 0x00, 0xB8, 0x34, 0x12, 247dd7cddfSDavid du Colombier 0x26, 0x89, 0x07, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 257dd7cddfSDavid du Colombier 0xEB, 0xD6, 0xAC, 0x0A, 0xC0, 0x74, 0x09, 0xB4, 267dd7cddfSDavid du Colombier 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2, 277dd7cddfSDavid du Colombier 0xC3, 'N', 'o', 't', ' ', 'a', ' ', 'b', 287dd7cddfSDavid du Colombier 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 297dd7cddfSDavid du Colombier 'd', 'i', 's', 'c', ' ', 'o', 'r', ' ', 307dd7cddfSDavid du Colombier 'd', 'i', 's', 'c', ' ', 'e', 'r', 'r', 317dd7cddfSDavid du Colombier 'o', 'r', '\r', '\n', 'P', 'r', 'e', 's', 327dd7cddfSDavid du Colombier 's', ' ', 'a', 'l', 'm', 'o', 's', 't', 337dd7cddfSDavid du Colombier ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', 347dd7cddfSDavid du Colombier ' ', 't', 'o', ' ', 'r', 'e', 'b', 'o', 357dd7cddfSDavid du Colombier 'o', 't', '.', '.', '.', 0x00, 0x00, 0x00, 367dd7cddfSDavid du Colombier }; 377dd7cddfSDavid du Colombier 387dd7cddfSDavid du Colombier void 397dd7cddfSDavid du Colombier usage(void) 407dd7cddfSDavid du Colombier { 417dd7cddfSDavid du Colombier fprint(2, "usage: disk/mbr [-m mbrfile] disk\n"); 427dd7cddfSDavid du Colombier exits("usage"); 437dd7cddfSDavid du Colombier } 447dd7cddfSDavid du Colombier 457dd7cddfSDavid du Colombier void 467dd7cddfSDavid du Colombier fatal(char *fmt, ...) 477dd7cddfSDavid du Colombier { 489a747e4fSDavid du Colombier char err[ERRMAX]; 497dd7cddfSDavid du Colombier va_list arg; 507dd7cddfSDavid du Colombier 517dd7cddfSDavid du Colombier va_start(arg, fmt); 529a747e4fSDavid du Colombier vsnprint(err, ERRMAX, fmt, arg); 537dd7cddfSDavid du Colombier va_end(arg); 547dd7cddfSDavid du Colombier fprint(2, "mbr: %s\n", err); 557dd7cddfSDavid du Colombier exits(err); 567dd7cddfSDavid du Colombier } 577dd7cddfSDavid du Colombier 587dd7cddfSDavid du Colombier void 597dd7cddfSDavid du Colombier main(int argc, char **argv) 607dd7cddfSDavid du Colombier { 617dd7cddfSDavid du Colombier Disk *disk; 627dd7cddfSDavid du Colombier uchar *mbr, *buf; 637dd7cddfSDavid du Colombier char *mbrfile; 647dd7cddfSDavid du Colombier ulong secsize; 657dd7cddfSDavid du Colombier int sysfd, nmbr; 667dd7cddfSDavid du Colombier 677dd7cddfSDavid du Colombier mbrfile = nil; 687dd7cddfSDavid du Colombier ARGBEGIN { 697dd7cddfSDavid du Colombier case 'm': 707dd7cddfSDavid du Colombier mbrfile = ARGF(); 717dd7cddfSDavid du Colombier break; 727dd7cddfSDavid du Colombier default: 737dd7cddfSDavid du Colombier usage(); 747dd7cddfSDavid du Colombier } ARGEND 757dd7cddfSDavid du Colombier 767dd7cddfSDavid du Colombier if(argc < 1) 777dd7cddfSDavid du Colombier usage(); 787dd7cddfSDavid du Colombier 797dd7cddfSDavid du Colombier disk = opendisk(argv[0], 0, 0); 807dd7cddfSDavid du Colombier if(disk == nil) 817dd7cddfSDavid du Colombier fatal("opendisk %s: %r", argv[0]); 827dd7cddfSDavid du Colombier 837dd7cddfSDavid du Colombier if(disk->type == Tfloppy) 847dd7cddfSDavid du Colombier fatal("will not install mbr on floppy"); 857dd7cddfSDavid du Colombier if(disk->secsize != 512) 867dd7cddfSDavid du Colombier fatal("secsize %d invalid", disk->secsize); 877dd7cddfSDavid du Colombier 887dd7cddfSDavid du Colombier secsize = disk->secsize; 89*3ff48bf5SDavid du Colombier buf = malloc(secsize*(disk->s+1)); 90*3ff48bf5SDavid du Colombier mbr = malloc(secsize*disk->s); 917dd7cddfSDavid du Colombier if(buf == nil || mbr == nil) 927dd7cddfSDavid du Colombier fatal("out of memory"); 937dd7cddfSDavid du Colombier 947dd7cddfSDavid du Colombier /* 957dd7cddfSDavid du Colombier * Start with initial sector from disk. 967dd7cddfSDavid du Colombier */ 977dd7cddfSDavid du Colombier if(seek(disk->fd, 0, 0) < 0) 987dd7cddfSDavid du Colombier fatal("seek to boot sector: %r\n"); 997dd7cddfSDavid du Colombier if(read(disk->fd, mbr, secsize) != secsize) 1007dd7cddfSDavid du Colombier fatal("reading boot sector: %r"); 1017dd7cddfSDavid du Colombier 1027dd7cddfSDavid du Colombier if(mbrfile == nil){ 1037dd7cddfSDavid du Colombier nmbr = ndefmbr; 1047dd7cddfSDavid du Colombier memmove(mbr, defmbr, nmbr); 1057dd7cddfSDavid du Colombier } else { 106*3ff48bf5SDavid du Colombier memset(buf, 0, secsize*disk->s); 1077dd7cddfSDavid du Colombier if((sysfd = open(mbrfile, OREAD)) < 0) 1087dd7cddfSDavid du Colombier fatal("open %s: %r", mbrfile); 109*3ff48bf5SDavid du Colombier if((nmbr = read(sysfd, buf, secsize*(disk->s+1))) < 0) 1107dd7cddfSDavid du Colombier fatal("read %s: %r", mbrfile); 111*3ff48bf5SDavid du Colombier if(nmbr > secsize*disk->s) 112*3ff48bf5SDavid du Colombier fatal("master boot record too large %d > %d", nmbr, secsize*disk->s); 113*3ff48bf5SDavid du Colombier if(nmbr < secsize) 114*3ff48bf5SDavid du Colombier nmbr = secsize; 1157dd7cddfSDavid du Colombier close(sysfd); 116*3ff48bf5SDavid du Colombier memmove(buf+Toffset, mbr+Toffset, secsize-Toffset); 1177dd7cddfSDavid du Colombier memmove(mbr, buf, nmbr); 1187dd7cddfSDavid du Colombier } 1197dd7cddfSDavid du Colombier mbr[secsize-2] = 0x55; 1207dd7cddfSDavid du Colombier mbr[secsize-1] = 0xAA; 121*3ff48bf5SDavid du Colombier nmbr = (nmbr+secsize-1)&~(secsize-1); 1227dd7cddfSDavid du Colombier if(seek(disk->wfd, 0, 0) < 0) 1237dd7cddfSDavid du Colombier fatal("seek to MBR sector: %r\n"); 124*3ff48bf5SDavid du Colombier if(write(disk->wfd, mbr, nmbr) != nmbr) 1257dd7cddfSDavid du Colombier fatal("writing MBR: %r"); 1267dd7cddfSDavid du Colombier 1277dd7cddfSDavid du Colombier exits(0); 1287dd7cddfSDavid du Colombier } 129