3#include "pedigree/kernel/Log.h"
4#include "pedigree/kernel/machine/Disk.h"
5#include "pedigree/kernel/utilities/StaticString.h"
6#include "pedigree/kernel/utilities/new"
7#include "pedigree/kernel/utilities/utility.h"
12bool copy(
Disk* disk, uint64_t offset, uint8_t* data,
size_t bytes) {
17 const size_t count = bytes < view.size() ? bytes : view.size();
22 MemoryCopy(data, view.data(), count);
30String partitionName(
const uint8_t* entry,
size_t stride) {
34 const size_t units = min(
static_cast<size_t>(36), (stride - 56) / 2);
35 for (
size_t i = 0; i < units; ++i) {
36 uint32_t character = Gpt::little(entry + 56 + i * 2, 2);
39 if (character >= 0xd800 && character <= 0xdbff) {
41 const uint32_t low = Gpt::little(entry + 56 + (i + 1) * 2, 2);
42 if (low >= 0xdc00 && low <= 0xdfff) {
43 character = 0x10000 + ((character - 0xd800) << 10) + (low - 0xdc00);
51 }
else if (character >= 0xdc00 && character <= 0xdfff) {
60 result +=
String(utf8, length,
true);
64bool candidate(
Disk* disk,
size_t sectorBytes, uint64_t sectors,
bool backup) {
67 if (!copy(disk, (backup ? sectors - 1 : 1) * sectorBytes, bytes, sectorBytes) ||
68 !Gpt::decode(bytes, sectorBytes, sectors, backup, header))
70 auto* entries =
new uint8_t[header.bytes];
71 if (!copy(disk, header.table * sectorBytes, entries, header.bytes) ||
72 !Gpt::validEntries(entries, header)) {
76 for (
size_t i = 0; i < header.count; ++i) {
77 const uint8_t* entry = entries + i * header.stride;
78 if (!Gpt::used(entry))
82 const uint64_t first = Gpt::little(entry + 32, 8), last = Gpt::little(entry + 40, 8);
84 new Partition(
String(label), first * sectorBytes, (last - first + 1) * sectorBytes);
86 Gpt::formatGuid(entry + 16, uuid);
87 partition->setPartitionIdentity(
String(uuid), partitionName(entry, header.stride));
88 partition->setParent(disk);
92 NOTICE(
"GPT: validated " << (backup ?
"backup" :
"primary") <<
" table, logical sector " <<
Dec
93 << sectorBytes <<
Hex);
97bool gptProbeDisk(
Disk* disk) {
99 if (bytes < 512 || bytes > 4096 || (bytes & (bytes - 1)) || disk->
getSize() % bytes)
101 const uint64_t sectors = disk->
getSize() / bytes;
105 if (!copy(disk, 0, mbr,
sizeof(mbr)) || mbr[510] != 0x55 || mbr[511] != 0xaa)
107 bool protective =
false;
108 for (
size_t i = 0; i < 4; ++i)
109 protective |= mbr[446 + 16 * i + 4] == 0xee && Gpt::little(mbr + 446 + 16 * i + 8, 4) == 1;
113 if (!candidate(disk, bytes, sectors,
false) && !candidate(disk, bytes, sectors,
true))
114 WARNING(
"GPT: no valid primary or backup table");
void addChild(Device *pDevice)
virtual BufferView read(uint64_t location)
virtual size_t getSize() const
Gets the size of the disk.
virtual void unpin(uint64_t location)=0
virtual size_t getNativeBlockSize() const
static size_t Utf32ToUtf8(uint32_t utf32, char *utf8)