diff --git a/include/aaru.h b/include/aaru.h index 328110c..573b339 100644 --- a/include/aaru.h +++ b/include/aaru.h @@ -161,6 +161,7 @@ typedef enum BDRE = 62, ///< BD-RE BDRXL = 63, ///< BD-R XL BDREXL = 64, ///< BD-RE XL + UHDBD = 65, ///< Ultra HD Blu-ray // Standard Blu-ray formats, types 60 to 69 // Rare or uncommon optical standards, types 70 to 79 @@ -211,6 +212,7 @@ typedef enum PS4BD = 117, ///< Sony PlayStation 4 game Blu-ray UMD = 118, ///< Sony PlayStation Portable Universal Media Disc (ECMA-365) PlayStationVitaGameCard = 119, ///< PS Vita NV memory card (proprietary flash) + PS5BD = 120, ///< Sony PlayStation 5 game Blu-ray // Sony game media, types 110 to 129 // Microsoft game media, types 130 to 149 @@ -977,6 +979,7 @@ typedef enum kSectorTagDvdSectorEdc = 19, ///< DVD sector EDC, 4 bytes kSectorTagAppleProfile = 20, ///< Apple's Profile sector tags, 20 bytes kSectorTagPriamDataTower = 21, ///< Priam DataTower sector tags, 24 bytes + kSectorTagBdSectorEdc = 22, ///< Blu-ray sector EDC, 4 bytes MaxSectorTag = kSectorTagPriamDataTower } SectorTagType; @@ -1082,6 +1085,8 @@ typedef enum kMediaTagWiiUPartitionKeyMap = 82, ///< Nintendo Wii U partition-to-key mapping with regions kMediaTagWiiPartitionKeyMap = 83, ///< Nintendo Wii partition-to-key mapping with regions kMediaTagNgcwJunkMap = 84, ///< Nintendo GameCube/Wii junk region map with LFG seeds + kMediaTagAacsMediaKey = 85, ///< AACS Media Key + kMediaTagAacsVolumeUniqueKey = 86, ///< AACS Volume Unique Key MaxMediaTag = kMediaTagNgcwJunkMap } MediaTagType; diff --git a/include/aaruformat/enums.h b/include/aaruformat/enums.h index e56f45d..1f8e1f7 100644 --- a/include/aaruformat/enums.h +++ b/include/aaruformat/enums.h @@ -145,6 +145,9 @@ typedef enum kDataTypeWiiUPartitionKeyMap = 98, ///< Nintendo Wii U partition-to-key mapping with regions kDataTypeWiiPartitionKeyMap = 99, ///< Nintendo Wii partition-to-key mapping with regions kDataTypeNgcwJunkMap = 100, ///< Nintendo GameCube/Wii junk region map with LFG seeds + kDataTypeAacsMediaKey = 101, ///< AACS Media Key + kDataTypeAacsVolumeUniqueKey = 102, ///< AACS Volume Unique Key + kDataTypeBdSectorEdc = 103, ///< Blu-ray Sector EDC } DataType; /** diff --git a/src/blocks/data.c b/src/blocks/data.c index 0c3972c..a1dad02 100644 --- a/src/blocks/data.c +++ b/src/blocks/data.c @@ -480,6 +480,10 @@ int32_t process_data_block(aaruformat_context *ctx, IndexEntry *entry) ctx->sector_decrypted_title_key = data; ctx->readableSectorTags[kSectorTagDvdTitleKeyDecrypted] = true; break; + case kDataTypeBdSectorEdc: + ctx->sector_edc = data; + ctx->readableSectorTags[kSectorTagBdSectorEdc] = true; + break; default: media_tag = (mediaTagEntry *)malloc(sizeof(mediaTagEntry)); diff --git a/src/helpers.c b/src/helpers.c index 97e4c83..7fcf0dd 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -202,6 +202,10 @@ AARU_LOCAL int32_t AARU_CALL aaruf_get_media_tag_type_for_datatype(const int32_t return kMediaTagWiiPartitionKeyMap; case kDataTypeNgcwJunkMap: return kMediaTagNgcwJunkMap; + case kDataTypeAacsMediaKey: + return kMediaTagAacsMediaKey; + case kDataTypeAacsVolumeUniqueKey: + return kMediaTagAacsVolumeUniqueKey; default: return -1; } @@ -382,6 +386,10 @@ AARU_LOCAL int32_t AARU_CALL aaruf_get_datatype_for_media_tag_type(const int32_t return kDataTypeWiiPartitionKeyMap; case kMediaTagNgcwJunkMap: return kDataTypeNgcwJunkMap; + case kMediaTagAacsMediaKey: + return kDataTypeAacsMediaKey; + case kMediaTagAacsVolumeUniqueKey: + return kDataTypeAacsVolumeUniqueKey; default: return -1; } diff --git a/src/read.c b/src/read.c index c3fc8c3..0ef033f 100644 --- a/src/read.c +++ b/src/read.c @@ -1542,70 +1542,134 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64 } if(ctx->image_info.MediaType == GOD || ctx->image_info.MediaType == WOD) - { - if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL || - ctx->sector_edc == NULL) - return aaruf_read_sector(context, sector_address, negative, data, length, sector_status); - - if(*length < 2064 || data == NULL) - { - *length = 2064; - FATAL("Buffer too small for sector, required %u bytes", *length); - - TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL"); - return AARUF_ERROR_BUFFER_TOO_SMALL; - } - - bare_length = 0; - query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status); - - if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK) - { - TRACE("Exiting aaruf_read_sector_long() = %d", query_status); - return query_status; - } - - if(bare_length == 0) - { - FATAL("Invalid bare sector length (0)"); - - TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE"); - return AARUF_ERROR_INCORRECT_DATA_SIZE; - } - - TRACE("Allocating memory for bare data"); - bare_data = (uint8_t *)malloc(bare_length); - - if(bare_data == NULL) - { - FATAL("Could not allocate memory for bare data"); - - TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY"); - return AARUF_ERROR_NOT_ENOUGH_MEMORY; - } - - res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status); - - if(res != AARUF_STATUS_OK) - { - *length = 2064; - free(bare_data); - - TRACE("Exiting aaruf_read_sector_long() = %d", res); - return res; - } - - memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4); - memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2); - memcpy(data + 6, bare_data, 2048); - memcpy(data + 2054, ctx->sector_cpr_mai + corrected_sector_address * 6, 6); - memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4); - - *length = 2064; - - free(bare_data); - return AARUF_STATUS_OK; - } + { + if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL || + ctx->sector_edc == NULL) + return aaruf_read_sector(context, sector_address, negative, data, length, sector_status); + + if(*length < 2064 || data == NULL) + { + *length = 2064; + FATAL("Buffer too small for sector, required %u bytes", *length); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL"); + return AARUF_ERROR_BUFFER_TOO_SMALL; + } + + bare_length = 0; + query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status); + + if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK) + { + TRACE("Exiting aaruf_read_sector_long() = %d", query_status); + return query_status; + } + + if(bare_length == 0) + { + FATAL("Invalid bare sector length (0)"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE"); + return AARUF_ERROR_INCORRECT_DATA_SIZE; + } + + TRACE("Allocating memory for bare data"); + bare_data = (uint8_t *)malloc(bare_length); + + if(bare_data == NULL) + { + FATAL("Could not allocate memory for bare data"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY"); + return AARUF_ERROR_NOT_ENOUGH_MEMORY; + } + + res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status); + + if(res != AARUF_STATUS_OK) + { + *length = 2064; + free(bare_data); + + TRACE("Exiting aaruf_read_sector_long() = %d", res); + return res; + } + + memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4); + memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2); + memcpy(data + 6, bare_data, 2048); + memcpy(data + 2054, ctx->sector_cpr_mai + corrected_sector_address * 6, 6); + memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4); + + *length = 2064; + + free(bare_data); + return AARUF_STATUS_OK; + } + + if(ctx->image_info.MediaType == BDROM || ctx->image_info.MediaType == BDR || + ctx->image_info.MediaType == BDRE || ctx->image_info.MediaType == BDRXL || + ctx->image_info.MediaType == BDREXL || ctx->image_info.MediaType == UHDBD || + ctx->image_info.MediaType == XGD4 || ctx->image_info.MediaType == PS3BD || + ctx->image_info.MediaType == PS4BD || ctx->image_info.MediaType == PS5BD) + { + if(ctx->sector_edc == NULL) return aaruf_read_sector(context, sector_address, negative, data, length, sector_status); + + if(*length < 2052 || data == NULL) + { + *length = 2052; + FATAL("Buffer too small for sector, required %u bytes", *length); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL"); + return AARUF_ERROR_BUFFER_TOO_SMALL; + } + + bare_length = 0; + query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status); + + if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK) + { + TRACE("Exiting aaruf_read_sector_long() = %d", query_status); + return query_status; + } + + if(bare_length == 0) + { + FATAL("Invalid bare sector length (0)"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE"); + return AARUF_ERROR_INCORRECT_DATA_SIZE; + } + + TRACE("Allocating memory for bare data"); + bare_data = (uint8_t *)malloc(bare_length); + + if(bare_data == NULL) + { + FATAL("Could not allocate memory for bare data"); + + TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY"); + return AARUF_ERROR_NOT_ENOUGH_MEMORY; + } + + res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status); + + if(res != AARUF_STATUS_OK) + { + free(bare_data); + + TRACE("Exiting aaruf_read_sector_long() = %d", res); + return res; + } + + memcpy(data, bare_data, 2048); + memcpy(data + 2048, ctx->sector_edc + corrected_sector_address * 4, 4); + + *length = 2052; + + free(bare_data); + return AARUF_STATUS_OK; + } if(*length < 2352 || data == NULL) { diff --git a/src/write.c b/src/write.c index f6ed8fc..c05bd38 100644 --- a/src/write.c +++ b/src/write.c @@ -735,6 +735,20 @@ AARU_EXPORT int32_t AARU_CALL aaruf_write_sector_long(void *context, uint64_t se return aaruf_write_sector(context, sector_address, negative, data + 6, sector_status, 2048); } + // Blu-ray long sector + if(length == 2052 && (ctx->image_info.MediaType == BDROM || ctx->image_info.MediaType == BDR || + ctx->image_info.MediaType == BDRE || ctx->image_info.MediaType == BDRXL || + ctx->image_info.MediaType == BDREXL || ctx->image_info.MediaType == UHDBD || + ctx->image_info.MediaType == XGD4 || ctx->image_info.MediaType == PS3BD || + ctx->image_info.MediaType == PS4BD || ctx->image_info.MediaType == PS5BD)) + { + if(ctx->sector_edc == NULL) ctx->sector_edc = calloc(1, 4 * total_sectors); + + memcpy(ctx->sector_edc + corrected_sector_address * 4, data + 2048, 4); + + return aaruf_write_sector(context, sector_address, negative, data, sector_status, 2048); + } + if(length != 2352) { FATAL("Incorrect sector size"); diff --git a/tool/helpers.c b/tool/helpers.c index 08c0ef2..b708ede 100644 --- a/tool/helpers.c +++ b/tool/helpers.c @@ -206,6 +206,10 @@ const char *media_tag_type_to_string(int32_t type) return "DVD Physical Format Information (2nd layer)"; case kMediaTagFloppyWriteProtect: return "Floppy Write-Protect Status"; + case kMediaTagAacsMediaKey: + return "AACS Media Key"; + case kMediaTagAacsVolumeUniqueKey: + return "AACS Volume Unique Key"; default: return "Unknown Media Tag"; } @@ -391,6 +395,12 @@ const char *data_type_to_string(uint16_t type) return "DVD Physical Format Info (2nd layer)"; case kDataTypeFloppyWriteProtect: return "Floppy Write-Protect Status"; + case kDataTypeAacsMediaKey: + return "AACS Media Key"; + case kDataTypeAacsVolumeUniqueKey: + return "AACS Volume Unique Key"; + case kDataTypeBdSectorEdc: + return "Blu-ray Sector EDC"; default: return "Unknown Data Type"; } @@ -1587,6 +1597,8 @@ const char *sector_tag_type_to_string(int32_t type) return "Apple Profile Tag"; case kSectorTagPriamDataTower: return "Priam DataTower Tag"; + case kSectorTagBdSectorEdc: + return "Blu-ray Sector EDC"; default: return "Unknown Sector Tag"; } diff --git a/tool/inject_media_tag.c b/tool/inject_media_tag.c index 701eb92..f34d1c2 100644 --- a/tool/inject_media_tag.c +++ b/tool/inject_media_tag.c @@ -134,6 +134,8 @@ static const MediaTagTypeMapping media_tag_mappings[] = { {"kMediaTagDvdDiscKeyDecrypted", kMediaTagDvdDiscKeyDecrypted}, {"kMediaTagDvdPfi2ndLayer", kMediaTagDvdPfi2ndLayer}, {"kMediaTagFloppyWriteProtect", kMediaTagFloppyWriteProtect}, + {"kMediaTagAacsMediaKey", kMediaTagAacsMediaKey}, + {"kMediaTagAacsVolumeUniqueKey", kMediaTagAacsVolumeUniqueKey}, }; // clang-format on @@ -290,6 +292,10 @@ static int32_t get_datatype_for_media_tag_type(MediaTagType tag_type) return kDataTypeDvdDiscKeyDecrypted; case kMediaTagFloppyWriteProtect: return kDataTypeFloppyWriteProtect; + case kMediaTagAacsMediaKey: + return kDataTypeAacsMediaKey; + case kMediaTagAacsVolumeUniqueKey: + return kDataTypeAacsVolumeUniqueKey; default: return -1; }