Files
nt-lite/code/common/boot_volume_selector.c

100 lines
3.2 KiB
C

// Shared parser for the canonical structural boot-volume selector grammar.
#include <common/boot_volume_selector.h>
#include <string.h>
// Converts one hexadecimal character without accepting non-hexadecimal text.
static bool BootVolumeHexDigit(char c, uint8_t* digitOut) {
if (!digitOut)
return false;
if (c >= '0' && c <= '9') {
*digitOut = (uint8_t)(c - '0');
return true;
}
if (c >= 'a' && c <= 'f') {
*digitOut = (uint8_t)(10 + c - 'a');
return true;
}
if (c >= 'A' && c <= 'F') {
*digitOut = (uint8_t)(10 + c - 'A');
return true;
}
return false;
}
// Parses an exact hexadecimal integer span into a 32-bit value.
static bool BootVolumeParseHex32(const char* text, size_t length, uint32_t* valueOut) {
if (!text || !valueOut || length == 0 || length > 8)
return false;
uint32_t value = 0;
for (size_t i = 0; i < length; ++i) {
uint8_t digit = 0;
if (!BootVolumeHexDigit(text[i], &digit))
return false;
value = (value << 4) | digit;
}
*valueOut = value;
return true;
}
// Parses one exact GUID hexadecimal group.
static bool BootVolumeParseGuidGroup(const char* text, size_t length, uint32_t* valueOut) {
return BootVolumeParseHex32(text, length, valueOut);
}
// Parses a canonical 8-4-4-4-12 GUID into EFI/GPT field layout.
static bool BootVolumeParseGuid(const char* text, size_t length, BOOT_VOLUME_GUID* guidOut) {
if (!text || !guidOut || length != 36 ||
text[8] != '-' || text[13] != '-' || text[18] != '-' || text[23] != '-') {
return false;
}
BOOT_VOLUME_GUID guid = {0};
uint32_t value = 0;
if (!BootVolumeParseGuidGroup(text, 8, &guid.Data1) ||
!BootVolumeParseGuidGroup(text + 9, 4, &value)) {
return false;
}
guid.Data2 = (uint16_t)value;
if (!BootVolumeParseGuidGroup(text + 14, 4, &value))
return false;
guid.Data3 = (uint16_t)value;
const size_t byteOffsets[8] = {19, 21, 24, 26, 28, 30, 32, 34};
for (size_t i = 0; i < 8; ++i) {
if (!BootVolumeParseGuidGroup(text + byteOffsets[i], 2, &value))
return false;
guid.Data4[i] = (uint8_t)value;
}
*guidOut = guid;
return true;
}
// Parses one canonical structural system-volume selector.
bool BootVolumeSelectorParse(const char* text, size_t length, BOOT_VOLUME_SELECTOR* selectorOut) {
if (!text || !selectorOut)
return false;
BOOT_VOLUME_SELECTOR selector = {0};
if (length == 14 && memcmp(text, "mbr/", 4) == 0 && text[12] == '/' &&
BootVolumeParseHex32(text + 4, 8, &selector.Identity.Mbr.DiskSignature) &&
text[13] >= '1' && text[13] <= '4') {
selector.Kind = BootVolumeSelectorMbr;
selector.Identity.Mbr.PartitionNumber = (uint32_t)(text[13] - '0');
*selectorOut = selector;
return true;
}
if (length == 40 && memcmp(text, "gpt/", 4) == 0 &&
BootVolumeParseGuid(text + 4, 36, &selector.Identity.Gpt.PartitionGuid)) {
selector.Kind = BootVolumeSelectorGpt;
*selectorOut = selector;
return true;
}
return false;
}