mbr.c 4.2 KB

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