mkboot.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * aarch64-rpi/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 create a RPi compatible MBR for ESP
  28. *
  29. */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <fcntl.h>
  34. #include <unistd.h>
  35. /* entry point */
  36. int main(int argc, char** argv)
  37. {
  38. // variables
  39. unsigned char data[65536];
  40. unsigned int np,sp,i,es,ee;
  41. int f;
  42. // check arguments
  43. if(argc < 2) {
  44. printf( "BOOTBOOT mkboot utility - bztsrc@gitlab\n\nUsage:\n"
  45. " ./mkboot <disk>\n\n"
  46. "Maps GPT EFI System Partition into MBR so that Raspberry Pi\n"
  47. "firmware can find it's files and boot from it.\n"
  48. "Examples:\n"
  49. " ./mkboot diskimage.dd - modify a disk image file\n"
  50. " ./mkboot /dev/sda - modify a real disk\n");
  51. return 1;
  52. }
  53. // open file
  54. f = open(argv[1], O_RDONLY);
  55. if(f < 0) {
  56. fprintf(stderr, "mkboot: file not found\n");
  57. return 2;
  58. }
  59. // read the partitioning tables
  60. if(read(f, data, 65536)==-1) {
  61. close(f);
  62. fprintf(stderr, "mkboot: unable to read file\n");
  63. return 2;
  64. }
  65. close(f);
  66. if(memcmp((void*)&data[512], "EFI PART", 8)) {
  67. fprintf(stderr, "mkboot: GPT partitioning table not found\n");
  68. return 2;
  69. }
  70. // get number of partitions and size of partition entry
  71. np=*((unsigned int*)&data[512+80]); sp=*((unsigned int*)&data[512+84]);
  72. i=*((unsigned int*)&data[512+72])*512; es=ee=0;
  73. // get esp start and esp end sectors
  74. while(np--) {
  75. if(*((unsigned int*)&data[i])==0xC12A7328 && *((unsigned int*)&data[i+4])==0x11D2F81F) {
  76. es=*((unsigned int*)&data[i+32]); ee=*((unsigned int*)&data[i+40]); break;
  77. }
  78. i+=sp;
  79. }
  80. if(es==0 || ee==0 || ee<es+1) {
  81. fprintf(stderr, "mkboot: ESP not found in GPT\n");
  82. return 2;
  83. }
  84. // if first MBR partition is not a FAT, make space for it
  85. if(data[0x1C2]!=0xC/*FAT32 LBA*/ && data[0x1C2]!=0xE/*FAT16 LBA*/) {
  86. memcpy((void*)&data+0x1EE, (void*)&data+0x1DE, 16);
  87. memcpy((void*)&data+0x1DE, (void*)&data+0x1CE, 16);
  88. memcpy((void*)&data+0x1CE, (void*)&data+0x1BE, 16);
  89. data[0x1C2]=0xC;
  90. }
  91. // check if it's already pointing to ESP
  92. ee-=sp-1;
  93. if(*((unsigned int*)&data[0x1C6])==es && *((unsigned int*)&data[0x1CA])==ee) {
  94. fprintf(stderr, "mkboot: ESP already mapped to MBR, nothing to do\n");
  95. return 0;
  96. }
  97. *((unsigned int*)&data[0x1C6])=es;
  98. *((unsigned int*)&data[0x1CA])=ee;
  99. // save boot record
  100. f = open(argv[1], O_WRONLY);
  101. if(f < 0 || write(f, data, 512) <= 0) {
  102. fprintf(stderr, "mkboot: unable to write MBR\n");
  103. return 3;
  104. }
  105. close(f);
  106. // all went well
  107. printf("mkboot: GPT ESP mapped to MBR successfully\n");
  108. }