mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-05 19:51:45 +00:00
[stage2] Add GPT parsing code (tested on PC)
This commit is contained in:
parent
437344fd25
commit
5b5aa38486
2 changed files with 134 additions and 0 deletions
91
fusee/fusee-secondary/src/gpt.c
Normal file
91
fusee/fusee-secondary/src/gpt.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "gpt.h"
|
||||
|
||||
int gpt_get_header(efi_header_t *out, FILE *disk) {
|
||||
union {
|
||||
uint8_t sector[512];
|
||||
efi_header_t hdr;
|
||||
} d;
|
||||
|
||||
if (disk == NULL || out == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read and check the protective MBR. */
|
||||
if (fread(d.sector, 512, 1, disk) == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (d.sector[0x1FE] != 0x55 || d.sector[0x1FF] != 0xAA) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We only allow for the GPT header to be at sector 1 (like nx-bootloader). */
|
||||
if (fread(d.sector, 512, 1, disk) == 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Check for "EFI PART". */
|
||||
if (memcmp(d.hdr.magic, "EFI PART", 8) != 0) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
/* Check whether we're really at sector 1, etc. (we won't check backup_lba). */
|
||||
if (d.hdr.header_lba != 1 || d.hdr.entries_first_lba < 2 || d.hdr.partitions_last_lba < d.hdr.partitions_first_lba) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
if (d.hdr.header_size < sizeof(efi_header_t) || d.hdr.entry_size < sizeof(efi_entry_t)) {
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
/* Some more checks: */
|
||||
if(d.hdr.header_size > 512 || d.hdr.revision != 0x10000) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(out, &d.hdr, sizeof(efi_header_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpt_iterate_through_entries(FILE *disk, gpt_entry_iterator_t callback) {
|
||||
efi_header_t hdr;
|
||||
efi_entry_t entry;
|
||||
size_t offset = 2 * 512; /* Sector #2. */
|
||||
size_t delta;
|
||||
|
||||
/* Get the header. */
|
||||
if (gpt_get_header(&hdr, disk) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Seek to the entry table. */
|
||||
if (fseek(disk, 512 * hdr.entries_first_lba - offset, SEEK_CUR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 512 * hdr.entries_first_lba;
|
||||
delta = hdr.entry_size - sizeof(efi_entry_t);
|
||||
|
||||
/* Iterate through the entries. */
|
||||
for (uint32_t i = 0; i < hdr.entry_count; i++) {
|
||||
if (fread(&entry, sizeof(efi_entry_t), 1, disk) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (callback(&entry, offset, disk) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (delta != 0 && fseek(disk, delta, SEEK_CUR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += hdr.entry_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
43
fusee/fusee-secondary/src/gpt.h
Normal file
43
fusee/fusee-secondary/src/gpt.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef FUSEE_GPT_H
|
||||
#define FUSEE_GPT_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct efi_entry_t {
|
||||
uint8_t type_uuid[16];
|
||||
uint8_t unique_uuid[16];
|
||||
uint64_t first_lba;
|
||||
uint64_t last_lba; /* Inclusive */
|
||||
uint64_t attributes;
|
||||
uint16_t name[36];
|
||||
} efi_entry_t;
|
||||
|
||||
typedef struct efi_header {
|
||||
uint8_t magic[8]; /* Must be "EFI PART" */
|
||||
uint32_t revision;
|
||||
|
||||
uint32_t header_size; /* Usually and at most 92 bytes. */
|
||||
uint32_t header_crc32; /* 0 during the computation */
|
||||
uint32_t reserved; /* Must be 0. */
|
||||
|
||||
uint64_t header_lba;
|
||||
uint64_t backup_lba;
|
||||
uint64_t partitions_first_lba;
|
||||
uint64_t partitions_last_lba;
|
||||
|
||||
uint8_t disk_guid[16];
|
||||
|
||||
uint64_t entries_first_lba;
|
||||
uint32_t entry_count;
|
||||
uint32_t entry_size;
|
||||
uint32_t entries_crc32;
|
||||
} __attribute__((packed, aligned(4))) efi_header_t;
|
||||
|
||||
typedef int (*gpt_entry_iterator_t)(const efi_entry_t *entry, size_t entry_offset, FILE *disk);
|
||||
|
||||
int gpt_get_header(efi_header_t *out, FILE *disk);
|
||||
int gpt_iterate_through_entries(FILE *disk, gpt_entry_iterator_t callback);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue