Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

713 lines
19 KiB

  1. /*
  2. Gpt - Guid Partition Table routines
  3. */
  4. #include "diskpart.h"
  5. BOOLEAN Debug = TRUE;
  6. EFI_STATUS WriteShadowMBR(EFI_HANDLE DiskHandle);
  7. EFI_STATUS
  8. ReadGPT(
  9. EFI_HANDLE DiskHandle,
  10. PGPT_HEADER *Header,
  11. PGPT_TABLE *Table,
  12. PLBA_BLOCK *LbaBlock,
  13. UINTN *DiskType
  14. )
  15. /*
  16. *Header, *Table, *LbaBlock will either be NULL or have a pointer.
  17. If they have pointers, caller is expected to free them with DoFree();
  18. RAW and MBR stuff is NOT DONE.
  19. DISK_RAW - no known partition scheme on the disk
  20. DISK_MBR - an MBR/Legacy disk
  21. DISK_GPT - a GPT style disk
  22. DISK_GPT_UPD - a GPT disk with inconsistent partition tables
  23. that need to be fixed up (may also need MBR rewrite)
  24. DISK_GPT_BAD - a GPT disk that is hopeless (or a hopeless disk
  25. that we think is a GPT disk)
  26. */
  27. {
  28. #define MBR_STATE_RAW 0
  29. #define MBR_STATE_MBR 1
  30. #define MBR_STATE_GPT 2
  31. UINTN MbrState = MBR_STATE_RAW;
  32. UINT32 BlockSize;
  33. UINT64 DiskSize;
  34. VOID *p = NULL;
  35. PGPT_HEADER h1 = NULL;
  36. PGPT_HEADER h2 = NULL;
  37. PGPT_TABLE t1 = NULL;
  38. PGPT_TABLE t2 = NULL;
  39. PLBA_BLOCK lba = NULL;
  40. UINT32 h1crc;
  41. UINT32 h2crc;
  42. UINT32 newcrc;
  43. UINT32 TableSize;
  44. UINT32 TableBlocks;
  45. BOOLEAN PartialGPT = FALSE;
  46. MBR_ENTRY *MbrTable;
  47. UINT16 *MbrSignature;
  48. BOOLEAN H1T1good = TRUE;
  49. BOOLEAN H2T2good = TRUE;
  50. BlockSize = GetBlockSize(DiskHandle);
  51. DiskSize = GetDiskSize(DiskHandle);
  52. //
  53. // Assure that DoFree will notice uninited returns...
  54. //
  55. *Header = NULL;
  56. *Table = NULL;
  57. *LbaBlock = NULL;
  58. *DiskType = DISK_ERROR;
  59. status = EFI_SUCCESS;
  60. p = DoAllocate(BlockSize);
  61. if (p == NULL) goto ErrorMem;
  62. //
  63. // Read the MBR, if we can't read that, assume
  64. // we're in deep trouble (MBR is always block 0, 1 block long)
  65. //
  66. status = ReadBlock(DiskHandle, p, (UINT64)0, BlockSize);
  67. if (EFI_ERROR(status)) goto ErrorRead;
  68. MbrTable = (MBR_ENTRY *)((CHAR8 *)p + MBR_TABLE_OFFSET);
  69. MbrSignature = (UINT16 *)((CHAR8 *)p + MBR_SIGNATURE_OFFSET);
  70. if (*MbrSignature == MBR_SIGNATURE) { // 0xaa55
  71. //
  72. // There's an MBR signature, so assume NOT RAW
  73. //
  74. //
  75. // If we find a type 0xEE in the first slot, we'll assume
  76. // it's a GPT Shadow MBR. Otherwise we think it's an old MBR.
  77. // But code below will account for GPT structures as well
  78. //
  79. if (MbrTable[0].PartitionType == PARTITION_TYPE_GPT_SHADOW) { // 0xEE
  80. //
  81. // Well, that type should never occur anywhere else,
  82. // so assume it's a GPT Shadow regardless of how it's set
  83. //
  84. MbrState = MBR_STATE_GPT;
  85. } else {
  86. //
  87. // It's not RAW (there's a signature) and it's not
  88. // GPT Shadow MBR (no 0xEE for Table[0] type
  89. // So, assume it's an MBR and we're done
  90. //
  91. *DiskType = DISK_MBR;
  92. DoFree(p);
  93. p = NULL;
  94. return EFI_SUCCESS;
  95. }
  96. } else {
  97. *DiskType = DISK_RAW; // if we don't find more...
  98. }
  99. //
  100. // ----- h1/t1 ------------------------------------------------
  101. //
  102. //
  103. // Read Header1. If cannot *read* it, punt.
  104. // First header is always at Block 1, 1 block long
  105. //
  106. h1 = p;
  107. p = NULL;
  108. status = ReadBlock(DiskHandle, h1, 1, BlockSize);
  109. if (EFI_ERROR(status)) goto ErrorRead;
  110. //
  111. // h1 => header1
  112. //
  113. if ( (h1->Signature != GPT_HEADER_SIGNATURE) ||
  114. (h1->Revision != GPT_REVISION_1_0) ||
  115. (h1->HeaderSize != sizeof(GPT_HEADER)) ||
  116. (h1->SizeOfGPT_ENTRY != sizeof(GPT_ENTRY)) )
  117. {
  118. H1T1good = FALSE;
  119. if (DebugLevel >= DEBUG_ERRPRINT) {
  120. Print(L"GPT header 1 is incorrect with status %x\n",
  121. (h1->Signature != GPT_HEADER_SIGNATURE)*1 +
  122. (h1->Revision != GPT_REVISION_1_0)*2 +
  123. (h1->HeaderSize != sizeof(GPT_HEADER))*4 +
  124. (h1->SizeOfGPT_ENTRY != sizeof(GPT_ENTRY))*8);
  125. }
  126. }
  127. h1crc = h1->HeaderCRC32;
  128. h1->HeaderCRC32 = 0;
  129. newcrc = GetCRC32(h1, sizeof(GPT_HEADER));
  130. h1->HeaderCRC32 = h1crc;
  131. if (h1crc != newcrc) {
  132. H1T1good = FALSE;
  133. if (DebugLevel >= DEBUG_ERRPRINT) {
  134. Print(L"GPT header 1 crc is incorrect\n");
  135. }
  136. }
  137. if (H1T1good) {
  138. PartialGPT = TRUE;
  139. }
  140. //
  141. // if header1 is bad, assume that table1 is bad too...
  142. //
  143. if (H1T1good) {
  144. TableSize = sizeof(GPT_ENTRY) * h1->EntriesAllocated;
  145. t1 = DoAllocate(TableSize);
  146. if (t1 == NULL) goto ErrorMem;
  147. //
  148. // OK, so how many BLOCKS long is the table?
  149. //
  150. TableBlocks = TableSize / BlockSize;
  151. //
  152. // if we cannot READ t1, punt...
  153. //
  154. status = ReadBlock(DiskHandle, t1, h1->TableLBA, TableSize);
  155. if (EFI_ERROR(status)) goto ErrorRead;
  156. newcrc = GetCRC32(t1, TableSize);
  157. if (h1->TableCRC32 != newcrc) {
  158. H1T1good = FALSE;
  159. if (DebugLevel >= DEBUG_ERRPRINT) {
  160. Print(L"GPT table 1 crc is incorrect\n");
  161. }
  162. }
  163. }
  164. //
  165. // ----- h2/t2 ------------------------------------------------
  166. //
  167. //
  168. // Read Header2. If cannot *read* it, punt.
  169. //
  170. h2 = DoAllocate(BlockSize);
  171. if (h2 == NULL) goto ErrorMem;
  172. //
  173. // Header2 is always 1 block long, last block on disk
  174. //
  175. status = ReadBlock(DiskHandle, h2, DiskSize-1, BlockSize);
  176. if (EFI_ERROR(status)) goto ErrorRead;
  177. //
  178. // h2 => header2
  179. //
  180. if ( (h2->Signature != GPT_HEADER_SIGNATURE) ||
  181. (h2->Revision != GPT_REVISION_1_0) ||
  182. (h2->HeaderSize != sizeof(GPT_HEADER)) ||
  183. (h2->SizeOfGPT_ENTRY != sizeof(GPT_ENTRY)) )
  184. {
  185. H2T2good = FALSE;
  186. if (DebugLevel >= DEBUG_ERRPRINT) {
  187. Print(L"GPT header 2 is incorrect with status %x\n",
  188. (h2->Signature != GPT_HEADER_SIGNATURE)*1 +
  189. (h2->Revision != GPT_REVISION_1_0)*2 +
  190. (h2->HeaderSize != sizeof(GPT_HEADER))*4 +
  191. (h2->SizeOfGPT_ENTRY != sizeof(GPT_ENTRY))*8);
  192. }
  193. }
  194. h2crc = h2->HeaderCRC32;
  195. h2->HeaderCRC32 = 0;
  196. newcrc = GetCRC32(h2, sizeof(GPT_HEADER));
  197. h2->HeaderCRC32 = h2crc;
  198. if (h2crc != newcrc) {
  199. H2T2good = FALSE;
  200. if (DebugLevel >= DEBUG_ERRPRINT) {
  201. Print(L"GPT header 2 crc is incorrect\n");
  202. }
  203. }
  204. if (H2T2good) {
  205. PartialGPT = TRUE;
  206. }
  207. //
  208. // if header2 is bad, assume that table2 is bad too...
  209. //
  210. if (H2T2good) {
  211. TableSize = sizeof(GPT_ENTRY) * h2->EntriesAllocated;
  212. t2 = DoAllocate(TableSize);
  213. if (t2 == NULL) goto ErrorMem;
  214. //
  215. // OK, so how many BLOCKS long is the table?
  216. //
  217. TableBlocks = TableSize / BlockSize;
  218. //
  219. // if we cannot READ t2, punt...
  220. //
  221. status = ReadBlock(DiskHandle, t2, h2->TableLBA, TableSize);
  222. if (EFI_ERROR(status)) goto ErrorRead;
  223. newcrc = GetCRC32(t2, TableSize);
  224. if (h2->TableCRC32 != newcrc) {
  225. H2T2good = FALSE;
  226. if (DebugLevel >= DEBUG_ERRPRINT) {
  227. Print(L"GPT table 2 crc is incorrect\n");
  228. }
  229. }
  230. }
  231. //
  232. // ------ analysis --------------------------------------------------
  233. //
  234. // since we are here:
  235. // h1 -> header1, t1 -> table1, H1T1good indicates state
  236. // h2 -> header2, t2 -> table2, H2T2good indicates state
  237. //
  238. lba = (PLBA_BLOCK)DoAllocate(sizeof(LBA_BLOCK));
  239. if (lba == NULL) goto ErrorMem;
  240. lba->Header1_LBA = 1;
  241. lba->Table1_LBA = h1->TableLBA;
  242. lba->Header2_LBA = (DiskSize - 1);
  243. lba->Table2_LBA = h2->TableLBA;
  244. if (H1T1good) {
  245. *Header = h1;
  246. *Table = t1;
  247. *LbaBlock = lba;
  248. if ( (H2T2good) &&
  249. (h1->AlternateLBA == (DiskSize-1)) &&
  250. (CompareMem(t1, t2, TableSize) == 0)
  251. )
  252. {
  253. *DiskType = DISK_GPT;
  254. } else {
  255. *DiskType = DISK_GPT_UPD;
  256. if (DebugLevel >= DEBUG_ERRPRINT) {
  257. Print(L"GPT partition table 1 checked out but table 2 is inconsistent with table 1\n");
  258. }
  259. }
  260. DoFree(h2);
  261. h2 = NULL;
  262. DoFree(t2);
  263. t2 = NULL;
  264. status = EFI_SUCCESS;
  265. return status;
  266. }
  267. if (H2T2good) {
  268. // since we're here, H1T1good is FALSE...
  269. *Header = h2;
  270. *Table = t2;
  271. *LbaBlock = lba;
  272. DoFree(h1);
  273. h1 = NULL;
  274. DoFree(t1);
  275. t1 = NULL;
  276. *DiskType = DISK_GPT_UPD;
  277. if (DebugLevel >= DEBUG_ERRPRINT) {
  278. Print(L"GPT partition table 2 checked out but table 1 is not good\n");
  279. }
  280. return EFI_SUCCESS;
  281. }
  282. //
  283. // Since we're HERE, H1T1good AND H2T2good are BOTH false.
  284. // Unless the shadow MBR says it's a GPT disk, claim it's raw.
  285. // If we did see a shadow, or GPT partial is set, say it's a bad GPT
  286. //
  287. if ( (PartialGPT) || (MbrState == MBR_STATE_GPT) ) {
  288. //
  289. // At least one of the headers looked OK,
  290. // OR
  291. // There's an MBR that looks like a GPT shadow MBR
  292. // SO
  293. // Report DISK_GPT_BAD
  294. //
  295. *DiskType = DISK_GPT_BAD;
  296. goto ExitRet;
  297. } else {
  298. //
  299. // It's not an MBR disk, or we wouldn't have gotten here
  300. //
  301. *DiskType = DISK_RAW;
  302. goto ExitRet;
  303. }
  304. ErrorMem:
  305. status = EFI_OUT_OF_RESOURCES;
  306. goto ExitRet;
  307. ErrorRead:
  308. status = EFI_DEVICE_ERROR;
  309. ExitRet:
  310. DoFree(p);
  311. DoFree(h1);
  312. DoFree(t1);
  313. DoFree(h2);
  314. DoFree(t2);
  315. DoFree(lba);
  316. return status;
  317. }
  318. EFI_STATUS
  319. WriteGPT(
  320. EFI_HANDLE DiskHandle,
  321. PGPT_HEADER Header,
  322. PGPT_TABLE Table,
  323. PLBA_BLOCK LbaBlock
  324. )
  325. /*
  326. CALLER is expected to fill in:
  327. FirstUseableLBA
  328. LastUseableLBA
  329. EntryCount
  330. DiskGUID
  331. We fill in the rest, and blast it out.
  332. Returns a status.
  333. */
  334. {
  335. UINT32 BlockSize;
  336. UINT32 TableSize;
  337. UINT32 TableBlocks;
  338. status = EFI_SUCCESS;
  339. BlockSize = GetBlockSize(DiskHandle);
  340. TableSize = Header->EntriesAllocated * sizeof(GPT_ENTRY);
  341. WriteShadowMBR(DiskHandle);
  342. //
  343. // Write out the primary header...
  344. //
  345. Header->Signature = GPT_HEADER_SIGNATURE;
  346. Header->Revision = GPT_REVISION_1_0;
  347. Header->HeaderSize = sizeof(GPT_HEADER);
  348. Header->MyLBA = LbaBlock->Header1_LBA;
  349. Header->AlternateLBA = LbaBlock->Header2_LBA;
  350. Header->TableLBA = LbaBlock->Table1_LBA;
  351. Header->SizeOfGPT_ENTRY = sizeof(GPT_ENTRY);
  352. Header->TableCRC32 = GetCRC32(Table, TableSize);
  353. Header->HeaderCRC32 = 0;
  354. Header->HeaderCRC32 = GetCRC32(Header, sizeof(GPT_HEADER));
  355. if (DebugLevel >= DEBUG_ARGPRINT) {
  356. Print(L"\nWriteGPT\n DiskHandle = %8X\n", DiskHandle);
  357. Print(L" Header=%X\n", Header);
  358. Print(L" Signature=%lX\n Revision=%X HeaderSize=%X HeaderCRC=%X\n",
  359. Header->Signature, Header->Revision, Header->HeaderSize, Header->HeaderCRC32);
  360. Print(L" MyLBA=%lX AltLBA=%lX\n", Header->MyLBA, Header->AlternateLBA);
  361. Print(L" FirstUsable=%lX Last=%lX\n", Header->FirstUsableLBA, Header->LastUsableLBA);
  362. Print(L" TableLBA=%lX\n", Header->TableLBA);
  363. }
  364. status = WriteBlock(DiskHandle, Header, LbaBlock->Header1_LBA, BlockSize);
  365. if (EFI_ERROR(status)) return status;
  366. //
  367. // Write out the primary table ...
  368. //
  369. TableBlocks = TableSize / BlockSize;
  370. status = WriteBlock(DiskHandle, Table, LbaBlock->Table1_LBA, TableSize);
  371. if (EFI_ERROR(status)) return status;
  372. //
  373. // Write out the secondary header ...
  374. //
  375. Header->MyLBA = LbaBlock->Header2_LBA;
  376. Header->AlternateLBA = 0;
  377. Header->TableLBA = LbaBlock->Table2_LBA;
  378. Header->HeaderCRC32 = 0;
  379. Header->HeaderCRC32 = GetCRC32(Header, sizeof(GPT_HEADER));
  380. status = WriteBlock(DiskHandle, Header, LbaBlock->Header2_LBA, BlockSize);
  381. if (EFI_ERROR(status)) return status;
  382. //
  383. // write out the secondary table ..
  384. //
  385. TableBlocks = TableSize / BlockSize;
  386. status = WriteBlock(DiskHandle, Table, LbaBlock->Table2_LBA, TableSize);
  387. FlushBlock(DiskHandle);
  388. return status;
  389. }
  390. EFI_STATUS
  391. WriteShadowMBR(
  392. EFI_HANDLE DiskHandle
  393. )
  394. /*
  395. WriteShadowMBR writes out a GPT shadow master boot record,
  396. which means an MBR full of zeros except:
  397. a. It has the 0xaa55 signature at 0x1fe
  398. b. It has a single partition entry of type 'EE'...
  399. */
  400. {
  401. UINT32 BlockSize;
  402. UINT8 *MbrBlock;
  403. UINT64 DiskSize;
  404. MBR_ENTRY UNALIGNED *MbrEntry = NULL;
  405. UINT16 UNALIGNED *MbrSignature;
  406. BlockSize = GetBlockSize(DiskHandle);
  407. MbrBlock = DoAllocate(BlockSize);
  408. if (MbrBlock == NULL) {
  409. status = EFI_OUT_OF_RESOURCES;
  410. return status;
  411. }
  412. ZeroMem(MbrBlock, BlockSize);
  413. DiskSize = GetDiskSize(DiskHandle);
  414. if (DiskSize > 0xffffffff) {
  415. DiskSize = 0xffffffff;
  416. }
  417. MbrEntry = (MBR_ENTRY *)(MbrBlock + MBR_TABLE_OFFSET);
  418. MbrEntry->ActiveFlag = 0;
  419. MbrEntry->PartitionType = PARTITION_TYPE_GPT_SHADOW;
  420. MbrEntry->StartingSector = 1;
  421. MbrEntry->PartitionLength = (UINT32)DiskSize - MbrEntry->StartingSector;
  422. //
  423. // We don't actually know this data, so we'll make up
  424. // something that seems likely.
  425. //
  426. //
  427. // Old software is expecting the Partition to start on
  428. // a Track boundary, so we'll set track to 1 to avoid "overlay"
  429. // with the MBR
  430. //
  431. MbrEntry->StartingTrack = 1;
  432. MbrEntry->StartingCylinderLsb = 0;
  433. MbrEntry->StartingCylinderMsb = 0;
  434. MbrEntry->EndingTrack = 0xff;
  435. MbrEntry->EndingCylinderLsb = 0xff;
  436. MbrEntry->EndingCylinderMsb = 0xff;
  437. MbrSignature = (UINT16 *)(MbrBlock + MBR_SIGNATURE_OFFSET);
  438. *MbrSignature = BOOT_RECORD_SIGNATURE;
  439. status = WriteBlock(DiskHandle, MbrBlock, 0, BlockSize);
  440. DoFree(MbrBlock);
  441. return status;
  442. }
  443. EFI_STATUS
  444. CreateGPT(
  445. EFI_HANDLE DiskHandle,
  446. UINTN EntryRequest
  447. )
  448. /*
  449. Write a new GPT table onto a clean disk
  450. When we get here, we assume the disk is clean, and
  451. that the user really wants to do this.
  452. DiskHandle - the disk we are going to write to
  453. EntryRequest - number of entries the user wants, ignored
  454. if less than our minimum, rounded up to number of entries
  455. that fill up the nearest sector. So, the user is
  456. says "at least" this many.
  457. Ignored if > 1024. (At least for now)
  458. NOTE:
  459. Even though the disk is in theory all zeros from
  460. having been cleaned, we actually rewrite all the data,
  461. just in case somebody fooled the detector code...
  462. */
  463. {
  464. UINTN EntryCount;
  465. UINTN BlockFit;
  466. UINTN BlockSize;
  467. UINTN EntryBlocks;
  468. UINT64 DiskSize;
  469. LBA_BLOCK LbaBlock;
  470. PGPT_HEADER Header;
  471. PGPT_TABLE Table;
  472. UINTN TableSize;
  473. EFI_LBA Header1_LBA;
  474. EFI_LBA Table1_LBA;
  475. EFI_LBA Header2_LBA;
  476. EFI_LBA Table2_LBA;
  477. EFI_LBA FirstUsableLBA;
  478. EFI_LBA LastUsableLBA;
  479. //
  480. // BlockSize is the block/sector size, in bytes.
  481. // It is assumed to be a power of 2 and >= 512
  482. //
  483. BlockSize = GetBlockSize(DiskHandle);
  484. //
  485. // DiskSize is a Count (1 based, not 0 based) of
  486. // software visible blocks on the disk. We assume
  487. // we may address them as 0 to DiskSize-1.
  488. //
  489. DiskSize = GetDiskSize(DiskHandle);
  490. //
  491. // By default, we support the max of 32 entries or
  492. // BlockSize/sizeof(GPT_ENTRY). (Meaning there will
  493. // always be at least 32 entries and always be at least
  494. // enough entries to fill 1 sector)
  495. // If the user asks for more than that, but less than
  496. // the sanity threshold, we give the user what they asked
  497. // for, rounded up to BlockSize/sizeof(GPT_ENTRY)
  498. //
  499. EntryCount = ENTRY_DEFAULT;
  500. BlockFit = BlockSize/sizeof(GPT_ENTRY);
  501. if (BlockFit > ENTRY_DEFAULT) {
  502. EntryCount = BlockFit;
  503. }
  504. if (EntryRequest > EntryCount) {
  505. if (EntryRequest <= ENTRY_SANITY_LIMIT) { // 1024
  506. EntryCount = ((EntryRequest + BlockFit) / BlockFit) * BlockFit;
  507. if ((EntryCount < EntryRequest) ||
  508. (EntryCount < ENTRY_DEFAULT) ||
  509. (EntryCount < BlockFit))
  510. {
  511. TerribleError(L"CreateGPT is terribly confused\n");
  512. }
  513. }
  514. }
  515. EntryBlocks = EntryCount / BlockFit;
  516. if ((EntryBlocks * BlockFit) != EntryCount) {
  517. TerribleError(L"CreateGPT is terribly confused, spot #2\n");
  518. }
  519. Header1_LBA = 1;
  520. Table1_LBA = 2;
  521. FirstUsableLBA = Table1_LBA + EntryBlocks;
  522. Header2_LBA = DiskSize - 1;
  523. Table2_LBA = Header2_LBA - EntryBlocks;
  524. LastUsableLBA = Table2_LBA - 1;
  525. TableSize = EntryBlocks * BlockSize;
  526. if (TableSize != (EntryCount * sizeof(GPT_ENTRY))) {
  527. TerribleError(L"CreateGPT is terribly confused, spot #3\n");
  528. }
  529. if (DebugLevel >= DEBUG_ARGPRINT) {
  530. Print(L"DiskSize = %lx\n", DiskSize);
  531. Print(L"BlockSize = %x\n", BlockSize);
  532. Print(L"Header1_LBA = %lx\n", Header1_LBA);
  533. Print(L"Table1_LBA = %lx\n", Table1_LBA);
  534. Print(L"FirstUsableLBA = %lx\n", FirstUsableLBA);
  535. Print(L"Header2_LBA = %lx\n", Header2_LBA);
  536. Print(L"Table2_LBA = %lx\n", Table2_LBA);
  537. Print(L"LastUsableLBA = %lx\n", LastUsableLBA);
  538. Print(L"EntryCount = %x\n", EntryCount);
  539. Print(L"EntryBlocks = %x\n", EntryBlocks);
  540. }
  541. //
  542. // OK, from this point it's just filling in structures
  543. // and writing them out.
  544. //
  545. Header = (PGPT_HEADER)DoAllocate(BlockSize);
  546. if (Header == NULL) {
  547. return EFI_OUT_OF_RESOURCES;
  548. }
  549. ZeroMem(Header, BlockSize);
  550. //
  551. // Since we're making empty tables, we just write zeros...
  552. //
  553. Table = (PGPT_TABLE)DoAllocate(TableSize);
  554. if (Table == NULL) {
  555. DoFree(Header);
  556. Header = NULL;
  557. return EFI_OUT_OF_RESOURCES;
  558. }
  559. ZeroMem(Table, TableSize);
  560. //
  561. // Fill in the things that WriteGPT doesn't understand
  562. //
  563. Header->FirstUsableLBA = FirstUsableLBA;
  564. Header->LastUsableLBA = LastUsableLBA;
  565. Header->EntriesAllocated = (UINT32)EntryCount;
  566. Header->DiskGUID = GetGUID();
  567. LbaBlock.Header1_LBA = Header1_LBA;
  568. LbaBlock.Header2_LBA = Header2_LBA;
  569. LbaBlock.Table1_LBA = Table1_LBA;
  570. LbaBlock.Table2_LBA = Table2_LBA;
  571. status = WriteGPT(
  572. DiskHandle,
  573. Header,
  574. Table,
  575. &LbaBlock
  576. );
  577. DoFree(Header);
  578. DoFree(Table);
  579. return status;
  580. }