|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Canonical Microsoft exFAT up-case table, its writer, and its reader. More...
#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_fs.h"#include "ra8_fs_fat_internal.h"Go to the source code of this file.
Functions | |
| uint16_t | priv_exfat_upcase_unit (uint16_t unit) |
| Fold a UTF-16 code unit through the canonical exFAT up-case table. | |
| uint32_t | priv_exfat_upcase_checksum (void) |
| Rotate-add checksum of the up-case table this build embeds. | |
| ra8_err_t | priv_exfat_write_upcase (const ra8_fs_backend_t *backend, uint64_t abs_lba, uint32_t bps, uint32_t *out_csum) |
| Write the canonical exFAT up-case table and return its checksum. | |
Variables | |
| static const uint8_t | s_exfat_upcase [k_exfat_fmt_upc_std_bytes] |
| The canonical Microsoft exFAT up-case table (compressed, 5836 bytes). | |
Canonical Microsoft exFAT up-case table, its writer, and its reader.
exFAT stores a Unicode up-case table so the file system can fold names to a single case for its case-insensitive lookups. The Microsoft reference table covers the whole Basic Multilingual Plane in run-length-compressed form; it is the exact byte sequence mkfs.exfat and the Windows formatter emit, and its rotate-add checksum is the well-known 0xE619D30D. Embedding it verbatim (rather than the earlier a-z-only stub) makes a card the firmware formats byte-for-byte compatible with a PC-formatted one and folds accented / Greek / Cyrillic file names correctly – so a book dragged onto the card from any computer resolves regardless of case.
This table is 5836 bytes (k_exfat_fmt_upc_std_bytes), lives in its own translation unit to keep ra8_fs_fat_exfat_fmt.c under the source-size cap, and is written by priv_exfat_write_upcase across the up-case clusters of a freshly formatted volume.
The table was write-only until name handling needed to FOLD a case, and it is the fold the exFAT specification defines NameHash against – so hashing with an ASCII-only up-case, which is what the create path used to do, stored a hash a compliant host disagrees with for any name outside ASCII. priv_exfat_upcase_unit() answers the same question the table does, by walking the compressed form in place rather than expanding it: a full 64 Ki-entry expansion is 128 KiB of RAM on a part that has 1.6 MB in total, to answer a query that arrives a few times per file name.
The compressed encoding is the specification's: a unit that is not k_exfat_upc_run_tag is the mapping for the next code point, and one that is introduces a run length of code points that map to themselves. The table ends with a k_exfat_upc_run_tag that has no length after it – the mapping for U+FFFF, which is its own up-case – so a walk that runs out of words while expecting a run length returns the identity, which is the right answer there.
priv_exfat_upcase_checksum() folds the same bytes with the same rotate-add the writer uses, which is what lets a mount COMPARE this build's table against the one the volume actually carries instead of assuming they agree.
Definition in file ra8_fs_fat_exfat_upcase.c.
| uint32_t priv_exfat_upcase_checksum | ( | void | ) |
Rotate-add checksum of the up-case table this build embeds.
The same 32-bit fold priv_exfat_write_upcase records in the volume's up-case directory entry, computed over the in-flash table. Having it as a function rather than a constant is the point: a constant could drift from the bytes it claims to describe, and this cannot.
| 0xE619D30D | The canonical Microsoft table, which is what is embedded. |
Definition at line 471 of file ra8_fs_fat_exfat_upcase.c.
References k_exfat_fmt_upc_std_bytes, priv_exfat_csum32(), and s_exfat_upcase.
Referenced by priv_exfat_upcase_verify().
| uint16_t priv_exfat_upcase_unit | ( | uint16_t | unit | ) |
Fold a UTF-16 code unit through the canonical exFAT up-case table.
The exFAT specification defines both NameHash and name comparison over the UP-CASED name, using the table the volume carries. This build embeds and writes the canonical Microsoft table – the one mkfs.exfat and the Windows formatter emit, checksum 0xE619D30D – and this is the reader for it, so the hash stored on create is the hash a host recomputes.
Look-up walks the compressed table rather than expanding it, because the expansion is 128 KiB. The ASCII range short-circuits to priv_ascii_upper, which the table agrees with for every one of those 128 units.
A surrogate unit folds to itself: the table covers the BMP, and a supplementary code point has no simple case mapping inside a single unit.
| [in] | unit | UTF-16 code unit to fold. |
| unit | No mapping applies (identity run, or past the table). |
| other | The table's mapping for unit. |
unit and the embedded table. Definition at line 435 of file ra8_fs_fat_exfat_upcase.c.
References k_exfat_upc_run_tag, k_exfat_upc_words, k_utf_ascii_max, priv_ascii_upper(), priv_rd16(), and s_exfat_upcase.
Referenced by priv_exfat_name_chunk_eq(), priv_exfat_name_hash(), and priv_utf16_ieq().
| ra8_err_t priv_exfat_write_upcase | ( | const ra8_fs_backend_t * | backend, |
| uint64_t | abs_lba, | ||
| uint32_t | bps, | ||
| uint32_t * | out_csum ) |
Write the canonical exFAT up-case table and return its checksum.
Streams the 5836-byte Microsoft up-case table (k_exfat_fmt_upc_std_bytes, embedded in ra8_fs_fat_exfat_upcase.c) to the device starting at absolute LBA abs_lba, one bps-byte sector at a time, zero-padding the final partial sector. The rotate-add checksum (priv_exfat_csum32) is accumulated over exactly the table bytes – not the pad – so it equals the well-known 0xE619D30D and can be stamped into the root Up-case directory entry.
| [in] | backend | Block-device backend with a non-NULL write_block. |
| [in] | abs_lba | Absolute (partition-adjusted) first LBA of the up-case table's cluster run. |
| [in] | bps | Device sector size in bytes (a power of two, 512..4096). |
| [out] | out_csum | Receives the table checksum on success. |
| k_ra8_ok | Table written; out_csum populated. |
| k_ra8_err_* | Backend write_block failure; out_csum unspecified. |
backend and backend->write_block are non-NULL. out_csum is non-NULL; abs_lba's cluster run holds the table span. out_csum holds the checksum for the root Up-case entry. Definition at line 477 of file ra8_fs_fat_exfat_upcase.c.
References ra8_fs_backend_t::ctx, g_fs_scratch, k_exfat_fmt_upc_std_bytes, k_ra8_ok, priv_byte_copy(), priv_exfat_csum32(), s_exfat_upcase, and ra8_fs_backend_t::write_block.
Referenced by priv_exfat_format().
|
static |
The canonical Microsoft exFAT up-case table (compressed, 5836 bytes).
Little-endian UTF-16 up-case mapping table in the exFAT run-length compressed encoding, identical to the one mkfs.exfat writes. Its rotate-add checksum is 0xE619D30D. Read-only; lives in flash.
Definition at line 66 of file ra8_fs_fat_exfat_upcase.c.
Referenced by priv_exfat_upcase_checksum(), priv_exfat_upcase_unit(), and priv_exfat_write_upcase().