Serenity Operating System
at master 270 lines 7.5 kB view raw
1/* 2 * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/EnumBits.h> 10#include <AK/Types.h> 11 12namespace Kernel { 13 14namespace ISO { 15 16// The implemented spec here is ECMA 119, available at: 17// https://www.ecma-international.org/wp-content/uploads/ECMA-119_4th_edition_june_2019.pdf 18 19template<typename T> 20struct [[gnu::packed]] LittleAndBigEndian { 21 T little; 22 T big; 23}; 24 25// 8.4.26.1 Date and Time Format 26struct [[gnu::packed]] AsciiDateAndTime { 27 // All of these fields are ASCII digits. :^) 28 u8 year[4]; 29 u8 month[2]; 30 u8 day[2]; 31 32 u8 hour[2]; 33 u8 minute[2]; 34 u8 second[2]; 35 u8 hundredths_of_second[2]; 36 37 // From OSDev wiki: 38 // Time zone offset from GMT in 15 minute intervals, starting at 39 // interval -48 (west) and running up to interval 52 (east). So value 0 40 // indicates interval -48 which equals GMT-12 hours, and value 100 41 // indicates interval 52 which equals GMT+13 hours. 42 u8 timezone_offset; 43}; 44static_assert(sizeof(AsciiDateAndTime) == 17); 45 46// 9.1.5 Recording Date and Time (BP 19 to 25) 47struct [[gnu::packed]] NumericalDateAndTime { 48 u8 years_since_1900; 49 u8 month; 50 u8 day; 51 u8 hour; 52 u8 minute; 53 u8 second; 54 // Same format as AsciiDateAndTime. 55 u8 timezone_offset; 56}; 57static_assert(sizeof(NumericalDateAndTime) == 7); 58 59// --- Path Table --- 60 61// 9.4 Format of a Path Table Record 62struct [[gnu::packed]] PathTableRecord { 63 u8 directory_identifier_length; 64 u8 extended_attribute_record_length; 65 u32 extent_location; 66 u16 parent_directory_number; 67 68 u8 directory_identifier[]; 69}; 70static_assert(sizeof(PathTableRecord) == 8); 71 72// --- Extended Attribute Record --- 73 74// 9.5.3 Permissions 75enum class ExtendedPermissions : u16 { 76 SystemGroupReadable = 1 << 0, 77 SystemGroupExecutable = 1 << 2, 78 UserReadable = 1 << 4, 79 UserExecutable = 1 << 6, 80 GroupReadable = 1 << 8, 81 GroupExecutable = 1 << 10, 82 OtherReadable = 1 << 12, 83 OtherExecutable = 1 << 14, 84}; 85AK_ENUM_BITWISE_OPERATORS(ExtendedPermissions); 86 87// 9.5.8 Record Format 88enum class RecordFormat : u8 { 89 NotSpecified = 0, 90 FixedLengthRecords = 1, 91 LittleEndianVariableRecords = 2, 92 BigEndianVariableRecords = 3, 93 // 4-127 are reserved for future standardization. 94 // 128-255 are reserved for system use. 95}; 96 97// 9.5.9 Record Attributes 98enum class RecordAttributes : u8 { 99 // This value means the record is stored like: \n123456\r. 100 LfCrDelimited = 0, 101 FortranVerticalSpacing = 1, 102 ContainsControlInformation = 2, 103 // 3-255 are reserved for future standardization. 104}; 105 106// 9.5 Format of an Extended Attribute Record 107struct [[gnu::packed]] ExtendedAttributeRecord { 108 LittleAndBigEndian<u16> owner_identification; 109 LittleAndBigEndian<u16> group_identification; 110 ExtendedPermissions permissions; 111 112 AsciiDateAndTime file_creation_date_and_time; 113 AsciiDateAndTime file_modification_date_and_time; 114 AsciiDateAndTime file_expiration_date_and_time; 115 AsciiDateAndTime file_effective_date_and_time; 116 117 RecordFormat record_format; 118 u8 record_attributes; 119 120 LittleAndBigEndian<u16> record_length; 121 122 u8 system_identifier[32]; 123 u8 system_use[64]; 124 125 u8 extended_attribute_record_version; 126 u8 escape_sequence_length; 127 128 u8 reserved[64]; 129 130 LittleAndBigEndian<u16> application_use_length; 131 132 // NOTE: Application use is immediately followed by escape sequences (no 133 // padding). 134 u8 application_use_and_escape_sequences[]; 135}; 136static_assert(sizeof(ExtendedAttributeRecord) == 250); 137 138// --- Files and Directories --- 139 140// 9.1.6 File Flags 141enum class FileFlags : u8 { 142 Hidden = 1 << 0, // The "existence" flag 143 Directory = 1 << 1, 144 AssociatedFile = 1 << 2, 145 Record = 1 << 3, 146 Protection = 1 << 4, 147 // 5 and 6 are reserved. 148 MultiExtent = 1 << 7, 149}; 150 151AK_ENUM_BITWISE_OPERATORS(FileFlags); 152 153struct [[gnu::packed]] DirectoryRecordHeader { 154 u8 length; 155 u8 extended_attribute_record_length; 156 LittleAndBigEndian<u32> extent_location; 157 LittleAndBigEndian<u32> data_length; 158 NumericalDateAndTime recording_date_and_time; 159 FileFlags file_flags; 160 u8 file_unit_size; 161 u8 interleave_gap_size; 162 LittleAndBigEndian<u16> volume_sequence_number; 163 u8 file_identifier_length; 164 165 // NOTE: The file identifier itself is of variable length, so it and the 166 // fields following it are not included in this struct. Instead, they are: 167 // 168 // 34 to (33+file_identifier_length) - file identifier 169 // 1 byte of padding, if file_identifier_length is even 170 // 171 // The remaining bytes are system use (ISO9660 extensions). 172}; 173static_assert(sizeof(DirectoryRecordHeader) == 33); 174 175// --- Volume Descriptors --- 176 177enum class VolumeDescriptorType : u8 { 178 BootRecord = 0, 179 PrimaryVolumeDescriptor = 1, 180 SupplementaryOrEnhancedVolumeDescriptor = 2, 181 VolumePartitionDescriptor = 3, 182 // 4-254 are reserved. 183 VolumeDescriptorSetTerminator = 255, 184}; 185 186// 8.1 Format of a Volume Descriptor 187struct [[gnu::packed]] VolumeDescriptorHeader { 188 VolumeDescriptorType type; 189 // NOTE: Contains exactly "CD001". 190 u8 identifier[5]; 191 u8 version; 192}; 193static_assert(sizeof(VolumeDescriptorHeader) == 7); 194 195// 8.2 Boot Record 196struct [[gnu::packed]] BootRecord { 197 VolumeDescriptorHeader header; 198 u8 boot_system_identifier[32]; 199 u8 boot_identifier[32]; 200 u8 boot_system_use[1977]; 201}; 202static_assert(sizeof(BootRecord) == 2048); 203 204// 8.3 Volume Descriptor Set Terminator 205struct [[gnu::packed]] VolumeDescriptorSetTerminator { 206 VolumeDescriptorHeader header; 207 u8 zeros[2041]; 208}; 209static_assert(sizeof(VolumeDescriptorSetTerminator) == 2048); 210 211// 8.4 Primary Volume Descriptor 212struct [[gnu::packed]] PrimaryVolumeDescriptor { 213 VolumeDescriptorHeader header; 214 u8 unused1; 215 u8 system_identifier[32]; 216 u8 volume_identifier[32]; 217 u64 unused2; 218 LittleAndBigEndian<u32> volume_space_size; 219 u8 unused3[32]; 220 LittleAndBigEndian<u16> volume_set_size; 221 LittleAndBigEndian<u16> volume_sequence_number; 222 LittleAndBigEndian<u16> logical_block_size; 223 LittleAndBigEndian<u32> path_table_size; 224 225 u32 l_path_table_occurrence_location; 226 u32 l_path_table_optional_occurrence_location; 227 u32 m_path_table_occurrence_location; 228 u32 m_path_table_optional_occurrence_location; 229 230 DirectoryRecordHeader root_directory_record_header; 231 u8 root_directory_identifier; // Exactly 0x00. 232 233 u8 volume_set_identifier[128]; 234 u8 publisher_identifier[128]; 235 u8 data_preparer_identifier[128]; 236 u8 application_identifier[128]; 237 238 u8 copyright_file_identifier[37]; 239 u8 abstract_file_identifier[37]; 240 u8 bibliographic_file_identifier[37]; 241 242 AsciiDateAndTime volume_creation_date_and_time; 243 AsciiDateAndTime volume_modification_date_and_time; 244 AsciiDateAndTime volume_expiration_date_and_time; 245 AsciiDateAndTime volume_effective_date_and_time; 246 247 u8 file_structure_version; // Always 0x01. 248 u8 unused4; 249 u8 application_use[512]; 250 u8 reserved[653]; 251}; 252static_assert(sizeof(PrimaryVolumeDescriptor) == 2048); 253 254// 8.6 Volume Partition Descriptor 255struct [[gnu::packed]] VolumePartitionDescriptor { 256 VolumeDescriptorHeader header; 257 u8 unused; 258 259 u8 system_identifier[32]; 260 u8 volume_partition_identifier[32]; 261 LittleAndBigEndian<u32> volume_partition_location; 262 LittleAndBigEndian<u32> volume_partition_size; 263 264 u8 system_use[1960]; 265}; 266static_assert(sizeof(VolumePartitionDescriptor) == 2048); 267 268} 269 270}