1 /* 2 * install new master boot record boot code on PC disk. 3 */ 4 5 #include <u.h> 6 #include <libc.h> 7 #include <disk.h> 8 9 typedef struct { 10 uchar active; /* active flag */ 11 uchar starth; /* starting head */ 12 uchar starts; /* starting sector */ 13 uchar startc; /* starting cylinder */ 14 uchar type; /* partition type */ 15 uchar endh; /* ending head */ 16 uchar ends; /* ending sector */ 17 uchar endc; /* ending cylinder */ 18 uchar lba[4]; /* starting LBA */ 19 uchar size[4]; /* size in sectors */ 20 } Tentry; 21 22 enum { 23 Toffset = 0x1BE, /* offset of partition table */ 24 25 Type9 = 0x39, 26 }; 27 28 /* 29 * Default boot block prints an error message and reboots. 30 */ 31 static int ndefmbr = Toffset; 32 static char defmbr[512] = { 33 [0x000] 0xEB, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 [0x03E] 0xFA, 0xFC, 0x8C, 0xC8, 0x8E, 0xD8, 0x8E, 0xD0, 36 0xBC, 0x00, 0x7C, 0xBE, 0x77, 0x7C, 0xE8, 0x19, 37 0x00, 0x33, 0xC0, 0xCD, 0x16, 0xBB, 0x40, 0x00, 38 0x8E, 0xC3, 0xBB, 0x72, 0x00, 0xB8, 0x34, 0x12, 39 0x26, 0x89, 0x07, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 40 0xEB, 0xD6, 0xAC, 0x0A, 0xC0, 0x74, 0x09, 0xB4, 41 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2, 42 0xC3, 'N', 'o', 't', ' ', 'a', ' ', 'b', 43 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 44 'd', 'i', 's', 'c', ' ', 'o', 'r', ' ', 45 'd', 'i', 's', 'c', ' ', 'e', 'r', 'r', 46 'o', 'r', '\r', '\n', 'P', 'r', 'e', 's', 47 's', ' ', 'a', 'l', 'm', 'o', 's', 't', 48 ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', 49 ' ', 't', 'o', ' ', 'r', 'e', 'b', 'o', 50 'o', 't', '.', '.', '.', 0x00, 0x00, 0x00, 51 }; 52 53 void 54 usage(void) 55 { 56 fprint(2, "usage: disk/mbr [-m mbrfile] disk\n"); 57 exits("usage"); 58 } 59 60 void 61 fatal(char *fmt, ...) 62 { 63 char err[ERRMAX]; 64 va_list arg; 65 66 va_start(arg, fmt); 67 vsnprint(err, ERRMAX, fmt, arg); 68 va_end(arg); 69 fprint(2, "mbr: %s\n", err); 70 exits(err); 71 } 72 73 static void 74 putle32(void* v, u32int i) 75 { 76 uchar *p; 77 78 p = v; 79 p[0] = i; 80 p[1] = i>>8; 81 p[2] = i>>16; 82 p[3] = i>>24; 83 } 84 85 static void 86 writechs(Disk *disk, uchar *p, vlong lba) 87 { 88 int c, h, s; 89 90 s = lba % disk->s; 91 h = (lba / disk->s) % disk->h; 92 c = lba / (disk->s * disk->h); 93 94 if(c >= 1024) { 95 c = 1023; 96 h = disk->h - 1; 97 s = disk->s - 1; 98 } 99 100 p[0] = h; 101 p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0); 102 p[2] = c; 103 } 104 105 static void 106 wrtentry(Disk *disk, Tentry *tp, int type, u32int base, u32int lba, u32int end) 107 { 108 tp->active = 0x80; /* make this sole partition active */ 109 tp->type = type; 110 writechs(disk, &tp->starth, lba); 111 writechs(disk, &tp->endh, end-1); 112 putle32(tp->lba, lba-base); 113 putle32(tp->size, end-lba); 114 } 115 116 void 117 main(int argc, char **argv) 118 { 119 Disk *disk; 120 Tentry *tp; 121 uchar *mbr, *buf; 122 char *mbrfile; 123 ulong secsize; 124 int flag9, sysfd, nmbr; 125 126 flag9 = 0; 127 mbrfile = nil; 128 ARGBEGIN { 129 case '9': 130 flag9 = 1; 131 break; 132 case 'm': 133 mbrfile = EARGF(usage()); 134 break; 135 default: 136 usage(); 137 } ARGEND 138 139 if(argc < 1) 140 usage(); 141 142 disk = opendisk(argv[0], 0, 0); 143 if(disk == nil) 144 fatal("opendisk %s: %r", argv[0]); 145 146 if(disk->type == Tfloppy) 147 fatal("will not install mbr on floppy"); 148 if(disk->secsize != 512) 149 fatal("secsize %d invalid", disk->secsize); 150 151 secsize = disk->secsize; 152 buf = malloc(secsize*(disk->s+1)); 153 mbr = malloc(secsize*disk->s); 154 if(buf == nil || mbr == nil) 155 fatal("out of memory"); 156 157 /* 158 * Start with initial sector from disk. 159 */ 160 if(seek(disk->fd, 0, 0) < 0) 161 fatal("seek to boot sector: %r\n"); 162 if(read(disk->fd, mbr, secsize) != secsize) 163 fatal("reading boot sector: %r"); 164 165 if(mbrfile == nil){ 166 nmbr = ndefmbr; 167 memmove(mbr, defmbr, nmbr); 168 } else { 169 memset(buf, 0, secsize*disk->s); 170 if((sysfd = open(mbrfile, OREAD)) < 0) 171 fatal("open %s: %r", mbrfile); 172 if((nmbr = read(sysfd, buf, secsize*(disk->s+1))) < 0) 173 fatal("read %s: %r", mbrfile); 174 if(nmbr > secsize*disk->s) 175 fatal("master boot record too large %d > %d", nmbr, secsize*disk->s); 176 if(nmbr < secsize) 177 nmbr = secsize; 178 close(sysfd); 179 memmove(buf+Toffset, mbr+Toffset, secsize-Toffset); 180 memmove(mbr, buf, nmbr); 181 } 182 183 if(flag9){ 184 tp = (Tentry*)(mbr+Toffset); 185 memset(tp, 0, secsize-Toffset); 186 wrtentry(disk, tp, Type9, 0, disk->s, disk->secs); 187 } 188 mbr[secsize-2] = 0x55; 189 mbr[secsize-1] = 0xAA; 190 nmbr = (nmbr+secsize-1)&~(secsize-1); 191 if(seek(disk->wfd, 0, 0) < 0) 192 fatal("seek to MBR sector: %r\n"); 193 if(write(disk->wfd, mbr, nmbr) != nmbr) 194 fatal("writing MBR: %r"); 195 196 exits(0); 197 } 198