Merge pull request #443

Implement 2 missing UEFI protocols
This commit is contained in:
Travis Geiselbrecht
2025-05-06 23:36:48 -07:00
committed by GitHub
8 changed files with 189 additions and 81 deletions

View File

@@ -21,13 +21,14 @@
#include "arch/defines.h"
#include "boot_service.h"
#include "defer.h"
#include "lib/bio.h"
#include "libfdt.h"
#include "protocols/block_io_protocol.h"
#include "protocols/dt_fixup_protocol.h"
#include "protocols/gbl_efi_os_configuration_protocol.h"
#include "protocols/loaded_image_protocol.h"
#include "uefi_platform.h"
#include <lk/compiler.h>
#include "switch_stack.h"
#include "types.h"
@@ -164,11 +165,6 @@ EfiStatus install_configuration_table(const EfiGuid *guid, void *table) {
return UNSUPPORTED;
}
EfiStatus exit_boot_services(EfiHandle image_handle, size_t map_key) {
printf("%s is called\n", __FUNCTION__);
return SUCCESS;
}
void copy_mem(void *dest, const void *src, size_t len) {
memcpy(dest, src, len);
}
@@ -179,74 +175,6 @@ EfiTpl raise_tpl(EfiTpl new_tpl) {
return APPLICATION;
}
EFI_STATUS efi_dt_fixup(struct EfiDtFixupProtocol *self, void *fdt,
size_t *buffer_size, uint32_t flags) {
auto offset = fdt_subnode_offset(fdt, 0, "chosen");
if (offset < 0) {
printf("Failed to find chosen node %d\n", offset);
return SUCCESS;
}
int length = 0;
auto prop = fdt_get_property(fdt, offset, "bootargs", &length);
if (prop == nullptr) {
printf("Failed to find chosen/bootargs prop\n");
return SUCCESS;
}
char *new_prop_data = reinterpret_cast<char *>(malloc(length));
DEFER {
free(new_prop_data);
new_prop_data = nullptr;
};
auto prop_length = strnlen(prop->data, length);
static constexpr auto &&to_add =
"console=ttyAMA0 earlycon=pl011,mmio32,0x9000000 ";
memset(new_prop_data, 0, length);
memcpy(new_prop_data, to_add, sizeof(to_add) - 1);
memcpy(new_prop_data + sizeof(to_add) - 1, prop->data, prop_length);
auto ret = fdt_setprop(fdt, offset, "bootargs", new_prop_data, length);
printf("chosen/bootargs: %d %d \"%s\"\n", ret, length, new_prop_data);
return SUCCESS;
}
// Generates fixups for the kernel command line built by GBL.
EfiStatus fixup_kernel_commandline(struct GblEfiOsConfigurationProtocol *self,
const char *command_line, char *fixup,
size_t *fixup_buffer_size) {
printf("%s(%p, \"%s\")\n", __FUNCTION__, self, command_line);
*fixup_buffer_size = 0;
return SUCCESS;
}
// Generates fixups for the bootconfig built by GBL.
EfiStatus fixup_bootconfig(struct GblEfiOsConfigurationProtocol *self,
const char *bootconfig, size_t size, char *fixup,
size_t *fixup_buffer_size) {
printf("%s(%p, %s, %lu, %lu)\n", __FUNCTION__, self, bootconfig, size,
*fixup_buffer_size);
constexpr auto &&to_add = "\nandroidboot.fstab_suffix=cf.f2fs."
"hctr2\nandroidboot.boot_devices=4010000000.pcie";
const auto final_len = sizeof(to_add);
if (final_len > *fixup_buffer_size) {
*fixup_buffer_size = final_len;
return OUT_OF_RESOURCES;
}
*fixup_buffer_size = final_len;
memcpy(fixup, to_add, final_len);
return SUCCESS;
}
// Selects which device trees and overlays to use from those loaded by GBL.
EfiStatus select_device_trees(struct GblEfiOsConfigurationProtocol *self,
GblEfiVerifiedDeviceTree *device_trees,
size_t num_device_trees) {
printf("%s(%p, %p %lu)\n", __FUNCTION__, self, device_trees,
num_device_trees);
return UNSUPPORTED;
}
EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
EfiHandle agent_handle, EfiHandle controller_handle,
@@ -291,7 +219,7 @@ EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
}
fixup->revision = EFI_DT_FIXUP_PROTOCOL_REVISION;
fixup->fixup = efi_dt_fixup;
*intf = reinterpret_cast<EfiHandle *>(fixup);
*intf = reinterpret_cast<void *>(fixup);
}
return SUCCESS;
} else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
@@ -309,7 +237,7 @@ EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
config->fixup_bootconfig = fixup_bootconfig;
config->fixup_kernel_commandline = fixup_kernel_commandline;
config->select_device_trees = select_device_trees;
*intf = reinterpret_cast<EfiHandle *>(config);
*intf = reinterpret_cast<void *>(config);
return SUCCESS;
}
printf("%s is unsupported 0x%x 0x%x 0x%x 0x%llx\n", __FUNCTION__,

View File

@@ -121,4 +121,9 @@ struct EFI_LOADED_IMAGE_PROTOCOL {
static constexpr size_t EFI_LOADED_IMAGE_PROTOCOL_REVISION = 0x1000;
// This function would be called from GBL before jumping into android kernel
// LK provides a default no-op implementation that is weakly linked,
// different platforms can override with their own implementation.
EfiStatus exit_boot_services(EfiHandle image_handle, size_t map_key);
#endif

15
lib/uefi/include/uefi.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef __LIB_UEFI_HEADER_
#define __LIB_UEFI_HEADER_
#ifdef __cplusplus
extern "C" {
#endif
int load_pe_file(const char *blkdev);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,10 +1,14 @@
#include "relocation.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "pe.h"
namespace {
constexpr size_t BIT26 = 1 << 26;
constexpr size_t BIT11 = 1 << 11;
constexpr size_t BIT10 = 1 << 10;
@@ -97,6 +101,8 @@ void ThumbMovwMovtImmediatePatch(uint16_t *Instructions, uint32_t Address) {
ThumbMovtImmediatePatch(Top, static_cast<uint16_t>(Address >> 16));
}
} // namespace
int relocate_image(char *image) {
const auto dos_header = reinterpret_cast<IMAGE_DOS_HEADER *>(image);
const auto pe_header = dos_header->GetPEHeader();

View File

@@ -13,6 +13,7 @@ MODULE_SRCS += \
$(LOCAL_DIR)/boot_service_provider.cpp \
$(LOCAL_DIR)/memory_protocols.cpp \
$(LOCAL_DIR)/blockio_protocols.cpp \
$(LOCAL_DIR)/uefi_platform.cpp \
$(LOCAL_DIR)/runtime_service_provider.cpp \
$(LOCAL_DIR)/switch_stack.S \
$(LOCAL_DIR)/configuration_table.cpp \

View File

@@ -16,14 +16,16 @@
*/
#include "runtime_service_provider.h"
#include "types.h"
#include <platform.h>
#include <stdio.h>
#include <string.h>
#include "types.h"
namespace {
constexpr auto &&kSecureBoot = L"SecureBoot";
constexpr auto &&kSecureBoot = "SecureBoot";
EFI_STATUS GetVariable(char16_t *VariableName, EfiGuid *VendorGuid,
uint32_t *Attributes, size_t *DataSize, void *Data) {
@@ -37,7 +39,7 @@ EFI_STATUS GetVariable(char16_t *VariableName, EfiGuid *VendorGuid,
i += j;
}
buffer[i] = 0;
if (strcmp(buffer, "SecureBoot") == 0 || strcmp(buffer, "SetupMode") == 0) {
if (strncmp(buffer, kSecureBoot, sizeof(kSecureBoot)) == 0 || strcmp(buffer, "SetupMode") == 0) {
if (DataSize) {
*DataSize = 1;
}
@@ -64,10 +66,17 @@ EFI_STATUS SetVariable(char16_t *VariableName, EfiGuid *VendorGuid,
return UNSUPPORTED;
}
} // namespace
void ResetSystem(EFI_RESET_TYPE ResetType, EFI_STATUS ResetStatus,
size_t DataSize, void *ResetData) {
platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
}
} // namespace
void setup_runtime_service_table(EfiRuntimeService *service) {
service->GetVariable = GetVariable;
service->SetVariable = SetVariable;
service->SetVirtualAddressMap = SetVirtualAddressMap;
service->ResetSystem = ResetSystem;
}

100
lib/uefi/uefi_platform.cpp Normal file
View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <libfdt.h>
#include <stdio.h>
#include <stdlib.h>
#include <types.h>
#include "defer.h"
#include "uefi_platform.h"
#include "protocols/gbl_efi_os_configuration_protocol.h"
__WEAK EFI_STATUS efi_dt_fixup(struct EfiDtFixupProtocol *self, void *fdt,
size_t *buffer_size, uint32_t flags) {
auto offset = fdt_subnode_offset(fdt, 0, "chosen");
if (offset < 0) {
printf("Failed to find chosen node %d\n", offset);
return SUCCESS;
}
int length = 0;
auto prop = fdt_get_property(fdt, offset, "bootargs", &length);
if (prop == nullptr) {
printf("Failed to find chosen/bootargs prop\n");
return SUCCESS;
}
char *new_prop_data = reinterpret_cast<char *>(malloc(length));
DEFER {
free(new_prop_data);
new_prop_data = nullptr;
};
auto prop_length = strnlen(prop->data, length);
static constexpr auto &&to_add =
"console=ttyAMA0 earlycon=pl011,mmio32,0x9000000 ";
memset(new_prop_data, 0, length);
memcpy(new_prop_data, to_add, sizeof(to_add) - 1);
memcpy(new_prop_data + sizeof(to_add) - 1, prop->data, prop_length);
auto ret = fdt_setprop(fdt, offset, "bootargs", new_prop_data, length);
printf("chosen/bootargs: %d %d \"%s\"\n", ret, length, new_prop_data);
return SUCCESS;
}
// Generates fixups for the kernel command line built by GBL.
__WEAK EfiStatus fixup_kernel_commandline(
struct GblEfiOsConfigurationProtocol *self, const char *command_line,
char *fixup, size_t *fixup_buffer_size) {
printf("%s(%p, \"%s\")\n", __FUNCTION__, self, command_line);
*fixup_buffer_size = 0;
return SUCCESS;
}
// Generates fixups for the bootconfig built by GBL.
__WEAK EfiStatus fixup_bootconfig(struct GblEfiOsConfigurationProtocol *self,
const char *bootconfig, size_t size,
char *fixup, size_t *fixup_buffer_size) {
printf("%s(%p, %s, %lu, %lu)\n", __FUNCTION__, self, bootconfig, size,
*fixup_buffer_size);
constexpr auto &&to_add =
"\nandroidboot.fstab_suffix=cf.f2fs."
"hctr2\nandroidboot.boot_devices=4010000000.pcie";
const auto final_len = sizeof(to_add);
if (final_len > *fixup_buffer_size) {
*fixup_buffer_size = final_len;
return OUT_OF_RESOURCES;
}
*fixup_buffer_size = final_len;
memcpy(fixup, to_add, final_len);
return SUCCESS;
}
// Selects which device trees and overlays to use from those loaded by GBL.
__WEAK EfiStatus select_device_trees(struct GblEfiOsConfigurationProtocol *self,
GblEfiVerifiedDeviceTree *device_trees,
size_t num_device_trees) {
printf("%s(%p, %p %lu)\n", __FUNCTION__, self, device_trees,
num_device_trees);
return UNSUPPORTED;
}
__WEAK EfiStatus exit_boot_services(EfiHandle image_handle, size_t map_key) {
printf("%s is called\n", __FUNCTION__);
return SUCCESS;
}

44
lib/uefi/uefi_platform.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef __GBL_OS_CONFIGURATION_
#define __GBL_OS_CONFIGURATION_
#include <types.h>
#include "protocols/gbl_efi_os_configuration_protocol.h"
// Functions which should be implemented by individual platforms.
// The UEFI library provides a default no-op implementation that
// is weakly linked.
EFI_STATUS efi_dt_fixup(struct EfiDtFixupProtocol *self, void *fdt,
size_t *buffer_size, uint32_t flags);
EfiStatus fixup_kernel_commandline(struct GblEfiOsConfigurationProtocol *self,
const char *command_line, char *fixup,
size_t *fixup_buffer_size);
EfiStatus fixup_bootconfig(struct GblEfiOsConfigurationProtocol *self,
const char *bootconfig, size_t size, char *fixup,
size_t *fixup_buffer_size);
EfiStatus select_device_trees(struct GblEfiOsConfigurationProtocol *self,
GblEfiVerifiedDeviceTree *device_trees,
size_t num_device_trees);
EfiStatus exit_boot_services(EfiHandle image_handle, size_t map_key);
#endif