libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
lisa_tag.c
Go to the documentation of this file.
1/*
2 * This file is part of the Aaru Data Preservation Suite.
3 * Copyright (c) 2019-2026 Natalia Portillo.
4 *
5 * This library is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
59
60#include <stdint.h>
61
63
64#include <stdlib.h>
65
66#define SONY_BLOCK_NUMBER_MASK 0x07FFU
67#define SONY_BLOCK_VALID_FLAG 0x8000U
68#define SONY_BLOCK_ALLOWED_MASK (SONY_BLOCK_VALID_FLAG | SONY_BLOCK_NUMBER_MASK)
69
82sony_tag bytes_to_sony_tag(const uint8_t *bytes)
83{
84 sony_tag tag = {0};
85
86 tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
87 tag.kind = (bytes[2] & 0xC0) >> 6;
88 tag.reserved = bytes[2] & 0x3F;
89 tag.volume = bytes[3];
90 tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
91 tag.rel_page = (uint16_t)(bytes[6] << 8 | bytes[7]);
92 const uint16_t next_raw = (uint16_t)((uint16_t)bytes[8] << 8 | bytes[9]);
93 const uint16_t prev_raw = (uint16_t)((uint16_t)bytes[10] << 8 | bytes[11]);
94
95 tag.next_block = next_raw & SONY_BLOCK_ALLOWED_MASK;
96 tag.prev_block = prev_raw & SONY_BLOCK_ALLOWED_MASK;
97
98 return tag;
99}
100
112priam_tag bytes_to_priam_tag(const uint8_t *bytes)
113{
114 priam_tag tag = {0};
115
116 tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
117 tag.kind = (bytes[2] & 0xC0) >> 6;
118 tag.reserved = bytes[2] & 0x3F;
119 tag.volume = bytes[3];
120 tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
121 tag.used_bytes = (uint16_t)((bytes[6] & 0x7F) << 8 | bytes[7]);
122 tag.valid_chk = (bytes[6] & 0x80) != 0;
123 tag.abs_page = (uint32_t)(bytes[8] << 16 | bytes[9] << 8 | bytes[10]);
124 tag.checksum = bytes[11];
125 tag.rel_page = (uint16_t)(bytes[12] << 8 | bytes[13]);
126 tag.next_block = (uint32_t)(bytes[14] << 16 | bytes[15] << 8 | bytes[16]);
127 tag.prev_block = (uint32_t)(bytes[17] << 16 | bytes[18] << 8 | bytes[19]);
128 tag.disk_size = (uint32_t)(bytes[20] << 24 | bytes[21] << 16 | bytes[22] << 8 | bytes[23]);
129
130 return tag;
131}
132
143{
144 profile_tag tag = {0};
145
146 tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
147 tag.kind = (bytes[2] & 0xC0) >> 6;
148 tag.reserved = bytes[2] & 0x3F;
149 tag.volume = bytes[3];
150 tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
151 tag.used_bytes = (uint16_t)((bytes[6] & 0x7F) << 8 | bytes[7]);
152 tag.valid_chk = (bytes[6] & 0x80) != 0;
153 tag.abs_page = (uint32_t)(bytes[8] << 16 | bytes[9] << 8 | bytes[10]);
154 tag.checksum = bytes[11];
155 tag.rel_page = (uint16_t)(bytes[12] << 8 | bytes[13]);
156 tag.next_block = (uint32_t)(bytes[14] << 16 | bytes[15] << 8 | bytes[16]);
157 tag.prev_block = (uint32_t)(bytes[17] << 16 | bytes[18] << 8 | bytes[19]);
158
159 return tag;
160}
161
174{
175 profile_tag profile = {0};
176
177 const uint16_t next_number = tag.next_block & SONY_BLOCK_NUMBER_MASK;
178 const uint16_t prev_number = tag.prev_block & SONY_BLOCK_NUMBER_MASK;
179
180 profile.file_id = tag.file_id;
181 profile.kind = tag.kind;
182 profile.reserved = tag.reserved;
183 profile.next_block = next_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : next_number;
184 profile.prev_block = prev_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : prev_number;
185 profile.rel_page = tag.rel_page;
186 profile.version = tag.version;
187 profile.volume = tag.volume;
188
189 return profile;
190}
191
202{
203 priam_tag priam = {0};
204
205 const uint16_t next_number = tag.next_block & SONY_BLOCK_NUMBER_MASK;
206 const uint16_t prev_number = tag.prev_block & SONY_BLOCK_NUMBER_MASK;
207
208 priam.file_id = tag.file_id;
209 priam.kind = tag.kind;
210 priam.reserved = tag.reserved;
211 priam.next_block = next_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : next_number;
212 priam.prev_block = prev_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : prev_number;
213 priam.rel_page = tag.rel_page;
214 priam.version = tag.version;
215 priam.volume = tag.volume;
216
217 return priam;
218}
219
229{
230 priam_tag priam = {0};
231
232 priam.abs_page = tag.abs_page;
233 priam.checksum = tag.checksum;
234 priam.file_id = tag.file_id;
235 priam.kind = tag.kind;
236 priam.reserved = tag.reserved;
237 priam.next_block = tag.next_block;
238 priam.prev_block = tag.prev_block;
239 priam.rel_page = tag.rel_page;
240 priam.used_bytes = tag.used_bytes;
241 priam.valid_chk = tag.valid_chk;
242 priam.version = tag.version;
243 priam.volume = tag.volume;
244
245 return priam;
246}
247
258{
259 sony_tag sony = {0};
260
261 const uint32_t next_number = tag.next_block & 0xFFFFFFU;
262 const uint32_t prev_number = tag.prev_block & 0xFFFFFFU;
263
264 uint16_t sony_next = (uint16_t)(next_number & SONY_BLOCK_NUMBER_MASK);
265 uint16_t sony_prev = (uint16_t)(prev_number & SONY_BLOCK_NUMBER_MASK);
266
267 if(next_number == 0xFFFFFFU) sony_next = SONY_BLOCK_NUMBER_MASK;
268 if(prev_number == 0xFFFFFFU) sony_prev = SONY_BLOCK_NUMBER_MASK;
269
270 sony.file_id = tag.file_id;
271 sony.kind = tag.kind;
272 sony.reserved = tag.reserved;
273 sony.next_block = sony_next;
274 sony.prev_block = sony_prev;
275 sony.rel_page = tag.rel_page;
276 sony.version = tag.version;
277 sony.volume = tag.volume;
278
279 return sony;
280}
281
292{
293 sony_tag sony = {0};
294
295 const uint32_t next_number = tag.next_block & 0xFFFFFFU;
296 const uint32_t prev_number = tag.prev_block & 0xFFFFFFU;
297
298 uint16_t sony_next = (uint16_t)(next_number & SONY_BLOCK_NUMBER_MASK);
299 uint16_t sony_prev = (uint16_t)(prev_number & SONY_BLOCK_NUMBER_MASK);
300
301 if(next_number == 0xFFFFFFU) sony_next = SONY_BLOCK_NUMBER_MASK;
302 if(prev_number == 0xFFFFFFU) sony_prev = SONY_BLOCK_NUMBER_MASK;
303
304 sony.file_id = tag.file_id;
305 sony.kind = tag.kind;
306 sony.reserved = tag.reserved;
307 sony.next_block = sony_next;
308 sony.prev_block = sony_prev;
309 sony.rel_page = tag.rel_page;
310 sony.version = tag.version;
311 sony.volume = tag.volume;
312
313 return sony;
314}
315
326{
327 profile_tag profile = {0};
328
329 profile.abs_page = tag.abs_page;
330 profile.checksum = tag.checksum;
331 profile.file_id = tag.file_id;
332 profile.kind = tag.kind;
333 profile.reserved = tag.reserved;
334 profile.next_block = tag.next_block;
335 profile.prev_block = tag.prev_block;
336 profile.rel_page = tag.rel_page;
337 profile.used_bytes = tag.used_bytes;
338 profile.valid_chk = tag.valid_chk;
339 profile.version = tag.version;
340 profile.volume = tag.volume;
341
342 return profile;
343}
344
358{
359 uint8_t *bytes = calloc(1, 20);
360 if(!bytes) return NULL;
361
362 const uint16_t version = tag.version;
363 const uint8_t volume = tag.volume;
364 const int16_t file_id = tag.file_id;
365 const uint16_t rel_page = tag.rel_page;
366 const uint32_t abs_page = tag.abs_page & 0xFFFFFFU;
367 const uint32_t next_block = tag.next_block & 0xFFFFFFU;
368 const uint32_t prev_block = tag.prev_block & 0xFFFFFFU;
369 const uint16_t used_bytes = (uint16_t)(tag.used_bytes & 0x7FFFU);
370 const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
371 const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
372
373 bytes[0] = (uint8_t)((version >> 8) & 0xFF);
374 bytes[1] = (uint8_t)(version & 0xFF);
375 bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
376 bytes[3] = volume;
377 bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
378 bytes[5] = (uint8_t)(file_id & 0xFF);
379 bytes[6] = (uint8_t)((used_bytes >> 8) & 0x7F);
380 if(tag.valid_chk) bytes[6] |= 0x80U;
381 bytes[7] = (uint8_t)(used_bytes & 0xFF);
382 bytes[8] = (uint8_t)((abs_page >> 16) & 0xFF);
383 bytes[9] = (uint8_t)((abs_page >> 8) & 0xFF);
384 bytes[10] = (uint8_t)(abs_page & 0xFF);
385 bytes[11] = tag.checksum;
386 bytes[12] = (uint8_t)((rel_page >> 8) & 0xFF);
387 bytes[13] = (uint8_t)(rel_page & 0xFF);
388 bytes[14] = (uint8_t)((next_block >> 16) & 0xFF);
389 bytes[15] = (uint8_t)((next_block >> 8) & 0xFF);
390 bytes[16] = (uint8_t)(next_block & 0xFF);
391 bytes[17] = (uint8_t)((prev_block >> 16) & 0xFF);
392 bytes[18] = (uint8_t)((prev_block >> 8) & 0xFF);
393 bytes[19] = (uint8_t)(prev_block & 0xFF);
394
395 return bytes;
396}
397
409uint8_t *priam_tag_to_bytes(const priam_tag tag)
410{
411 uint8_t *bytes = calloc(1, 24);
412 if(!bytes) return NULL;
413
414 const uint16_t version = tag.version;
415 const uint8_t volume = tag.volume;
416 const int16_t file_id = tag.file_id;
417 const uint16_t rel_page = tag.rel_page;
418 const uint32_t abs_page = tag.abs_page & 0xFFFFFFU;
419 const uint32_t next_block = tag.next_block & 0xFFFFFFU;
420 const uint32_t prev_block = tag.prev_block & 0xFFFFFFU;
421 const uint32_t disk_size = tag.disk_size;
422 const uint16_t used_bytes = (uint16_t)(tag.used_bytes & 0x7FFFU);
423 const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
424 const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
425
426 bytes[0] = (uint8_t)((version >> 8) & 0xFF);
427 bytes[1] = (uint8_t)(version & 0xFF);
428 bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
429 bytes[3] = volume;
430 bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
431 bytes[5] = (uint8_t)(file_id & 0xFF);
432 bytes[6] = (uint8_t)((used_bytes >> 8) & 0x7F);
433 if(tag.valid_chk) bytes[6] |= 0x80U;
434 bytes[7] = (uint8_t)(used_bytes & 0xFF);
435 bytes[8] = (uint8_t)((abs_page >> 16) & 0xFF);
436 bytes[9] = (uint8_t)((abs_page >> 8) & 0xFF);
437 bytes[10] = (uint8_t)(abs_page & 0xFF);
438 bytes[11] = tag.checksum;
439 bytes[12] = (uint8_t)((rel_page >> 8) & 0xFF);
440 bytes[13] = (uint8_t)(rel_page & 0xFF);
441 bytes[14] = (uint8_t)((next_block >> 16) & 0xFF);
442 bytes[15] = (uint8_t)((next_block >> 8) & 0xFF);
443 bytes[16] = (uint8_t)(next_block & 0xFF);
444 bytes[17] = (uint8_t)((prev_block >> 16) & 0xFF);
445 bytes[18] = (uint8_t)((prev_block >> 8) & 0xFF);
446 bytes[19] = (uint8_t)(prev_block & 0xFF);
447 bytes[20] = (uint8_t)((disk_size >> 24) & 0xFF);
448 bytes[21] = (uint8_t)((disk_size >> 16) & 0xFF);
449 bytes[22] = (uint8_t)((disk_size >> 8) & 0xFF);
450 bytes[23] = (uint8_t)(disk_size & 0xFF);
451
452 return bytes;
453}
454
467{
468 uint8_t *bytes = calloc(1, 12);
469 if(!bytes) return NULL;
470
471 const uint16_t version = tag.version;
472 const uint8_t volume = tag.volume;
473 const int16_t file_id = tag.file_id;
474 const uint16_t rel_page = tag.rel_page;
475 const uint16_t next_block = tag.next_block & SONY_BLOCK_ALLOWED_MASK;
476 const uint16_t prev_block = tag.prev_block & SONY_BLOCK_ALLOWED_MASK;
477 const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
478 const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
479
480 bytes[0] = (uint8_t)((version >> 8) & 0xFF);
481 bytes[1] = (uint8_t)(version & 0xFF);
482 bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
483 bytes[3] = volume;
484 bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
485 bytes[5] = (uint8_t)(file_id & 0xFF);
486 bytes[6] = (uint8_t)((rel_page >> 8) & 0xFF);
487 bytes[7] = (uint8_t)(rel_page & 0xFF);
488 bytes[8] = (uint8_t)((next_block >> 8) & 0xFF);
489 bytes[9] = (uint8_t)(next_block & 0xFF);
490 bytes[10] = (uint8_t)((prev_block >> 8) & 0xFF);
491 bytes[11] = (uint8_t)(prev_block & 0xFF);
492
493 return bytes;
494}
priam_tag bytes_to_priam_tag(const uint8_t *bytes)
Parse a 24-byte Priam tag record into a priam_tag structure.
Definition lisa_tag.c:112
priam_tag sony_tag_to_priam(const sony_tag tag)
Convert a sony_tag to a priam_tag representation.
Definition lisa_tag.c:201
uint8_t * profile_tag_to_bytes(const profile_tag tag)
Serialize a profile_tag into a newly allocated 20-byte big-endian on-disk representation.
Definition lisa_tag.c:357
uint8_t * sony_tag_to_bytes(sony_tag tag)
Serialize a sony_tag into a newly allocated 12-byte big-endian on-disk representation.
Definition lisa_tag.c:466
profile_tag priam_tag_to_profile(const priam_tag tag)
Convert a priam_tag to a profile_tag.
Definition lisa_tag.c:325
#define SONY_BLOCK_ALLOWED_MASK
Preserve valid bit + 11-bit index.
Definition lisa_tag.c:68
profile_tag sony_tag_to_profile(const sony_tag tag)
Convert a sony_tag to a profile_tag representation.
Definition lisa_tag.c:173
sony_tag priam_tag_to_sony(const priam_tag tag)
Convert a priam_tag to a sony_tag.
Definition lisa_tag.c:291
sony_tag bytes_to_sony_tag(const uint8_t *bytes)
Parse a 12-byte Sony tag record into a sony_tag structure.
Definition lisa_tag.c:82
priam_tag profile_tag_to_priam(const profile_tag tag)
Convert a profile_tag to a priam_tag.
Definition lisa_tag.c:228
profile_tag bytes_to_profile_tag(const uint8_t *bytes)
Parse a 20-byte Profile tag record into a profile_tag structure.
Definition lisa_tag.c:142
sony_tag profile_tag_to_sony(const profile_tag tag)
Convert a profile_tag to a sony_tag.
Definition lisa_tag.c:257
uint8_t * priam_tag_to_bytes(const priam_tag tag)
Serialize a priam_tag into a newly allocated 24-byte big-endian on-disk representation.
Definition lisa_tag.c:409
#define SONY_BLOCK_NUMBER_MASK
Definition lisa_tag.c:66
Structure definitions and conversion/serialization function declarations for Lisa family disk tags.
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:66
int16_t file_id
0x04, file ID
Definition lisa_tag.h:68
uint32_t next_block
0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
Definition lisa_tag.h:74
uint32_t prev_block
0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
Definition lisa_tag.h:75
uint32_t disk_size
0x14, disk size
Definition lisa_tag.h:76
uint8_t checksum
0x0B, checksum of data
Definition lisa_tag.h:72
uint32_t abs_page
0x08, 3 bytes, absolute page number
Definition lisa_tag.h:71
uint8_t valid_chk
0x06 bit 7, checksum valid?
Definition lisa_tag.h:69
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:65
uint16_t used_bytes
0x06 bits 6 to 0, used bytes in block
Definition lisa_tag.h:70
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:67
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:64
uint16_t rel_page
0x0C, relative page number
Definition lisa_tag.h:73
uint8_t checksum
0x0B, checksum of data
Definition lisa_tag.h:56
uint16_t rel_page
0x0C, relative page number
Definition lisa_tag.h:57
uint16_t used_bytes
0x06 bits 6 to 0, used bytes in block
Definition lisa_tag.h:54
uint8_t valid_chk
0x06 bit 7, checksum valid?
Definition lisa_tag.h:53
uint32_t abs_page
0x08, 3 bytes, absolute page number
Definition lisa_tag.h:55
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:50
uint32_t next_block
0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
Definition lisa_tag.h:58
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:51
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:49
int16_t file_id
0x04, file ID
Definition lisa_tag.h:52
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:48
uint32_t prev_block
0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
Definition lisa_tag.h:59
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:39
int16_t file_id
0x04, file ID
Definition lisa_tag.h:40
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:36
uint16_t rel_page
0x06, relative page number
Definition lisa_tag.h:41
uint16_t next_block
0x08, next block, 0x7FF if it's last block, 0x8000 set if block is valid
Definition lisa_tag.h:42
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:38
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:37
uint16_t prev_block
0x0A, previous block, 0x7FF if it's first block
Definition lisa_tag.h:43