mkboot.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * x86_64-bios/mkboot.c
  3. *
  4. * Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * This file is part of the BOOTBOOT Protocol package.
  27. * @brief Little tool to install boot.bin in MBR or VBR
  28. *
  29. */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <fcntl.h>
  34. #include <unistd.h>
  35. /* the BOOTBOOT 1st stage loader code */
  36. extern unsigned char *_binary____dist_boot_bin_start;
  37. /* entry point */
  38. int main(int argc, char** argv)
  39. {
  40. // variables
  41. unsigned char bootrec[512], data[512];
  42. int f, lba=0, seek=0, lsn, bootlsn=-1;
  43. // check arguments
  44. if(argc < 2) {
  45. printf( "BOOTBOOT mkboot utility - bztsrc@gitlab\n\nUsage:\n"
  46. " ./mkboot <disk> [partition lba] [bootsector lba]\n\n"
  47. "Installs boot record on a disk. Disk can be a local file, a disk or partition\n"
  48. "device. If you want to install it on a partition, you'll have to specify the\n"
  49. "starting LBA of that partition as well. Requires that bootboot.bin is already\n"
  50. "copied on the disk in a contiguous area in order to work.\n\n"
  51. "Examples:\n"
  52. " ./mkboot diskimage.dd - installing on a disk image\n"
  53. " ./mkboot /dev/sda - installing as (P)MBR\n"
  54. " ./mkboot /dev/sda 123 - installing as VBR on a disk device\n"
  55. " ./mkboot /dev/sda1 123 0 - installing as VBR on a partition device\n");
  56. return 1;
  57. }
  58. if(argc > 2 || argv[2]!=NULL) {
  59. lba = seek = atoi(argv[2]);
  60. }
  61. if(argc > 3 || argv[3]!=NULL) {
  62. seek = atoi(argv[3]);
  63. }
  64. if(lba < seek) seek = lba;
  65. // open file
  66. f = open(argv[1], O_RDONLY);
  67. if(f < 0) {
  68. fprintf(stderr, "mkboot: file not found\n");
  69. return 2;
  70. }
  71. // read the boot record
  72. if(seek>0) lseek(f, seek*512, SEEK_SET);
  73. if(read(f, data, 512)==-1) {
  74. close(f);
  75. fprintf(stderr, "mkboot: unable to read file\n");
  76. return 2;
  77. }
  78. // create the boot record. First copy the code then the data area from original sector on disk
  79. memcpy((void*)&bootrec, (void*)&_binary____dist_boot_bin_start, 512);
  80. memcpy((void*)&bootrec+0x3, (void*)&data+0x3, 0x78-0x3); // copy BPB (if any)
  81. memcpy((void*)&bootrec+0x1B8, (void*)&data+0x1B8, 510-0x1B8); // copy WNTID and partitioning table (if any)
  82. // now locate the second stage by magic bytes
  83. for(lsn = 1; lsn < 1024*1024; lsn++) {
  84. printf("Checking sector %d\r", lsn);
  85. if(read(f, data, 512) != -1 &&
  86. data[0] == 0x55 && data[1] == 0xAA && data[3] == 0xE9 && data[8] == 'B' && data[12] == 'B') {
  87. bootlsn=lsn;
  88. break;
  89. }
  90. }
  91. close(f);
  92. if(bootlsn == -1) {
  93. fprintf(stderr, "mkboot: unable to locate 2nd stage (bootboot.bin) in the first 512 Mbyte\n");
  94. return 2;
  95. }
  96. // add bootboot.bin's address to boot record
  97. bootlsn += lba - seek;
  98. memcpy((void*)&bootrec+0x1B0, (void*)&bootlsn, 4);
  99. // save boot record
  100. f = open(argv[1], O_WRONLY);
  101. if(seek>0 && f) lseek(f, seek*512, SEEK_SET);
  102. if(f < 0 || write(f, bootrec, 512) <= 0) {
  103. fprintf(stderr, "mkboot: unable to write boot record\n");
  104. return 3;
  105. }
  106. close(f);
  107. // all went well
  108. printf("mkboot: BOOTBOOT installed, 2nd stage starts at LBA %d\n", bootlsn);
  109. }