mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
3.7 KiB
187 lines
3.7 KiB
// SPDX-License-Identifier: GPL-2.0+ |
|
/* |
|
* efi_selftest_pos |
|
* |
|
* Copyright (c) 2018 Heinrich Schuchardt <[email protected]> |
|
* |
|
* Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. |
|
* |
|
* The following services are tested: |
|
* OutputString, TestString, SetAttribute. |
|
*/ |
|
|
|
#include <efi_selftest.h> |
|
#include <linux/libfdt.h> |
|
|
|
static struct efi_boot_services *boottime; |
|
static const char *fdt; |
|
|
|
/* This should be sufficent for */ |
|
#define BUFFERSIZE 0x100000 |
|
|
|
static efi_guid_t fdt_guid = EFI_FDT_GUID; |
|
|
|
/* |
|
* Convert FDT value to host endianness. |
|
* |
|
* @val FDT value |
|
* @return converted value |
|
*/ |
|
static uint32_t f2h(fdt32_t val) |
|
{ |
|
char *buf = (char *)&val; |
|
char i; |
|
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
|
/* Swap the bytes */ |
|
i = buf[0]; buf[0] = buf[3]; buf[3] = i; |
|
i = buf[1]; buf[1] = buf[2]; buf[2] = i; |
|
#endif |
|
return *(uint32_t *)buf; |
|
} |
|
|
|
/* |
|
* Return the value of a property of the FDT root node. |
|
* |
|
* @name name of the property |
|
* @return value of the property |
|
*/ |
|
static char *get_property(const u16 *property) |
|
{ |
|
struct fdt_header *header = (struct fdt_header *)fdt; |
|
const fdt32_t *pos; |
|
const char *strings; |
|
|
|
if (!header) |
|
return NULL; |
|
|
|
if (f2h(header->magic) != FDT_MAGIC) { |
|
printf("Wrong magic\n"); |
|
return NULL; |
|
} |
|
|
|
pos = (fdt32_t *)(fdt + f2h(header->off_dt_struct)); |
|
strings = fdt + f2h(header->off_dt_strings); |
|
|
|
for (;;) { |
|
switch (f2h(pos[0])) { |
|
case FDT_BEGIN_NODE: { |
|
char *c = (char *)&pos[1]; |
|
size_t i; |
|
|
|
for (i = 0; c[i]; ++i) |
|
; |
|
pos = &pos[2 + (i >> 2)]; |
|
break; |
|
} |
|
case FDT_PROP: { |
|
struct fdt_property *prop = (struct fdt_property *)pos; |
|
const char *label = &strings[f2h(prop->nameoff)]; |
|
efi_status_t ret; |
|
|
|
/* Check if this is the property to be returned */ |
|
if (!efi_st_strcmp_16_8(property, label)) { |
|
char *str; |
|
efi_uintn_t len = f2h(prop->len); |
|
|
|
if (!len) |
|
return NULL; |
|
/* |
|
* The string might not be 0 terminated. |
|
* It is safer to make a copy. |
|
*/ |
|
ret = boottime->allocate_pool( |
|
EFI_LOADER_DATA, len + 1, |
|
(void **)&str); |
|
if (ret != EFI_SUCCESS) { |
|
efi_st_printf("AllocatePool failed\n"); |
|
return NULL; |
|
} |
|
boottime->copy_mem(str, &pos[3], len); |
|
str[len] = 0; |
|
|
|
return str; |
|
} |
|
|
|
pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)]; |
|
break; |
|
} |
|
case FDT_NOP: |
|
pos = &pos[1]; |
|
break; |
|
default: |
|
return NULL; |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* Setup unit test. |
|
* |
|
* @handle: handle of the loaded image |
|
* @systable: system table |
|
* @return: EFI_ST_SUCCESS for success |
|
*/ |
|
static int setup(const efi_handle_t img_handle, |
|
const struct efi_system_table *systable) |
|
{ |
|
efi_uintn_t i; |
|
|
|
boottime = systable->boottime; |
|
|
|
/* Find configuration tables */ |
|
for (i = 0; i < systable->nr_tables; ++i) { |
|
if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid, |
|
sizeof(efi_guid_t))) |
|
fdt = systable->tables[i].table; |
|
} |
|
if (!fdt) { |
|
efi_st_error("Missing device tree\n"); |
|
return EFI_ST_FAILURE; |
|
} |
|
|
|
return EFI_ST_SUCCESS; |
|
} |
|
|
|
/* |
|
* Execute unit test. |
|
* |
|
* @return: EFI_ST_SUCCESS for success |
|
*/ |
|
static int execute(void) |
|
{ |
|
char *str; |
|
efi_status_t ret; |
|
|
|
str = get_property(L"compatible"); |
|
if (str) { |
|
efi_st_printf("compatible: %s\n", str); |
|
ret = boottime->free_pool(str); |
|
if (ret != EFI_SUCCESS) { |
|
efi_st_error("FreePool failed\n"); |
|
return EFI_ST_FAILURE; |
|
} |
|
} else { |
|
efi_st_printf("Missing property 'compatible'\n"); |
|
return EFI_ST_FAILURE; |
|
} |
|
str = get_property(L"serial-number"); |
|
if (str) { |
|
efi_st_printf("serial-number: %s\n", str); |
|
ret = boottime->free_pool(str); |
|
if (ret != EFI_SUCCESS) { |
|
efi_st_error("FreePool failed\n"); |
|
return EFI_ST_FAILURE; |
|
} |
|
} |
|
|
|
return EFI_ST_SUCCESS; |
|
} |
|
|
|
EFI_UNIT_TEST(fdt) = { |
|
.name = "device tree", |
|
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, |
|
.setup = setup, |
|
.execute = execute, |
|
.on_request = true, |
|
};
|
|
|