partition.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <inttypes.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <common/debug.h>
  11. #include <common/tf_crc32.h>
  12. #include <drivers/io/io_storage.h>
  13. #include <drivers/partition/efi.h>
  14. #include <drivers/partition/partition.h>
  15. #include <drivers/partition/gpt.h>
  16. #include <drivers/partition/mbr.h>
  17. #include <plat/common/platform.h>
  18. static uint8_t mbr_sector[PLAT_PARTITION_BLOCK_SIZE];
  19. static partition_entry_list_t list;
  20. #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
  21. static void dump_entries(int num)
  22. {
  23. char name[EFI_NAMELEN];
  24. int i, j, len;
  25. VERBOSE("Partition table with %d entries:\n", num);
  26. for (i = 0; i < num; i++) {
  27. len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name);
  28. for (j = 0; j < EFI_NAMELEN - len - 1; j++) {
  29. name[len + j] = ' ';
  30. }
  31. name[EFI_NAMELEN - 1] = '\0';
  32. VERBOSE("%d: %s %" PRIx64 "-%" PRIx64 "\n", i + 1, name, list.list[i].start,
  33. list.list[i].start + list.list[i].length - 4);
  34. }
  35. }
  36. #else
  37. #define dump_entries(num) ((void)num)
  38. #endif
  39. /*
  40. * Load the first sector that carries MBR header.
  41. * The MBR boot signature should be always valid whether it's MBR or GPT.
  42. */
  43. static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry)
  44. {
  45. size_t bytes_read;
  46. uintptr_t offset;
  47. int result;
  48. assert(mbr_entry != NULL);
  49. /* MBR partition table is in LBA0. */
  50. result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET);
  51. if (result != 0) {
  52. WARN("Failed to seek (%i)\n", result);
  53. return result;
  54. }
  55. result = io_read(image_handle, (uintptr_t)&mbr_sector,
  56. PLAT_PARTITION_BLOCK_SIZE, &bytes_read);
  57. if (result != 0) {
  58. WARN("Failed to read data (%i)\n", result);
  59. return result;
  60. }
  61. /* Check MBR boot signature. */
  62. if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) ||
  63. (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) {
  64. return -ENOENT;
  65. }
  66. offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET;
  67. memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t));
  68. return 0;
  69. }
  70. /*
  71. * Load GPT header and check the GPT signature and header CRC.
  72. * If partition numbers could be found, check & update it.
  73. */
  74. static int load_gpt_header(uintptr_t image_handle)
  75. {
  76. gpt_header_t header;
  77. size_t bytes_read;
  78. int result;
  79. uint32_t header_crc, calc_crc;
  80. result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET);
  81. if (result != 0) {
  82. return result;
  83. }
  84. result = io_read(image_handle, (uintptr_t)&header,
  85. sizeof(gpt_header_t), &bytes_read);
  86. if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) {
  87. return result;
  88. }
  89. if (memcmp(header.signature, GPT_SIGNATURE,
  90. sizeof(header.signature)) != 0) {
  91. return -EINVAL;
  92. }
  93. /*
  94. * UEFI Spec 2.8 March 2019 Page 119: HeaderCRC32 value is
  95. * computed by setting this field to 0, and computing the
  96. * 32-bit CRC for HeaderSize bytes.
  97. */
  98. header_crc = header.header_crc;
  99. header.header_crc = 0U;
  100. calc_crc = tf_crc32(0U, (uint8_t *)&header, DEFAULT_GPT_HEADER_SIZE);
  101. if (header_crc != calc_crc) {
  102. ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n",
  103. header_crc, calc_crc);
  104. return -EINVAL;
  105. }
  106. header.header_crc = header_crc;
  107. /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */
  108. list.entry_count = header.list_num;
  109. if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) {
  110. list.entry_count = PLAT_PARTITION_MAX_ENTRIES;
  111. }
  112. return 0;
  113. }
  114. static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry,
  115. int part_number)
  116. {
  117. size_t bytes_read;
  118. uintptr_t offset;
  119. int result;
  120. assert(mbr_entry != NULL);
  121. /* MBR partition table is in LBA0. */
  122. result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET);
  123. if (result != 0) {
  124. WARN("Failed to seek (%i)\n", result);
  125. return result;
  126. }
  127. result = io_read(image_handle, (uintptr_t)&mbr_sector,
  128. PLAT_PARTITION_BLOCK_SIZE, &bytes_read);
  129. if (result != 0) {
  130. WARN("Failed to read data (%i)\n", result);
  131. return result;
  132. }
  133. /* Check MBR boot signature. */
  134. if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) ||
  135. (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) {
  136. return -ENOENT;
  137. }
  138. offset = (uintptr_t)&mbr_sector +
  139. MBR_PRIMARY_ENTRY_OFFSET +
  140. MBR_PRIMARY_ENTRY_SIZE * part_number;
  141. memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t));
  142. return 0;
  143. }
  144. static int load_mbr_entries(uintptr_t image_handle)
  145. {
  146. mbr_entry_t mbr_entry;
  147. int i;
  148. list.entry_count = MBR_PRIMARY_ENTRY_NUMBER;
  149. for (i = 0; i < list.entry_count; i++) {
  150. load_mbr_entry(image_handle, &mbr_entry, i);
  151. list.list[i].start = mbr_entry.first_lba * 512;
  152. list.list[i].length = mbr_entry.sector_nums * 512;
  153. list.list[i].name[0] = mbr_entry.type;
  154. }
  155. return 0;
  156. }
  157. static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry)
  158. {
  159. size_t bytes_read;
  160. int result;
  161. assert(entry != NULL);
  162. result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t),
  163. &bytes_read);
  164. if (sizeof(gpt_entry_t) != bytes_read)
  165. return -EINVAL;
  166. return result;
  167. }
  168. static int verify_partition_gpt(uintptr_t image_handle)
  169. {
  170. gpt_entry_t entry;
  171. int result, i;
  172. for (i = 0; i < list.entry_count; i++) {
  173. result = load_gpt_entry(image_handle, &entry);
  174. assert(result == 0);
  175. result = parse_gpt_entry(&entry, &list.list[i]);
  176. if (result != 0) {
  177. break;
  178. }
  179. }
  180. if (i == 0) {
  181. return -EINVAL;
  182. }
  183. /*
  184. * Only records the valid partition number that is loaded from
  185. * partition table.
  186. */
  187. list.entry_count = i;
  188. dump_entries(list.entry_count);
  189. return 0;
  190. }
  191. int load_partition_table(unsigned int image_id)
  192. {
  193. uintptr_t dev_handle, image_handle, image_spec = 0;
  194. mbr_entry_t mbr_entry;
  195. int result;
  196. result = plat_get_image_source(image_id, &dev_handle, &image_spec);
  197. if (result != 0) {
  198. WARN("Failed to obtain reference to image id=%u (%i)\n",
  199. image_id, result);
  200. return result;
  201. }
  202. result = io_open(dev_handle, image_spec, &image_handle);
  203. if (result != 0) {
  204. WARN("Failed to access image id=%u (%i)\n", image_id, result);
  205. return result;
  206. }
  207. result = load_mbr_header(image_handle, &mbr_entry);
  208. if (result != 0) {
  209. WARN("Failed to access image id=%u (%i)\n", image_id, result);
  210. return result;
  211. }
  212. if (mbr_entry.type == PARTITION_TYPE_GPT) {
  213. result = load_gpt_header(image_handle);
  214. assert(result == 0);
  215. result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET);
  216. assert(result == 0);
  217. result = verify_partition_gpt(image_handle);
  218. } else {
  219. result = load_mbr_entries(image_handle);
  220. }
  221. io_close(image_handle);
  222. return result;
  223. }
  224. const partition_entry_t *get_partition_entry(const char *name)
  225. {
  226. int i;
  227. for (i = 0; i < list.entry_count; i++) {
  228. if (strcmp(name, list.list[i].name) == 0) {
  229. return &list.list[i];
  230. }
  231. }
  232. return NULL;
  233. }
  234. const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid)
  235. {
  236. int i;
  237. for (i = 0; i < list.entry_count; i++) {
  238. if (guidcmp(type_uuid, &list.list[i].type_guid) == 0) {
  239. return &list.list[i];
  240. }
  241. }
  242. return NULL;
  243. }
  244. const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid)
  245. {
  246. int i;
  247. for (i = 0; i < list.entry_count; i++) {
  248. if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) {
  249. return &list.list[i];
  250. }
  251. }
  252. return NULL;
  253. }
  254. const partition_entry_list_t *get_partition_entry_list(void)
  255. {
  256. return &list;
  257. }
  258. void partition_init(unsigned int image_id)
  259. {
  260. load_partition_table(image_id);
  261. }