fundamental: Introduce EDID header parsing
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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 <endian.h>
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
# include <uchar.h>
|
||||
#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]);
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user