From 9e8f937437083a330f440629007ec1ce13221d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 28 Jan 2013 22:42:01 +0100 Subject: [PATCH] gpt: Added some missing pieces of supporting the backup header. * The alternate block was not set correctly. * The CRC of the backup header was never updated. * We now dump both headers. --- .../partitioning_systems/gpt/Header.cpp | 55 ++++++++++++------- .../kernel/partitioning_systems/gpt/Header.h | 3 +- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/add-ons/kernel/partitioning_systems/gpt/Header.cpp b/src/add-ons/kernel/partitioning_systems/gpt/Header.cpp index 96a952c359e..289f926adad 100644 --- a/src/add-ons/kernel/partitioning_systems/gpt/Header.cpp +++ b/src/add-ons/kernel/partitioning_systems/gpt/Header.cpp @@ -55,6 +55,12 @@ Header::Header(int fd, uint64 lastBlock, uint32 blockSize) fStatus = B_BAD_DATA; } + if (fStatus == B_OK && lastBlock != fHeader.AlternateBlock()) { + dprintf("gpt: alternate header not in last block (%" B_PRIu64 " vs. %" + B_PRIu64 ")\n", fHeader.AlternateBlock(), lastBlock); + lastBlock = fHeader.AlternateBlock(); + } + // Read backup header, too status_t status = _Read(fd, lastBlock * blockSize, &fBackupHeader, sizeof(efi_table_header)); @@ -72,6 +78,7 @@ Header::Header(int fd, uint64 lastBlock, uint32 blockSize) fHeader = fBackupHeader; fHeader.SetAbsoluteBlock(EFI_HEADER_LOCATION); fHeader.SetEntriesBlock(EFI_PARTITION_ENTRIES_BLOCK); + fHeader.SetAlternateBlock(lastBlock); } else if (status != B_OK) { // Recreate backup header from primary _SetBackupHeaderFromPrimary(lastBlock); @@ -105,7 +112,8 @@ Header::Header(int fd, uint64 lastBlock, uint32 blockSize) // TODO: check overlapping or out of range partitions #ifdef TRACE_EFI_GPT - _Dump(); + _Dump(fHeader); + _Dump(fBackupHeader); _DumpPartitions(); #endif @@ -153,7 +161,7 @@ Header::Header(uint64 lastBlock, uint32 blockSize) _SetBackupHeaderFromPrimary(lastBlock); #ifdef TRACE_EFI_GPT - _Dump(); + _Dump(fHeader); _DumpPartitions(); #endif @@ -253,9 +261,17 @@ Header::_Write(int fd, off_t offset, const void* data, size_t size) const void Header::_UpdateCRC() { - fHeader.SetEntriesCRC(crc32(fEntries, _EntryArraySize())); - fHeader.SetHeaderCRC(0); - fHeader.SetHeaderCRC(crc32((uint8*)&fHeader, sizeof(efi_table_header))); + _UpdateCRC(fHeader); + _UpdateCRC(fBackupHeader); +} + + +void +Header::_UpdateCRC(efi_table_header& header) +{ + header.SetEntriesCRC(crc32(fEntries, _EntryArraySize())); + header.SetHeaderCRC(0); + header.SetHeaderCRC(crc32((uint8*)&header, sizeof(efi_table_header))); } #endif // !_BOOT_MODE @@ -310,6 +326,7 @@ Header::_SetBackupHeaderFromPrimary(uint64 lastBlock) fBackupHeader.SetAbsoluteBlock(lastBlock); fBackupHeader.SetEntriesBlock( lastBlock - _EntryArraySize() / fBlockSize); + fBackupHeader.SetAlternateBlock(1); } @@ -329,21 +346,21 @@ Header::_PrintGUID(const guid_t &id) void -Header::_Dump() +Header::_Dump(const efi_table_header& header) { - dprintf("EFI header: %.8s\n", fHeader.header); - dprintf("EFI revision: %" B_PRIx32 "\n", fHeader.Revision()); - dprintf("header size: %ld\n", fHeader.HeaderSize()); - dprintf("header CRC: %ld\n", fHeader.HeaderCRC()); - dprintf("absolute block: %Ld\n", fHeader.AbsoluteBlock()); - dprintf("alternate block: %Ld\n", fHeader.AlternateBlock()); - dprintf("first usable block: %Ld\n", fHeader.FirstUsableBlock()); - dprintf("last usable block: %Ld\n", fHeader.LastUsableBlock()); - dprintf("disk GUID: %s\n", _PrintGUID(fHeader.disk_guid)); - dprintf("entries block: %Ld\n", fHeader.EntriesBlock()); - dprintf("entry size: %ld\n", fHeader.EntrySize()); - dprintf("entry count: %ld\n", fHeader.EntryCount()); - dprintf("entries CRC: %ld\n", fHeader.EntriesCRC()); + dprintf("EFI header: %.8s\n", header.header); + dprintf("EFI revision: %" B_PRIx32 "\n", header.Revision()); + dprintf("header size: %ld\n", header.HeaderSize()); + dprintf("header CRC: %ld\n", header.HeaderCRC()); + dprintf("absolute block: %Ld\n", header.AbsoluteBlock()); + dprintf("alternate block: %Ld\n", header.AlternateBlock()); + dprintf("first usable block: %Ld\n", header.FirstUsableBlock()); + dprintf("last usable block: %Ld\n", header.LastUsableBlock()); + dprintf("disk GUID: %s\n", _PrintGUID(header.disk_guid)); + dprintf("entries block: %Ld\n", header.EntriesBlock()); + dprintf("entry size: %ld\n", header.EntrySize()); + dprintf("entry count: %ld\n", header.EntryCount()); + dprintf("entries CRC: %ld\n", header.EntriesCRC()); } diff --git a/src/add-ons/kernel/partitioning_systems/gpt/Header.h b/src/add-ons/kernel/partitioning_systems/gpt/Header.h index e1bb020edd8..f6781c642b4 100644 --- a/src/add-ons/kernel/partitioning_systems/gpt/Header.h +++ b/src/add-ons/kernel/partitioning_systems/gpt/Header.h @@ -48,6 +48,7 @@ class Header { status_t _Write(int fd, off_t offset, const void* data, size_t size) const; void _UpdateCRC(); + void _UpdateCRC(efi_table_header& header); #endif status_t _Read(int fd, off_t offset, void* data, @@ -62,7 +63,7 @@ class Header { * fHeader.EntryCount(); } const char* _PrintGUID(const guid_t& id); - void _Dump(); + void _Dump(const efi_table_header& header); void _DumpPartitions(); private: