cgpt_boot.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include "cgpt.h"
  9. #include "cgpt_params.h"
  10. #include "cgptlib_internal.h"
  11. #include "vboot_host.h"
  12. int CgptGetBootPartitionNumber(CgptBootParams *params) {
  13. struct drive drive;
  14. int gpt_retval= 0;
  15. int retval;
  16. if (params == NULL)
  17. return CGPT_FAILED;
  18. if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
  19. params->drive_size))
  20. return CGPT_FAILED;
  21. if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
  22. Error("GptSanityCheck() returned %d: %s\n",
  23. gpt_retval, GptError(gpt_retval));
  24. retval = CGPT_FAILED;
  25. goto done;
  26. }
  27. if (CGPT_OK != ReadPMBR(&drive)) {
  28. Error("Unable to read PMBR\n");
  29. retval = CGPT_FAILED;
  30. goto done;
  31. }
  32. char buf[GUID_STRLEN];
  33. GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
  34. int numEntries = GetNumberOfEntries(&drive);
  35. int i;
  36. for(i = 0; i < numEntries; i++) {
  37. GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
  38. if (GuidEqual(&entry->unique, &drive.pmbr.boot_guid)) {
  39. params->partition = i + 1;
  40. retval = CGPT_OK;
  41. goto done;
  42. }
  43. }
  44. Error("Didn't find any boot partition\n");
  45. params->partition = 0;
  46. retval = CGPT_FAILED;
  47. done:
  48. (void) DriveClose(&drive, 1);
  49. return retval;
  50. }
  51. int CgptBoot(CgptBootParams *params) {
  52. struct drive drive;
  53. int retval = 1;
  54. int gpt_retval= 0;
  55. int mode = O_RDONLY;
  56. if (params == NULL)
  57. return CGPT_FAILED;
  58. if (params->create_pmbr || params->partition || params->bootfile)
  59. mode = O_RDWR;
  60. if (CGPT_OK != DriveOpen(params->drive_name, &drive, mode,
  61. params->drive_size)) {
  62. return CGPT_FAILED;
  63. }
  64. if (CGPT_OK != ReadPMBR(&drive)) {
  65. Error("Unable to read PMBR\n");
  66. goto done;
  67. }
  68. if (params->create_pmbr) {
  69. drive.pmbr.magic[0] = 0x1d;
  70. drive.pmbr.magic[1] = 0x9a;
  71. drive.pmbr.sig[0] = 0x55;
  72. drive.pmbr.sig[1] = 0xaa;
  73. memset(&drive.pmbr.part, 0, sizeof(drive.pmbr.part));
  74. drive.pmbr.part[0].f_head = 0x00;
  75. drive.pmbr.part[0].f_sect = 0x02;
  76. drive.pmbr.part[0].f_cyl = 0x00;
  77. drive.pmbr.part[0].type = 0xee;
  78. drive.pmbr.part[0].l_head = 0xff;
  79. drive.pmbr.part[0].l_sect = 0xff;
  80. drive.pmbr.part[0].l_cyl = 0xff;
  81. drive.pmbr.part[0].f_lba = htole32(1);
  82. uint32_t max = 0xffffffff;
  83. if (drive.gpt.streaming_drive_sectors < 0xffffffff)
  84. max = drive.gpt.streaming_drive_sectors - 1;
  85. drive.pmbr.part[0].num_sect = htole32(max);
  86. }
  87. if (params->partition) {
  88. if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
  89. Error("GptSanityCheck() returned %d: %s\n",
  90. gpt_retval, GptError(gpt_retval));
  91. goto done;
  92. }
  93. if (params->partition > GetNumberOfEntries(&drive)) {
  94. Error("invalid partition number: %d\n", params->partition);
  95. goto done;
  96. }
  97. uint32_t index = params->partition - 1;
  98. GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
  99. memcpy(&drive.pmbr.boot_guid, &entry->unique, sizeof(Guid));
  100. }
  101. if (params->bootfile) {
  102. int fd = open(params->bootfile, O_RDONLY);
  103. if (fd < 0) {
  104. Error("Can't read %s: %s\n", params->bootfile, strerror(errno));
  105. goto done;
  106. }
  107. int n = read(fd, drive.pmbr.bootcode, sizeof(drive.pmbr.bootcode));
  108. if (n < 1) {
  109. Error("problem reading %s: %s\n", params->bootfile, strerror(errno));
  110. close(fd);
  111. goto done;
  112. }
  113. close(fd);
  114. }
  115. char buf[GUID_STRLEN];
  116. GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
  117. printf("%s\n", buf);
  118. // Write it all out, if needed.
  119. if (mode == O_RDONLY || CGPT_OK == WritePMBR(&drive))
  120. retval = 0;
  121. done:
  122. (void) DriveClose(&drive, 1);
  123. return retval;
  124. }