From: jtryba Date: Wed, 29 Jul 2026 00:03:02 +0000 (-0500) Subject: Harden GCC-4243N A102 HLDS E7 profile X-Git-Url: https://git.jtryba.com/browse/friidump.git/commitdiff_plain/1b1f91613a6976707cb92f47efa819c278c08d4f?ds=sidebyside Harden GCC-4243N A102 HLDS E7 profile --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d4b21bf..e3ebf1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,12 @@ option ( OFF ) +option ( + BUILD_HLDS_PROFILE_TESTS + "Build the read-only HLDS E7 profile-selection tests" + OFF +) + set ( FRIIDUMP_BUILD_COMMIT "" @@ -131,6 +137,25 @@ add_subdirectory (libmultihash) add_subdirectory (libfriidump) add_subdirectory (src) +if (BUILD_HLDS_PROFILE_TESTS) + enable_testing () + include_directories ( + ${FriiDump_SOURCE_DIR}/libfriidump + ) + add_executable ( + test_hlds_e7_profiles + tests/test_hlds_e7_profiles.c + ) + target_link_libraries ( + test_hlds_e7_profiles + friidumplib + ) + add_test ( + NAME hlds_e7_profiles + COMMAND test_hlds_e7_profiles + ) +endif (BUILD_HLDS_PROFILE_TESTS) + if (WIN32) install (FILES AUTHORS DESTINATION / RENAME Authors.txt) diff --git a/docs/reports/FRIIDUMP_HLDS_PROFILE_HARDENING_A102_CANDIDATE_V1.md b/docs/reports/FRIIDUMP_HLDS_PROFILE_HARDENING_A102_CANDIDATE_V1.md new file mode 100644 index 0000000..077c625 --- /dev/null +++ b/docs/reports/FRIIDUMP_HLDS_PROFILE_HARDENING_A102_CANDIDATE_V1.md @@ -0,0 +1,91 @@ +# FriiDump HLDS Profile Hardening — GCC-4243N A102 Candidate v1 + +## Purpose + +This candidate adds an exact read-only HLDS E7 profile for GCC-4243N A102. + +It also adds GCC-4244N B101 as the regression oracle. + +The candidate does not add a new command family. + +It does not change the Type3 cache geometry or Method 8 selection. + +## Accepted analyzer evidence + +Analyzer archive SHA-256: + +`9ca6cf34e8be45eebca08964285e944995e8b26490e643725542a9a7864fcfb8` + +Profiles: + +| Model and revision | CDB base | Gate | Parser tokens | +|---|---:|---:|---| +| GCC-4243N A102 | `0x880` | `0x9003731D` | `HL;IT;RPC;RPC_JCS3;RPC_SUFFIX` | +| GCC-4244N B101 | `0x894` | `0x900386D2` | `HL;IT;RPC;RPC_JCS3;RPC_SUFFIX` | + +The static CDB base and gate are diagnostic firmware evidence. + +FriiDump does not execute these addresses. + +## Runtime behavior + +A102 and B101 remain Type3 profiles with: + +- cache base `0x80000000`; +- five cache windows; +- command 2; +- Method 8. + +Unknown GCC-4243N and GCC-4244N revisions still use the conservative Type3 +fallback. + +## B101 regression role + +The accepted B101 run completed a GameCube dump and matched the known-good +image while FriiDump used the legacy Type3 fallback. + +This candidate binds B101 to the analyzer-derived reporting metadata. + +It keeps the same Type3 command and Method 8 behavior. + +The exact B101 metadata still requires a live profile-selection check before +release promotion. + +## GDR-8050L identity coherence + +The accepted release source still used `GDR-8050L 0L23` in the profile table. + +That value was the GDR-8163B package compatibility revision. + +This candidate changes the exact operating identity to `GDR-8050L 0012`. + +It keeps `0L23` as a generic GDR-8050L fallback only. It does not attach the +false GDR-8050L static metadata to that revision. + +The profile notes identify the physical test hardware as GDR-8163B with a +cross-flashed GDR-8050L 0012 payload. + +## Offline tests + +The new test covers: + +- A102 live INQUIRY spelling; +- A102 canonical spelling; +- B101 live INQUIRY spelling; +- B101 canonical spelling; +- the existing A101 profile; +- GDR-8050L 0012 identity; +- rejection of false exact GDR-8050L 0L23 metadata; +- conservative A103 and B102 Type3 fallback; +- rejection of a non-HL vendor. + +## Limits + +This candidate does not claim an A102 live dump. + +It does not claim that static firmware addresses are executable host commands. + +Live validation must start with profile selection and seed retrieval. + +A full dump and known-good hash comparison are required before A102 can move +to a live-validated tier. diff --git a/libfriidump/dvd_drive.c b/libfriidump/dvd_drive.c index fe71f80..b77a95d 100644 --- a/libfriidump/dvd_drive.c +++ b/libfriidump/dvd_drive.c @@ -200,6 +200,23 @@ static bool dvd_prod_has_any (dvd_drive *dvd, const char **needles, size_t count return false; } +static bool hlds_product_has (const char *product_id, const char *needle) { + return product_id && needle && strstr (product_id, needle) != NULL; +} + +static bool hlds_product_has_any ( + const char *product_id, + const char **needles, + size_t count +) { + size_t i; + for (i = 0; i < count; i++) { + if (hlds_product_has (product_id, needles[i])) + return true; + } + return false; +} + static bool dvd_is_hlds_gcc4243_4244_drive (dvd_drive *dvd) { static const char *names[] = { "GCC-4243N", "GCC4243N", "GCC4243", @@ -238,13 +255,17 @@ static const hlds_e7_profile_desc hlds_e7_profiles[] = { { "GCC-4242N", "0J06", 22, 0x80000000U, 1, 8, "GCC-4242N 0J06 promoted E7 parser profile", "error_prone_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0066", 0x824U, 0x90038621U, "capable but error-prone; conservative Method 8 one-window validation profile" }, { "GCC-4243N", "0000", 3, 0x80000000U, 5, 8, "GCC-4243N 0000 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0069", 0x884U, 0x90037929U, "known-supported GCC_424x profile hardening target" }, { "GCC-4243N", "1.08", 3, 0x80000000U, 5, 8, "GCC-4243N 1.08 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0071", 0x880U, 0x90036813U, "known-supported GCC_424x profile hardening target" }, + { "GCC4243", "A102", 3, 0x80000000U, 5, 8, "GCC-4243N A102 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "hybrid_identity_v3:stage5b_0439", 0x880U, 0x9003731dU, "Live INQUIRY alias for GCC4243/A102; analyzer-derived exact parser metadata; read-only profile hardening target; not yet live-validated with the exact profile" }, + { "GCC-4243N", "A102", 3, 0x80000000U, 5, 8, "GCC-4243N A102 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "hybrid_identity_v3:stage5b_0439", 0x880U, 0x9003731dU, "Canonical model alias for GCC-4243N A102; analyzer-derived exact parser metadata; read-only profile hardening target; not yet live-validated with the exact profile" }, { "GCC-4244N", "1.03", 3, 0x80000000U, 5, 8, "GCC-4244N 1.03 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0073", 0x88cU, 0x90037d06U, "P1 owned GCC_424x profile hardening target" }, { "GCC-4244N", "103", 3, 0x80000000U, 5, 8, "GCC-4244N 103 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0076", 0x894U, 0x900386fbU, "P1 owned GCC_424x profile hardening target" }, + { "GCC4244", "B101", 3, 0x80000000U, 5, 8, "GCC-4244N B101 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "hybrid_identity_v3:stage5b_0426", 0x894U, 0x900386d2U, "Live INQUIRY alias for GCC4244/B101; legacy Type3 fallback completed a Redump-matching GameCube dump; exact parser metadata is analyzer-derived and is the regression oracle for A102 hardening" }, + { "GCC-4244N", "B101", 3, 0x80000000U, 5, 8, "GCC-4244N B101 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "hybrid_identity_v3:stage5b_0426", 0x894U, 0x900386d2U, "Canonical model alias for GCC-4244N B101; legacy Type3 fallback completed a Redump-matching GameCube dump; exact parser metadata is analyzer-derived and is the regression oracle for A102 hardening" }, { "GCC4244", "B103", 3, 0x80000000U, 5, 8, "GCC-4244N B103 promoted E7 parser profile", "known_supported_profile_hardening_live_validated", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "promoted_parser_signature_v23", 0x894U, 0x900386fbU, "Live INQUIRY alias for HL-DT-ST CDRW/DVD GCC4244 B103; case label B101; exact Stage5B parser signature recovered; media preflight, seed retrieval, full GameCube dump, STOP UNIT, and Redump hash match validated" }, { "GCC-4244N", "B103", 3, 0x80000000U, 5, 8, "GCC-4244N B103 promoted E7 parser profile", "known_supported_profile_hardening_live_validated", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "promoted_parser_signature_v23", 0x894U, 0x900386fbU, "B103 shares the promoted parser signature gate/CDB with 103/104; live GCC4244/B103 hardware completed a Redump-matching GameCube dump" }, { "GCC-4244N", "104", 3, 0x80000000U, 5, 8, "GCC-4244N 104 promoted E7 parser profile", "known_supported_profile_hardening", "GCC_424x", "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX", "stage5b_0078", 0x894U, 0x900386fbU, "P1 owned GCC_424x profile hardening target" }, { "GDR-3120L", "0046", 4, 0x80000000U, 5, 8, "GDR-3120L 0046 experimental GC/Wii E7 parser profile", "experimental_gc_wii_candidate", "GDR_3120x", "HL;IT;RPC;RPC_JD4_SPACE;RPC_SUFFIX", "stage5b_0355", 0x5b8U, 0x90025bceU, "historically Xbox/reference; allow read-only GC/Wii Method 8 experiment, not proven support until dump validates" }, - { "GDR-8050L", "0L23", 44, 0x80000000U, 1, 8, "GDR-8050L 0L23 donor/modified-firmware E7 parser profile", "donor_reference_modified_firmware_only", "GDR_8050x", "HL;IT;RPC;RPC_JD4_SPACE;RPC_SUFFIX", "stage5b_0099", 0x5d0U, 0x90026160U, "stock firmware is Xbox-only here; GC/Wii 0xE7 path requires modified firmware with memdump support" }, + { "GDR-8050L", "0012", 44, 0x80000000U, 1, 8, "GDR-8050L 0012 hybrid cross-flash E7 parser profile", "hybrid_crossflash_modified_firmware_only", "GDR_8050x", "HL;IT;RPC;RPC_JD4_SPACE;RPC_SUFFIX", "hybrid_identity_v3:gdr8050l_0012", 0x5d0U, 0x90026160U, "Operating identity is GDR-8050L 0012 on GDR-8163B physical hardware; package compatibility identity is GDR-8163B 0L23; GC/Wii 0xE7 access requires modified firmware; native GDR-8050L hardware is not owned" }, { "GDR-8082N", "0120", 4, 0x80000000U, 5, 9, "GDR-8082N 0120 promoted E7 parser profile", "known_supported_profile_hardening", "GDR_808x", "HL;IT;RPC;RPC_SUFFIX", "stage5b_0103", 0x638U, 0x900282daU, "known-supported reference profile" }, { "GDR-8083N", "0K04", 4, 0x80000000U, 5, 9, "GDR-8083N 0K04 promoted E7 parser profile", "known_supported_profile_hardening", "GDR_808x", "HL;IT;RPC;RPC_SUFFIX", "stage5b_0104", 0x638U, 0x900291fcU, "known-supported reference profile" }, { "GDR-8161B", "0102", 4, 0x80000000U, 5, 9, "GDR-8161B 0102 promoted E7 parser profile", "known_supported_profile_hardening", "GDR_816x", "IT;RPC;RPC_SUFFIX", "stage5b_0109", 0x5a8U, 0x90025010U, "known-supported reference profile" }, @@ -274,25 +295,25 @@ static void hlds_normalize_model (const char *src, char *dst, size_t dst_size) { dst[j] = 0; } -static bool hlds_model_matches (dvd_drive *dvd, const char *model) { +static bool hlds_model_matches_value (const char *product_id, const char *model) { char prod_norm[64]; char model_norm[64]; - if (!dvd || !dvd -> prod_id || !model) + if (!product_id || !model) return false; - hlds_normalize_model (dvd -> prod_id, prod_norm, sizeof (prod_norm)); + hlds_normalize_model (product_id, prod_norm, sizeof (prod_norm)); hlds_normalize_model (model, model_norm, sizeof (model_norm)); return prod_norm[0] && model_norm[0] && strstr (prod_norm, model_norm) != NULL; } -static bool hlds_revision_matches (dvd_drive *dvd, const char *revision) { +static bool hlds_revision_matches_value (const char *actual, const char *expected) { const unsigned char *a; const unsigned char *b; - if (!revision || !revision[0]) + if (!expected || !expected[0]) return true; - if (!dvd || !dvd -> prod_rev) + if (!actual) return false; - a = (const unsigned char *) dvd -> prod_rev; - b = (const unsigned char *) revision; + a = (const unsigned char *) actual; + b = (const unsigned char *) expected; while (*a && *b) { if (toupper (*a) != toupper (*b)) return false; @@ -302,19 +323,70 @@ static bool hlds_revision_matches (dvd_drive *dvd, const char *revision) { return *a == 0 && *b == 0; } -static const hlds_e7_profile_desc *dvd_find_hlds_e7_profile (dvd_drive *dvd) { +static const hlds_e7_profile_desc *hlds_find_e7_profile_for_identity ( + const char *vendor, + const char *product_id, + const char *revision +) { const hlds_e7_profile_desc *p; - if (!dvd_is_hlds_drive (dvd)) + if (!vendor || strcmp (vendor, "HL-DT-ST") != 0) return NULL; for (p = hlds_e7_profiles; p -> model; p++) { - if (hlds_model_matches (dvd, p -> model) && hlds_revision_matches (dvd, p -> firmware)) + if ( + hlds_model_matches_value (product_id, p -> model) && + hlds_revision_matches_value (revision, p -> firmware) + ) return p; } return NULL; } -static u_int32_t dvd_hlds_e7_detect_type (dvd_drive *dvd) { - const hlds_e7_profile_desc *profile = dvd_find_hlds_e7_profile (dvd); +static const hlds_e7_profile_desc *dvd_find_hlds_e7_profile (dvd_drive *dvd) { + if (!dvd) + return NULL; + return hlds_find_e7_profile_for_identity ( + dvd -> vendor, + dvd -> prod_id, + dvd -> prod_rev + ); +} + +bool dvd_lookup_hlds_e7_profile ( + const char *vendor, + const char *product_id, + const char *revision, + dvd_hlds_e7_profile_info *out +) { + const hlds_e7_profile_desc *p; + if (out) + memset (out, 0, sizeof (*out)); + p = hlds_find_e7_profile_for_identity (vendor, product_id, revision); + if (!p) + return false; + if (out) { + out -> type = p -> type; + out -> cache_base = p -> cache_base; + out -> mem_blocks = p -> mem_blocks; + out -> preferred_method = p -> preferred_method; + out -> label = p -> label; + out -> support_tier = p -> support_tier; + out -> family = p -> family; + out -> tokens = p -> tokens; + out -> record_id = p -> record_id; + out -> static_cdb_base = p -> static_cdb_base; + out -> static_gate = p -> static_gate; + out -> notes = p -> notes; + } + return true; +} + +u_int32_t dvd_detect_hlds_e7_type_for_identity ( + const char *vendor, + const char *product_id, + const char *revision +) { + const hlds_e7_profile_desc *profile = + hlds_find_e7_profile_for_identity (vendor, product_id, revision); static const char *type1[] = { "GCC-4160N", "GCC4160N", "GCC4160", "GCC-4240N", "GCC4240N", "GCC4240" @@ -344,29 +416,39 @@ static u_int32_t dvd_hlds_e7_detect_type (dvd_drive *dvd) { "GDR3120L", "GDR-3120L" }; - if (!dvd_is_hlds_drive (dvd)) + if (!vendor || strcmp (vendor, "HL-DT-ST") != 0) return 0; if (profile) return profile -> type; - if (dvd_prod_has_any (dvd, type1, sizeof (type1) / sizeof (type1[0]))) + if (hlds_product_has_any (product_id, type1, sizeof (type1) / sizeof (type1[0]))) return 1; - if (dvd_prod_has_any (dvd, type2_1, sizeof (type2_1) / sizeof (type2_1[0]))) + if (hlds_product_has_any (product_id, type2_1, sizeof (type2_1) / sizeof (type2_1[0]))) return 21; - if (dvd_prod_has_any (dvd, type2_2, sizeof (type2_2) / sizeof (type2_2[0]))) + if (hlds_product_has_any (product_id, type2_2, sizeof (type2_2) / sizeof (type2_2[0]))) return 22; - if (dvd_prod_has_any (dvd, gdr8081n, sizeof (gdr8081n) / sizeof (gdr8081n[0]))) + if (hlds_product_has_any (product_id, gdr8081n, sizeof (gdr8081n) / sizeof (gdr8081n[0]))) return 81; - if (dvd_prod_has_any (dvd, type3, sizeof (type3) / sizeof (type3[0]))) + if (hlds_product_has_any (product_id, type3, sizeof (type3) / sizeof (type3[0]))) return 3; - if (dvd_is_hlds_gdr8050l_drive (dvd)) + if (hlds_product_has (product_id, "GDR8050L") || hlds_product_has (product_id, "GDR-8050L")) return 44; - if (dvd_prod_has_any (dvd, type4, sizeof (type4) / sizeof (type4[0]))) + if (hlds_product_has_any (product_id, type4, sizeof (type4) / sizeof (type4[0]))) return 4; /* DIC labels GSA-4163B as an Xbox swap candidate, not a normal 0xE7 * Nintendo-disc cache dump profile, so keep it out of the profile layer. */ return 0; } +static u_int32_t dvd_hlds_e7_detect_type (dvd_drive *dvd) { + if (!dvd) + return 0; + return dvd_detect_hlds_e7_type_for_identity ( + dvd -> vendor, + dvd -> prod_id, + dvd -> prod_rev + ); +} + static bool dvd_is_hlds_gc_wii_drive (dvd_drive *dvd) { return dvd_hlds_e7_detect_type (dvd) != 0; } diff --git a/libfriidump/dvd_drive.h b/libfriidump/dvd_drive.h index cac3627..2508fa2 100644 --- a/libfriidump/dvd_drive.h +++ b/libfriidump/dvd_drive.h @@ -56,6 +56,24 @@ typedef struct { u_int8_t cdb[12]; } dvd_command_diagnostic; +/* Read-only metadata for an exact HLDS/MN103 0xE7 profile match. + * Static firmware addresses are diagnostic evidence only. FriiDump does not + * execute these addresses or issue firmware-write commands through this API. */ +typedef struct { + u_int32_t type; + u_int32_t cache_base; + u_int32_t mem_blocks; + int preferred_method; + const char *label; + const char *support_tier; + const char *family; + const char *tokens; + const char *record_id; + u_int32_t static_cdb_base; + u_int32_t static_gate; + const char *notes; +} dvd_hlds_e7_profile_info; + typedef enum { DVD_DATA_NONE = 0, @@ -119,6 +137,17 @@ void *dvd_get_native_handle (dvd_drive *dvd); bool dvd_get_support_status (dvd_drive *dvd); u_int32_t dvd_get_def_method (dvd_drive *dvd); u_int32_t dvd_get_command (dvd_drive *dvd); +bool dvd_lookup_hlds_e7_profile ( + const char *vendor, + const char *product_id, + const char *revision, + dvd_hlds_e7_profile_info *out +); +u_int32_t dvd_detect_hlds_e7_type_for_identity ( + const char *vendor, + const char *product_id, + const char *revision +); const char *dvd_get_hlds_e7_profile_name (dvd_drive *dvd); const char *dvd_get_hlds_e7_support_tier (dvd_drive *dvd); const char *dvd_get_hlds_e7_family (dvd_drive *dvd); diff --git a/tests/test_hlds_e7_profiles.c b/tests/test_hlds_e7_profiles.c new file mode 100644 index 0000000..a7b6612 --- /dev/null +++ b/tests/test_hlds_e7_profiles.c @@ -0,0 +1,158 @@ +#include "dvd_drive.h" + +#include +#include + +typedef struct { + const char *label; + const char *vendor; + const char *product; + const char *revision; + bool exact; + u_int32_t type; + u_int32_t cdb; + u_int32_t gate; + u_int32_t blocks; + int method; + const char *record_id; + const char *tokens; +} profile_case; + +static int check_case(const profile_case *test) { + dvd_hlds_e7_profile_info info; + bool exact = dvd_lookup_hlds_e7_profile( + test->vendor, + test->product, + test->revision, + &info); + u_int32_t detected = dvd_detect_hlds_e7_type_for_identity( + test->vendor, + test->product, + test->revision); + + if (exact != test->exact) { + fprintf(stderr, + "FAIL: %s exact=%d expected=%d\n", + test->label, (int) exact, (int) test->exact); + return 0; + } + + if (detected != test->type) { + fprintf(stderr, + "FAIL: %s type=%u expected=%u\n", + test->label, detected, test->type); + return 0; + } + + if (!exact) { + printf("PASS: %s legacy type=%u\n", test->label, detected); + return 1; + } + + if ( + info.type != test->type || + info.static_cdb_base != test->cdb || + info.static_gate != test->gate || + info.mem_blocks != test->blocks || + info.preferred_method != test->method || + !info.tokens || + strcmp(info.tokens, test->tokens) != 0 || + !info.record_id || + strcmp(info.record_id, test->record_id) != 0 + ) { + fprintf(stderr, + "FAIL: %s type=%u cdb=0x%03x gate=0x%08x " + "blocks=%u method=%d tokens=%s record=%s\n", + test->label, + info.type, + info.static_cdb_base, + info.static_gate, + info.mem_blocks, + info.preferred_method, + info.tokens ? info.tokens : "(null)", + info.record_id ? info.record_id : "(null)"); + return 0; + } + + printf("PASS: %s exact cdb=0x%03x gate=0x%08x\n", + test->label, info.static_cdb_base, info.static_gate); + return 1; +} + +int main(void) { + static const profile_case cases[] = { + { + "A102 live inquiry alias", + "HL-DT-ST", "CDRW/DVD GCC4243", "A102", + true, 3, 0x880U, 0x9003731dU, 5, 8, + "hybrid_identity_v3:stage5b_0439", + "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX" + }, + { + "A102 canonical alias", + "HL-DT-ST", "GCC-4243N", "a102", + true, 3, 0x880U, 0x9003731dU, 5, 8, + "hybrid_identity_v3:stage5b_0439", + "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX" + }, + { + "B101 live inquiry alias", + "HL-DT-ST", "CDRW/DVD GCC4244", "B101", + true, 3, 0x894U, 0x900386d2U, 5, 8, + "hybrid_identity_v3:stage5b_0426", + "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX" + }, + { + "B101 canonical alias", + "HL-DT-ST", "GCC-4244N", "b101", + true, 3, 0x894U, 0x900386d2U, 5, 8, + "hybrid_identity_v3:stage5b_0426", + "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX" + }, + { + "A101 existing canonical profile", + "HL-DT-ST", "GCC-4241N", "A101", + true, 21, 0x85cU, 0x900356b7U, 1, 8, + "stage5b_0064", + "HL;IT;RPC;RPC_JCS3;RPC_SUFFIX" + }, + { + "GDR-8050L 0012 hybrid operating identity", + "HL-DT-ST", "DVD-ROM GDR8050L", "0012", + true, 44, 0x5d0U, 0x90026160U, 1, 8, + "hybrid_identity_v3:gdr8050l_0012", + "HL;IT;RPC;RPC_JD4_SPACE;RPC_SUFFIX" + }, + { + "GDR-8050L 0L23 has no false exact metadata", + "HL-DT-ST", "DVD-ROM GDR8050L", "0L23", + false, 44, 0, 0, 0, 0, NULL, NULL + }, + { + "A103 conservative Type3 fallback", + "HL-DT-ST", "CDRW/DVD GCC4243", "A103", + false, 3, 0, 0, 0, 0, NULL, NULL + }, + { + "B102 conservative Type3 fallback", + "HL-DT-ST", "CDRW/DVD GCC4244", "B102", + false, 3, 0, 0, 0, 0, NULL, NULL + }, + { + "non-HL vendor rejected", + "NOT-HL", "CDRW/DVD GCC4243", "A102", + false, 0, 0, 0, 0, 0, NULL, NULL + } + }; + size_t i; + int ok = 1; + + for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) + ok &= check_case(&cases[i]); + + if (!ok) + return 1; + + printf("HLDS E7 PROFILE SELECTION TESTS: PASS\n"); + return 0; +}