Add magic number and validation to cart dumps

This commit is contained in:
spicyjpeg 2024-03-25 23:45:17 +01:00
parent 28d89ae860
commit 6875939523
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
4 changed files with 33 additions and 14 deletions

View File

@ -9,9 +9,9 @@ header. The data can be broken down as follows:
| Offset | Length | Description |
| -----: | ------: | :-------------------------------------------------------- |
| 0 | 1 | EEPROM chip type: 1 = X76F041, 2 = reserved, 3 = ZS01 |
| 1 | 1 | Dump flags, see below |
| 2 | 2 | _Reserved_ (should be zero) |
| 0 | 2 | Magic number, must be `3d 57` (`0x573d` little endian) |
| 2 | 1 | EEPROM chip type: 1 = X76F041, 2 = reserved, 3 = ZS01 |
| 3 | 1 | Dump flags, see below |
| 4 | 8 | System identifier, zerofilled if none such |
| 12 | 8 | Cartridge DS2401 identifier, zerofilled if none such |
| 20 | 8 | Cartridge ZS01 identifier, zerofilled if none such |
@ -41,11 +41,11 @@ DS2401 chip.
The format used by QR code dumps is essentially the same as `.573` files, but
with an additional layer of compression and a custom base-41 encoding on top of
the raw data. Scanning a QR code generated by the tool yields a string similar
to this one:
the raw data. Scanning a QR code generated by the tool yields a string formatted
like this:
```
573::OGI8APY-U7W9553SDY9J+F.TGR1XY92YKJFAGN16ALNTMDDWGM0-U2MPP:60M3NJO1.TU05T5QZ376SRN4S3LFHHGXNTSA6ZSTSQPZBBA96RCXZQ6M01E1CTKR7941MH9D7B0Y.:JZ0PN8K2000::
573::OGI8APY- [...] 8K2000::
```
In order to extract the dump data from such a string, a decoder must:
@ -75,3 +75,11 @@ while not isEndOfData(input):
The contents of the dump can then obtained by running the decoded data through
zlib's `decompress()` function or a zlib-compatible decompressor.
## Flash, PCMCIA card, RTC and BIOS dumps
All dumps of the internal flash, PCMCIA flash cards, RTC RAM and BIOS ROM are
stored in raw format without any framing or headers other than the ones present
in the data itself. In RTC RAM dumps the last 8 bytes (mapped to the M48T58
chip's clock registers) are omitted, thus the resulting dump is 8184 bytes long
rather than 8192.

View File

@ -283,7 +283,7 @@ bool App::_cartRestoreWorker(void) {
if (length < (sizeof(newDump) - sizeof(newDump.data)))
goto _fileError;
if (false) // TODO: validate dump
if (!newDump.validateMagic())
goto _fileError;
if (length != newDump.getDumpLength())
goto _fileError;

View File

@ -148,6 +148,8 @@ public:
/* Cartridge dump structure */
static constexpr uint16_t DUMP_HEADER_MAGIC = 0x573d;
struct ChipSize {
public:
size_t dataLength, publicDataOffset, publicDataLength;
@ -157,9 +159,9 @@ extern const ChipSize CHIP_SIZES[NUM_CHIP_TYPES];
class [[gnu::packed]] Dump {
public:
uint16_t magic;
ChipType chipType;
uint8_t flags;
uint8_t _reserved[2];
Identifier systemID, cartID, zsID;
@ -167,14 +169,17 @@ public:
uint8_t data[512];
inline Dump(void)
: chipType(NONE), flags(0) {
_reserved[0] = 0;
_reserved[1] = 0;
}
: magic(DUMP_HEADER_MAGIC), chipType(NONE), flags(0) {}
inline const ChipSize &getChipSize(void) const {
return CHIP_SIZES[chipType];
}
inline bool validateMagic(void) const {
return
(magic == DUMP_HEADER_MAGIC) &&
(chipType > 0) &&
(chipType < NUM_CHIP_TYPES);
}
inline size_t getDumpLength(void) const {
return (sizeof(Dump) - sizeof(data)) + getChipSize().dataLength;
}

View File

@ -166,7 +166,8 @@ class PublicIdentifierSet:
## Cartridge dump structure
_DUMP_HEADER_STRUCT: Struct = Struct("< 2B 2x 8s 8s 8s 8s 8s")
_DUMP_HEADER_STRUCT: Struct = Struct("< H 2B 8s 8s 8s 8s 8s")
_DUMP_HEADER_MAGIC: int = 0x573d
_CHIP_SIZES: Mapping[ChipType, tuple[int, int, int]] = {
ChipType.X76F041: ( 512, 384, 128 ),
@ -191,6 +192,7 @@ class Dump:
def serialize(self) -> bytes:
return _DUMP_HEADER_STRUCT.pack(
_DUMP_HEADER_MAGIC,
self.chipType,
self.flags,
self.systemID,
@ -201,8 +203,12 @@ class Dump:
) + self.data
def parseDump(data: bytes) -> Dump:
chipType, flags, systemID, cartID, zsID, dataKey, config = \
magic, chipType, flags, systemID, cartID, zsID, dataKey, config = \
_DUMP_HEADER_STRUCT.unpack(data[0:_DUMP_HEADER_STRUCT.size])
if magic != _DUMP_HEADER_MAGIC:
raise ValueError(f"invalid or unsupported dump format: 0x{magic:04x}")
dataLength, _, _ = _CHIP_SIZES[chipType]
return Dump(