From c453aac65fda0043c714cf90d1d315dfb302999d Mon Sep 17 00:00:00 2001 From: anonymix007 <48598263+anonymix007@users.noreply.github.com> Date: Mon, 31 Mar 2025 20:38:24 +0300 Subject: [PATCH] fundamental: Introduce EDID header parsing --- src/fundamental/edid-fundamental.c | 49 ++++++++++++++++++++++++++++++ src/fundamental/edid-fundamental.h | 29 ++++++++++++++++++ src/fundamental/meson.build | 1 + 3 files changed, 79 insertions(+) create mode 100644 src/fundamental/edid-fundamental.c create mode 100644 src/fundamental/edid-fundamental.h diff --git a/src/fundamental/edid-fundamental.c b/src/fundamental/edid-fundamental.c new file mode 100644 index 00000000000..9657d967044 --- /dev/null +++ b/src/fundamental/edid-fundamental.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "edid-fundamental.h" +#include "efivars-fundamental.h" + +#define EDID_FIXED_HEADER_PATTERN "\x00\xFF\xFF\xFF\xFF\xFF\xFF" +assert_cc(sizeof_field(EdidHeader, pattern) == sizeof(EDID_FIXED_HEADER_PATTERN)); + +int edid_parse_blob(const void *blob, size_t blob_size, EdidHeader *ret_header) { + assert(ret_header); + + /* EDID size is at least 128 as per the specification */ + if (blob_size < 128) + return -EINVAL; + + const EdidHeader *edid_header = ASSERT_PTR(blob); + if (memcmp(edid_header->pattern, EDID_FIXED_HEADER_PATTERN, sizeof(EDID_FIXED_HEADER_PATTERN)) != 0) + return -EINVAL; + + *ret_header = (EdidHeader) { + .pattern = EDID_FIXED_HEADER_PATTERN, + .manufacturer_id = be16toh(edid_header->manufacturer_id), + .manufacturer_product_code = le16toh(edid_header->manufacturer_product_code), + .serial_number = le32toh(edid_header->serial_number), + .week_of_manufacture = edid_header->week_of_manufacture, + .year_of_manufacture = edid_header->year_of_manufacture, + .edid_version = edid_header->edid_version, + .edid_revision = edid_header->edid_revision, + }; + return 0; +} + +int edid_get_panel_id(const EdidHeader *edid_header, char16_t ret_panel[static 8]) { + assert(edid_header); + assert(ret_panel); + + for (size_t i = 0; i < 3; i++) { + uint8_t letter = (edid_header->manufacturer_id >> (5 * i)) & 0b11111; + if (letter > 0b11010) + return -EINVAL; + ret_panel[2 - i] = letter + 'A' - 1; + } + ret_panel[3] = LOWERCASE_HEXDIGITS[(edid_header->manufacturer_product_code >> 12) & 0x0F]; + ret_panel[4] = LOWERCASE_HEXDIGITS[(edid_header->manufacturer_product_code >> 8) & 0x0F]; + ret_panel[5] = LOWERCASE_HEXDIGITS[(edid_header->manufacturer_product_code >> 4) & 0x0F]; + ret_panel[6] = LOWERCASE_HEXDIGITS[(edid_header->manufacturer_product_code >> 0) & 0x0F]; + ret_panel[7] = L'\0'; + return 0; +} diff --git a/src/fundamental/edid-fundamental.h b/src/fundamental/edid-fundamental.h new file mode 100644 index 00000000000..52473784d90 --- /dev/null +++ b/src/fundamental/edid-fundamental.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#if SD_BOOT +# include "efi-string.h" +# include "util.h" +#else +# include +# include +# include +# include +#endif + +#include "string-util-fundamental.h" + +/* EDID structure, version 1.4 */ +typedef struct EdidHeader { + uint8_t pattern[8]; /* fixed pattern */ + uint16_t manufacturer_id; /* big-endian 3-letter code */ + uint16_t manufacturer_product_code; /* little-endian */ + uint32_t serial_number; /* little-endian */ + uint8_t week_of_manufacture; /* week or model year flag (0xFF) */ + uint8_t year_of_manufacture; /* year or model if flag is set (0 is 1990) */ + uint8_t edid_version; /* 0x01 for 1.3 and 1.4 */ + uint8_t edid_revision; /* 0x03 for 1.3, 0x04 for 1.4 */ +} _packed_ EdidHeader; + +int edid_parse_blob(const void *blob, size_t blob_size, EdidHeader *ret_header); +int edid_get_panel_id(const EdidHeader *edid_header, char16_t ret_panel[static 8]); diff --git a/src/fundamental/meson.build b/src/fundamental/meson.build index 7b72372e838..5536be6e4c4 100644 --- a/src/fundamental/meson.build +++ b/src/fundamental/meson.build @@ -5,6 +5,7 @@ fundamental_include = include_directories('.') fundamental_sources = files( 'bootspec-fundamental.c', 'chid-fundamental.c', + 'edid-fundamental.c', 'efivars-fundamental.c', 'iovec-util-fundamental.h', 'sha1-fundamental.c', -- 2.47.3