ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_fs_fat_gpt.c
Go to the documentation of this file.
1
18
19#include <stddef.h>
20#include <stdint.h>
21
22#include "ra8_attributes.h"
23#include "ra8_fs.h"
24#include "ra8_fs_fat_internal.h"
25
27static const uint8_t s_gpt_signature[k_gpt_sig_len] = {
28 0x45U,
29 0x46U,
30 0x49U,
31 0x20U,
32 0x50U,
33 0x41U,
34 0x52U,
35 0x54U,
36};
37
40static const uint8_t s_gpt_guid_basic_data[k_gpt_guid_len] = {
41 0xA2U,
42 0xA0U,
43 0xD0U,
44 0xEBU,
45 0xE5U,
46 0xB9U,
47 0x33U,
48 0x44U,
49 0x87U,
50 0xC0U,
51 0x68U,
52 0xB6U,
53 0xB7U,
54 0x26U,
55 0x99U,
56 0xC7U,
57};
58
78static uint64_t internal_gpt_entry_first_lba(const uint8_t* entry)
79{
80 uint32_t nonzero = 0U;
81 for (uint32_t i = 0U; i < (uint32_t)k_gpt_guid_len; i++) {
82 if (entry[i] != 0U) {
83 nonzero = 1U;
84 }
85 }
86 if (nonzero == 0U) {
87 return 0U;
88 }
90}
91
110static uint32_t internal_gpt_entry_is_basic_data(const uint8_t* entry)
111{
112 for (uint32_t i = 0U; i < (uint32_t)k_gpt_guid_len; i++) {
113 if (entry[i] != s_gpt_guid_basic_data[i]) {
114 return 0U;
115 }
116 }
117 return 1U;
118}
119
139static void internal_gpt_note_entry(const uint8_t* entry, uint64_t* basic_lba, uint64_t* any_lba)
140{
141 const uint64_t first = internal_gpt_entry_first_lba(entry);
142 if (first == 0U) {
143 return;
144 }
145 if (*any_lba == 0U) {
146 *any_lba = first;
147 }
148 if (*basic_lba == 0U) {
149 if (internal_gpt_entry_is_basic_data(entry) != 0U) {
150 *basic_lba = first;
151 }
152 }
153}
154
179 uint64_t entry_lba,
180 uint32_t count,
181 uint64_t* out_base)
182{
183 const uint32_t eps = priv_bps(m) / (uint32_t)k_gpt_entry_bytes;
184 uint64_t basic_lba = 0U;
185 uint64_t any_lba = 0U;
186 for (uint32_t i = 0U; i < count; i++) {
187 const uint32_t sector = i / eps;
188 const uint32_t offset = (i % eps) * (uint32_t)k_gpt_entry_bytes;
189 if (offset == 0U) {
190 const ra8_err_t err = priv_read_sector(m, entry_lba + sector, g_fs_scratch);
191 if (err != k_ra8_ok) {
192 return err;
193 }
194 }
195 internal_gpt_note_entry(&g_fs_scratch[offset], &basic_lba, &any_lba);
196 }
197 if (basic_lba != 0U) {
198 *out_base = basic_lba;
199 return k_ra8_ok;
200 }
201 if (any_lba != 0U) {
202 *out_base = any_lba;
203 return k_ra8_ok;
204 }
205 return k_ra8_err_not_found;
206}
207
233static ra8_err_t
234internal_gpt_read_geom(const ra8_fs_mount_t* m, uint64_t* out_entry_lba, uint32_t* out_count)
235{
236 const ra8_err_t err = priv_read_sector(m, (uint64_t)k_gpt_header_lba, g_fs_scratch);
237 if (err != k_ra8_ok) {
238 return err;
239 }
240 for (uint32_t i = 0U; i < (uint32_t)k_gpt_sig_len; i++) {
241 if (g_fs_scratch[i] != s_gpt_signature[i]) {
243 }
244 }
245 const uint64_t entry_lba = priv_rd64(&g_fs_scratch[k_gpt_off_entry_lba]);
246 const uint32_t entry_size = priv_rd32(&g_fs_scratch[k_gpt_off_entry_size]);
247 uint32_t count = priv_rd32(&g_fs_scratch[k_gpt_off_entry_count]);
248 if (entry_lba == 0U) {
250 }
251 if (entry_size != (uint32_t)k_gpt_entry_bytes) {
253 }
254 if (count > (uint32_t)k_gpt_entry_scan_max) {
255 count = (uint32_t)k_gpt_entry_scan_max;
256 }
257 *out_entry_lba = entry_lba;
258 *out_count = count;
259 return k_ra8_ok;
260}
261
262/* `priv_gpt_locate_volume()`: see header for the documented contract. */
264{
265 uint64_t entry_lba = 0U;
266 uint32_t count = 0U;
267 const ra8_err_t err = internal_gpt_read_geom(m, &entry_lba, &count);
268 if (err != k_ra8_ok) {
269 return err;
270 }
271 return internal_gpt_scan_entries(m, entry_lba, count, out_base);
272}
273
297static ra8_err_t internal_gpt_entry_select(const uint8_t* entry, uint64_t* out_base)
298{
299 uint32_t nonzero = 0U;
300 for (uint32_t i = 0U; i < (uint32_t)k_gpt_guid_len; i++) {
301 if (entry[i] != 0U) {
302 nonzero = 1U;
303 }
304 }
305 if (nonzero == 0U) {
306 return k_ra8_err_not_found;
307 }
308 const uint64_t base = priv_rd64(&entry[k_gpt_entry_off_first_lba]);
309 if (base == 0U) {
311 }
312 *out_base = base;
313 return k_ra8_ok;
314}
315
316/* `priv_gpt_locate_partition()`: see header for the documented contract. */
317ra8_err_t priv_gpt_locate_partition(const ra8_fs_mount_t* m, uint8_t index, uint64_t* out_base)
318{
319 uint64_t entry_lba = 0U;
320 uint32_t count = 0U;
321 const ra8_err_t err = internal_gpt_read_geom(m, &entry_lba, &count);
322 if (err != k_ra8_ok) {
323 return err;
324 }
325 if ((uint32_t)index >= count) {
327 }
328 const uint32_t eps = priv_bps(m) / (uint32_t)k_gpt_entry_bytes;
329 const uint32_t sector = (uint32_t)index / eps;
330 const uint32_t offset = ((uint32_t)index % eps) * (uint32_t)k_gpt_entry_bytes;
331 const ra8_err_t rerr = priv_read_sector(m, entry_lba + sector, g_fs_scratch);
332 if (rerr != k_ra8_ok) {
333 return rerr;
334 }
335 return internal_gpt_entry_select(&g_fs_scratch[offset], out_base);
336}
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
uint32_t priv_rd32(const uint8_t *p)
Decode a little-endian uint32_t from a byte buffer.
Definition ra8_fs_fat.c:48
ra8_err_t priv_read_sector(const ra8_fs_mount_t *m, uint64_t lba, uint8_t *buf)
Read a single sector into the module scratch buffer.
Definition ra8_fs_fat.c:134
uint32_t priv_bps(const ra8_fs_mount_t *m)
One mounted volume's sector size in bytes.
Definition ra8_fs_fat.c:84
uint64_t priv_rd64(const uint8_t *p)
Decode a little-endian uint64_t from a byte buffer.
Definition ra8_fs_fat.c:55
static uint32_t internal_gpt_entry_is_basic_data(const uint8_t *entry)
Test whether a GPT entry's type GUID is Microsoft Basic Data.
static ra8_err_t internal_gpt_read_geom(const ra8_fs_mount_t *m, uint64_t *out_entry_lba, uint32_t *out_count)
Read and validate the GPT header, returning the entry-array geometry.
static const uint8_t s_gpt_signature[k_gpt_sig_len]
GPT header signature ("EFI PART", UEFI spec 2.10 table 5.5).
static ra8_err_t internal_gpt_entry_select(const uint8_t *entry, uint64_t *out_base)
Extract the first LBA of one explicitly selected GPT entry.
static ra8_err_t internal_gpt_scan_entries(const ra8_fs_mount_t *m, uint64_t entry_lba, uint32_t count, uint64_t *out_base)
Read the GPT entry array sector-by-sector and pick a base LBA.
static void internal_gpt_note_entry(const uint8_t *entry, uint64_t *basic_lba, uint64_t *any_lba)
Fold one GPT entry into the candidate base-LBA bookkeeping.
ra8_err_t priv_gpt_locate_volume(const ra8_fs_mount_t *m, uint64_t *out_base)
Locate the first mountable partition on a GPT disk (auto-select).
ra8_err_t priv_gpt_locate_partition(const ra8_fs_mount_t *m, uint8_t index, uint64_t *out_base)
Locate a GPT partition chosen by entry-array index.
static const uint8_t s_gpt_guid_basic_data[k_gpt_guid_len]
Microsoft Basic Data type GUID, on-disk byte order (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7).
static uint64_t internal_gpt_entry_first_lba(const uint8_t *entry)
Extract a usable first-LBA from one GPT partition entry.
Cross-TU shared declarations for the FAT/exFAT ra8_fs adapter.
uint8_t g_fs_scratch[k_ra8_fs_sector_max]
Single max-sector scratch buffer reused across all I/O.
@ k_gpt_entry_off_first_lba
Entry: first LBA (8 bytes LE).
@ k_gpt_header_lba
GPT header location.
@ k_gpt_off_entry_lba
Entry-array first LBA (8 bytes LE).
@ k_gpt_guid_len
Type-GUID length in an entry.
@ k_gpt_off_entry_size
Bytes per partition entry.
@ k_gpt_off_entry_count
Number of partition entries.
@ k_gpt_entry_scan_max
Bounded entry walk (UEFI minimum).
@ k_gpt_sig_len
"EFI PART" signature length.
@ k_gpt_entry_bytes
Standard entry size supported.
Cached parse of one mounted FAT volume.