Loading...
Searching...
No Matches
lisa_tag.c
Go to the documentation of this file.
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2026 Natalia Portillo.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include "aaruformat/structs/lisa_tag.h"
#include <stdlib.h>
#define SONY_BLOCK_NUMBER_MASK 0x07FFU
#define SONY_BLOCK_VALID_FLAG 0x8000U
#define SONY_BLOCK_ALLOWED_MASK (SONY_BLOCK_VALID_FLAG | SONY_BLOCK_NUMBER_MASK)
sony_tag bytes_to_sony_tag(const uint8_t *bytes)
{
sony_tag tag = {0};
tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
tag.kind = (bytes[2] & 0xC0) >> 6;
tag.reserved = bytes[2] & 0x3F;
tag.volume = bytes[3];
tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
tag.rel_page = (uint16_t)(bytes[6] << 8 | bytes[7]);
const uint16_t next_raw = (uint16_t)((uint16_t)bytes[8] << 8 | bytes[9]);
const uint16_t prev_raw = (uint16_t)((uint16_t)bytes[10] << 8 | bytes[11]);
tag.next_block = next_raw & SONY_BLOCK_ALLOWED_MASK;
tag.prev_block = prev_raw & SONY_BLOCK_ALLOWED_MASK;
return tag;
}
priam_tag bytes_to_priam_tag(const uint8_t *bytes)
{
priam_tag tag = {0};
tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
tag.kind = (bytes[2] & 0xC0) >> 6;
tag.reserved = bytes[2] & 0x3F;
tag.volume = bytes[3];
tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
tag.used_bytes = (uint16_t)((bytes[6] & 0x7F) << 8 | bytes[7]);
tag.valid_chk = (bytes[6] & 0x80) != 0;
tag.abs_page = (uint32_t)(bytes[8] << 16 | bytes[9] << 8 | bytes[10]);
tag.checksum = bytes[11];
tag.rel_page = (uint16_t)(bytes[12] << 8 | bytes[13]);
tag.next_block = (uint32_t)(bytes[14] << 16 | bytes[15] << 8 | bytes[16]);
tag.prev_block = (uint32_t)(bytes[17] << 16 | bytes[18] << 8 | bytes[19]);
tag.disk_size = (uint32_t)(bytes[20] << 24 | bytes[21] << 16 | bytes[22] << 8 | bytes[23]);
return tag;
}
profile_tag bytes_to_profile_tag(const uint8_t *bytes)
{
profile_tag tag = {0};
tag.version = (uint16_t)(bytes[0] << 8 | bytes[1]);
tag.kind = (bytes[2] & 0xC0) >> 6;
tag.reserved = bytes[2] & 0x3F;
tag.volume = bytes[3];
tag.file_id = (int16_t)(bytes[4] << 8 | bytes[5]);
tag.used_bytes = (uint16_t)((bytes[6] & 0x7F) << 8 | bytes[7]);
tag.valid_chk = (bytes[6] & 0x80) != 0;
tag.abs_page = (uint32_t)(bytes[8] << 16 | bytes[9] << 8 | bytes[10]);
tag.checksum = bytes[11];
tag.rel_page = (uint16_t)(bytes[12] << 8 | bytes[13]);
tag.next_block = (uint32_t)(bytes[14] << 16 | bytes[15] << 8 | bytes[16]);
tag.prev_block = (uint32_t)(bytes[17] << 16 | bytes[18] << 8 | bytes[19]);
return tag;
}
profile_tag sony_tag_to_profile(const sony_tag tag)
{
profile_tag profile = {0};
const uint16_t next_number = tag.next_block & SONY_BLOCK_NUMBER_MASK;
const uint16_t prev_number = tag.prev_block & SONY_BLOCK_NUMBER_MASK;
profile.file_id = tag.file_id;
profile.kind = tag.kind;
profile.reserved = tag.reserved;
profile.next_block = next_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : next_number;
profile.prev_block = prev_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : prev_number;
profile.rel_page = tag.rel_page;
profile.version = tag.version;
profile.volume = tag.volume;
return profile;
}
priam_tag sony_tag_to_priam(const sony_tag tag)
{
priam_tag priam = {0};
const uint16_t next_number = tag.next_block & SONY_BLOCK_NUMBER_MASK;
const uint16_t prev_number = tag.prev_block & SONY_BLOCK_NUMBER_MASK;
priam.file_id = tag.file_id;
priam.kind = tag.kind;
priam.reserved = tag.reserved;
priam.next_block = next_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : next_number;
priam.prev_block = prev_number == SONY_BLOCK_NUMBER_MASK ? 0xFFFFFFU : prev_number;
priam.rel_page = tag.rel_page;
priam.version = tag.version;
priam.volume = tag.volume;
return priam;
}
priam_tag profile_tag_to_priam(const profile_tag tag)
{
priam_tag priam = {0};
priam.abs_page = tag.abs_page;
priam.checksum = tag.checksum;
priam.file_id = tag.file_id;
priam.kind = tag.kind;
priam.reserved = tag.reserved;
priam.next_block = tag.next_block;
priam.prev_block = tag.prev_block;
priam.rel_page = tag.rel_page;
priam.used_bytes = tag.used_bytes;
priam.valid_chk = tag.valid_chk;
priam.version = tag.version;
priam.volume = tag.volume;
return priam;
}
sony_tag profile_tag_to_sony(const profile_tag tag)
{
sony_tag sony = {0};
const uint32_t next_number = tag.next_block & 0xFFFFFFU;
const uint32_t prev_number = tag.prev_block & 0xFFFFFFU;
uint16_t sony_next = (uint16_t)(next_number & SONY_BLOCK_NUMBER_MASK);
uint16_t sony_prev = (uint16_t)(prev_number & SONY_BLOCK_NUMBER_MASK);
if(next_number == 0xFFFFFFU) sony_next = SONY_BLOCK_NUMBER_MASK;
if(prev_number == 0xFFFFFFU) sony_prev = SONY_BLOCK_NUMBER_MASK;
sony.file_id = tag.file_id;
sony.kind = tag.kind;
sony.reserved = tag.reserved;
sony.next_block = sony_next;
sony.prev_block = sony_prev;
sony.rel_page = tag.rel_page;
sony.version = tag.version;
sony.volume = tag.volume;
return sony;
}
sony_tag priam_tag_to_sony(const priam_tag tag)
{
sony_tag sony = {0};
const uint32_t next_number = tag.next_block & 0xFFFFFFU;
const uint32_t prev_number = tag.prev_block & 0xFFFFFFU;
uint16_t sony_next = (uint16_t)(next_number & SONY_BLOCK_NUMBER_MASK);
uint16_t sony_prev = (uint16_t)(prev_number & SONY_BLOCK_NUMBER_MASK);
if(next_number == 0xFFFFFFU) sony_next = SONY_BLOCK_NUMBER_MASK;
if(prev_number == 0xFFFFFFU) sony_prev = SONY_BLOCK_NUMBER_MASK;
sony.file_id = tag.file_id;
sony.kind = tag.kind;
sony.reserved = tag.reserved;
sony.next_block = sony_next;
sony.prev_block = sony_prev;
sony.rel_page = tag.rel_page;
sony.version = tag.version;
sony.volume = tag.volume;
return sony;
}
profile_tag priam_tag_to_profile(const priam_tag tag)
{
profile_tag profile = {0};
profile.abs_page = tag.abs_page;
profile.checksum = tag.checksum;
profile.file_id = tag.file_id;
profile.kind = tag.kind;
profile.reserved = tag.reserved;
profile.next_block = tag.next_block;
profile.prev_block = tag.prev_block;
profile.rel_page = tag.rel_page;
profile.used_bytes = tag.used_bytes;
profile.valid_chk = tag.valid_chk;
profile.version = tag.version;
profile.volume = tag.volume;
return profile;
}
uint8_t *profile_tag_to_bytes(const profile_tag tag)
{
uint8_t *bytes = calloc(1, 20);
if(!bytes) return NULL;
const uint16_t version = tag.version;
const uint8_t volume = tag.volume;
const int16_t file_id = tag.file_id;
const uint16_t rel_page = tag.rel_page;
const uint32_t abs_page = tag.abs_page & 0xFFFFFFU;
const uint32_t next_block = tag.next_block & 0xFFFFFFU;
const uint32_t prev_block = tag.prev_block & 0xFFFFFFU;
const uint16_t used_bytes = (uint16_t)(tag.used_bytes & 0x7FFFU);
const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
bytes[0] = (uint8_t)((version >> 8) & 0xFF);
bytes[1] = (uint8_t)(version & 0xFF);
bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
bytes[3] = volume;
bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
bytes[5] = (uint8_t)(file_id & 0xFF);
bytes[6] = (uint8_t)((used_bytes >> 8) & 0x7F);
if(tag.valid_chk) bytes[6] |= 0x80U;
bytes[7] = (uint8_t)(used_bytes & 0xFF);
bytes[8] = (uint8_t)((abs_page >> 16) & 0xFF);
bytes[9] = (uint8_t)((abs_page >> 8) & 0xFF);
bytes[10] = (uint8_t)(abs_page & 0xFF);
bytes[11] = tag.checksum;
bytes[12] = (uint8_t)((rel_page >> 8) & 0xFF);
bytes[13] = (uint8_t)(rel_page & 0xFF);
bytes[14] = (uint8_t)((next_block >> 16) & 0xFF);
bytes[15] = (uint8_t)((next_block >> 8) & 0xFF);
bytes[16] = (uint8_t)(next_block & 0xFF);
bytes[17] = (uint8_t)((prev_block >> 16) & 0xFF);
bytes[18] = (uint8_t)((prev_block >> 8) & 0xFF);
bytes[19] = (uint8_t)(prev_block & 0xFF);
return bytes;
}
uint8_t *priam_tag_to_bytes(const priam_tag tag)
{
uint8_t *bytes = calloc(1, 24);
if(!bytes) return NULL;
const uint16_t version = tag.version;
const uint8_t volume = tag.volume;
const int16_t file_id = tag.file_id;
const uint16_t rel_page = tag.rel_page;
const uint32_t abs_page = tag.abs_page & 0xFFFFFFU;
const uint32_t next_block = tag.next_block & 0xFFFFFFU;
const uint32_t prev_block = tag.prev_block & 0xFFFFFFU;
const uint32_t disk_size = tag.disk_size;
const uint16_t used_bytes = (uint16_t)(tag.used_bytes & 0x7FFFU);
const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
bytes[0] = (uint8_t)((version >> 8) & 0xFF);
bytes[1] = (uint8_t)(version & 0xFF);
bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
bytes[3] = volume;
bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
bytes[5] = (uint8_t)(file_id & 0xFF);
bytes[6] = (uint8_t)((used_bytes >> 8) & 0x7F);
if(tag.valid_chk) bytes[6] |= 0x80U;
bytes[7] = (uint8_t)(used_bytes & 0xFF);
bytes[8] = (uint8_t)((abs_page >> 16) & 0xFF);
bytes[9] = (uint8_t)((abs_page >> 8) & 0xFF);
bytes[10] = (uint8_t)(abs_page & 0xFF);
bytes[11] = tag.checksum;
bytes[12] = (uint8_t)((rel_page >> 8) & 0xFF);
bytes[13] = (uint8_t)(rel_page & 0xFF);
bytes[14] = (uint8_t)((next_block >> 16) & 0xFF);
bytes[15] = (uint8_t)((next_block >> 8) & 0xFF);
bytes[16] = (uint8_t)(next_block & 0xFF);
bytes[17] = (uint8_t)((prev_block >> 16) & 0xFF);
bytes[18] = (uint8_t)((prev_block >> 8) & 0xFF);
bytes[19] = (uint8_t)(prev_block & 0xFF);
bytes[20] = (uint8_t)((disk_size >> 24) & 0xFF);
bytes[21] = (uint8_t)((disk_size >> 16) & 0xFF);
bytes[22] = (uint8_t)((disk_size >> 8) & 0xFF);
bytes[23] = (uint8_t)(disk_size & 0xFF);
return bytes;
}
uint8_t *sony_tag_to_bytes(sony_tag tag)
{
uint8_t *bytes = calloc(1, 12);
if(!bytes) return NULL;
const uint16_t version = tag.version;
const uint8_t volume = tag.volume;
const int16_t file_id = tag.file_id;
const uint16_t rel_page = tag.rel_page;
const uint16_t next_block = tag.next_block & SONY_BLOCK_ALLOWED_MASK;
const uint16_t prev_block = tag.prev_block & SONY_BLOCK_ALLOWED_MASK;
const uint8_t kind_bits = (uint8_t)(tag.kind & 0x3U);
const uint8_t reserved = (uint8_t)(tag.reserved & 0x3FU);
bytes[0] = (uint8_t)((version >> 8) & 0xFF);
bytes[1] = (uint8_t)(version & 0xFF);
bytes[2] = (uint8_t)((kind_bits << 6) | reserved);
bytes[3] = volume;
bytes[4] = (uint8_t)((file_id >> 8) & 0xFF);
bytes[5] = (uint8_t)(file_id & 0xFF);
bytes[6] = (uint8_t)((rel_page >> 8) & 0xFF);
bytes[7] = (uint8_t)(rel_page & 0xFF);
bytes[8] = (uint8_t)((next_block >> 8) & 0xFF);
bytes[9] = (uint8_t)(next_block & 0xFF);
bytes[10] = (uint8_t)((prev_block >> 8) & 0xFF);
bytes[11] = (uint8_t)(prev_block & 0xFF);
return bytes;
}
bytes_to_priam_tag
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
sony_tag_to_priam
priam_tag sony_tag_to_priam(const sony_tag tag)
Convert a sony_tag to a priam_tag representation.
Definition lisa_tag.c:201
profile_tag_to_bytes
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
sony_tag_to_bytes
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
priam_tag_to_profile
profile_tag priam_tag_to_profile(const priam_tag tag)
Convert a priam_tag to a profile_tag.
Definition lisa_tag.c:325
SONY_BLOCK_ALLOWED_MASK
#define SONY_BLOCK_ALLOWED_MASK
Preserve valid bit + 11-bit index.
Definition lisa_tag.c:68
sony_tag_to_profile
profile_tag sony_tag_to_profile(const sony_tag tag)
Convert a sony_tag to a profile_tag representation.
Definition lisa_tag.c:173
priam_tag_to_sony
sony_tag priam_tag_to_sony(const priam_tag tag)
Convert a priam_tag to a sony_tag.
Definition lisa_tag.c:291
bytes_to_sony_tag
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
profile_tag_to_priam
priam_tag profile_tag_to_priam(const profile_tag tag)
Convert a profile_tag to a priam_tag.
Definition lisa_tag.c:228
bytes_to_profile_tag
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
profile_tag_to_sony
sony_tag profile_tag_to_sony(const profile_tag tag)
Convert a profile_tag to a sony_tag.
Definition lisa_tag.c:257
priam_tag_to_bytes
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
SONY_BLOCK_NUMBER_MASK
#define SONY_BLOCK_NUMBER_MASK
Definition lisa_tag.c:66
lisa_tag.h
Structure definitions and conversion/serialization function declarations for Lisa family disk tags.
priam_tag
Definition lisa_tag.h:63
priam_tag::reserved
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:66
priam_tag::file_id
int16_t file_id
0x04, file ID
Definition lisa_tag.h:68
priam_tag::next_block
uint32_t next_block
0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
Definition lisa_tag.h:74
priam_tag::prev_block
uint32_t prev_block
0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
Definition lisa_tag.h:75
priam_tag::disk_size
uint32_t disk_size
0x14, disk size
Definition lisa_tag.h:76
priam_tag::checksum
uint8_t checksum
0x0B, checksum of data
Definition lisa_tag.h:72
priam_tag::abs_page
uint32_t abs_page
0x08, 3 bytes, absolute page number
Definition lisa_tag.h:71
priam_tag::valid_chk
uint8_t valid_chk
0x06 bit 7, checksum valid?
Definition lisa_tag.h:69
priam_tag::kind
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:65
priam_tag::used_bytes
uint16_t used_bytes
0x06 bits 6 to 0, used bytes in block
Definition lisa_tag.h:70
priam_tag::volume
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:67
priam_tag::version
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:64
priam_tag::rel_page
uint16_t rel_page
0x0C, relative page number
Definition lisa_tag.h:73
profile_tag
Definition lisa_tag.h:47
profile_tag::checksum
uint8_t checksum
0x0B, checksum of data
Definition lisa_tag.h:56
profile_tag::rel_page
uint16_t rel_page
0x0C, relative page number
Definition lisa_tag.h:57
profile_tag::used_bytes
uint16_t used_bytes
0x06 bits 6 to 0, used bytes in block
Definition lisa_tag.h:54
profile_tag::valid_chk
uint8_t valid_chk
0x06 bit 7, checksum valid?
Definition lisa_tag.h:53
profile_tag::abs_page
uint32_t abs_page
0x08, 3 bytes, absolute page number
Definition lisa_tag.h:55
profile_tag::reserved
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:50
profile_tag::next_block
uint32_t next_block
0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
Definition lisa_tag.h:58
profile_tag::volume
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:51
profile_tag::kind
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:49
profile_tag::file_id
int16_t file_id
0x04, file ID
Definition lisa_tag.h:52
profile_tag::version
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:48
profile_tag::prev_block
uint32_t prev_block
0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
Definition lisa_tag.h:59
sony_tag
Definition lisa_tag.h:35
sony_tag::volume
uint8_t volume
0x03, disk volume number
Definition lisa_tag.h:39
sony_tag::file_id
int16_t file_id
0x04, file ID
Definition lisa_tag.h:40
sony_tag::version
uint16_t version
0x00, Lisa OS version number
Definition lisa_tag.h:36
sony_tag::rel_page
uint16_t rel_page
0x06, relative page number
Definition lisa_tag.h:41
sony_tag::next_block
uint16_t next_block
0x08, next block, 0x7FF if it's last block, 0x8000 set if block is valid
Definition lisa_tag.h:42
sony_tag::reserved
uint8_t reserved
0x02 bits 5 to 0, reserved
Definition lisa_tag.h:38
sony_tag::kind
uint8_t kind
0x02 bits 7 to 6, kind of info in this block
Definition lisa_tag.h:37
sony_tag::prev_block
uint16_t prev_block
0x0A, previous block, 0x7FF if it's first block
Definition lisa_tag.h:43