Skip to content

Commit e8ca8f2

Browse files
committed
[app][uefi] Implement GLB fdt fixiup protocol
1 parent 2fb3bca commit e8ca8f2

File tree

5 files changed

+280
-2
lines changed

5 files changed

+280
-2
lines changed

lib/uefi/boot_service_provider.cpp

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
#include "arch/defines.h"
1919
#include "boot_service.h"
2020

21+
#include "defer.h"
2122
#include "kernel/thread.h"
2223
#include "kernel/vm.h"
2324
#include "lib/bio.h"
2425
#include "lib/dlmalloc.h"
26+
#include "libfdt.h"
2527
#include "protocols/block_io_protocol.h"
28+
#include "protocols/dt_fixup_protocol.h"
29+
#include "protocols/gbl_efi_os_configuration_protocol.h"
2630
#include "protocols/loaded_image_protocol.h"
2731

2832
#include "switch_stack.h"
@@ -142,7 +146,7 @@ EfiStatus handle_protocol(EfiHandle handle, const EfiGuid *protocol,
142146
printf("handle_protocol(%p, LOADED_IMAGE_PROTOCOL_GUID, %p);\n", handle,
143147
intf);
144148
const auto loaded_image = static_cast<EFI_LOADED_IMAGE_PROTOCOL *>(
145-
malloc(sizeof(EFI_LOADED_IMAGE_PROTOCOL)));
149+
mspace_malloc(get_mspace(), sizeof(EFI_LOADED_IMAGE_PROTOCOL)));
146150
*loaded_image = {};
147151
loaded_image->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
148152
loaded_image->ParentHandle = nullptr;
@@ -413,7 +417,7 @@ EfiStatus read_blocks(EfiBlockIoProtocol *self, uint32_t media_id, uint64_t lba,
413417
auto interface = reinterpret_cast<EfiBlockIoInterface *>(self);
414418
auto dev = reinterpret_cast<bdev_t *>(interface->dev);
415419
if (lba >= dev->block_count) {
416-
printf("OOB read %ld %ld\n", lba, dev->block_count);
420+
printf("OOB read %llu %u\n", lba, dev->block_count);
417421
return END_OF_MEDIA;
418422
}
419423

@@ -464,6 +468,75 @@ EfiStatus open_block_device(EfiHandle handle, void **intf) {
464468
return SUCCESS;
465469
}
466470

471+
EFI_STATUS efi_dt_fixup(struct EfiDtFixupProtocol *self, void *fdt,
472+
size_t *buffer_size, uint32_t flags) {
473+
auto offset = fdt_subnode_offset(fdt, 0, "chosen");
474+
if (offset < 0) {
475+
printf("Failed to find chosen node %d\n", offset);
476+
return SUCCESS;
477+
}
478+
int length = 0;
479+
auto prop = fdt_get_property(fdt, offset, "bootargs", &length);
480+
481+
if (prop == nullptr) {
482+
printf("Failed to find chosen/bootargs prop\n");
483+
return SUCCESS;
484+
}
485+
char *new_prop_data = reinterpret_cast<char *>(malloc(length));
486+
DEFER {
487+
free(new_prop_data);
488+
new_prop_data = nullptr;
489+
};
490+
auto prop_length = strnlen(prop->data, length);
491+
static constexpr auto &&to_add =
492+
"console=ttyAMA0 earlycon=pl011,mmio32,0x9000000 ";
493+
memset(new_prop_data, 0, length);
494+
memcpy(new_prop_data, to_add, sizeof(to_add) - 1);
495+
memcpy(new_prop_data + sizeof(to_add) - 1, prop->data, prop_length);
496+
auto ret = fdt_setprop(fdt, offset, "bootargs", new_prop_data, length);
497+
498+
printf("chosen/bootargs: %d %d \"%s\"\n", ret, length, new_prop_data);
499+
500+
return SUCCESS;
501+
}
502+
503+
// Generates fixups for the kernel command line built by GBL.
504+
EfiStatus fixup_kernel_commandline(struct GblEfiOsConfigurationProtocol *self,
505+
const char *command_line, char *fixup,
506+
size_t *fixup_buffer_size) {
507+
printf("%s(0x%lx, \"%s\")\n", __FUNCTION__, self, command_line);
508+
*fixup_buffer_size = 0;
509+
return SUCCESS;
510+
}
511+
512+
// Generates fixups for the bootconfig built by GBL.
513+
EfiStatus fixup_bootconfig(struct GblEfiOsConfigurationProtocol *self,
514+
const char *bootconfig, size_t size, char *fixup,
515+
size_t *fixup_buffer_size) {
516+
printf("%s(0x%lx, %s, %lu, %lu)\n", __FUNCTION__, self, bootconfig, size,
517+
*fixup_buffer_size);
518+
constexpr auto &&to_add = "\nandroidboot.fstab_suffix=cf.f2fs."
519+
"hctr2\nandroidboot.boot_devices=4010000000.pcie";
520+
const auto final_len = sizeof(to_add);
521+
if (final_len > *fixup_buffer_size) {
522+
*fixup_buffer_size = final_len;
523+
return OUT_OF_RESOURCES;
524+
}
525+
*fixup_buffer_size = final_len;
526+
memcpy(fixup, to_add, final_len);
527+
528+
return SUCCESS;
529+
}
530+
531+
// Selects which device trees and overlays to use from those loaded by GBL.
532+
EfiStatus select_device_trees(struct GblEfiOsConfigurationProtocol *self,
533+
GblEfiVerifiedDeviceTree *device_trees,
534+
size_t num_device_trees) {
535+
printf("%s(0x%lx, %lx, %lu)\n", __FUNCTION__, self, device_trees,
536+
num_device_trees);
537+
return UNSUPPORTED;
538+
}
539+
467540
EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
468541
EfiHandle agent_handle, EfiHandle controller_handle,
469542
EfiOpenProtocolAttributes attr) {
@@ -494,6 +567,39 @@ EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
494567
"controller_handle=0x%lx, attr=0x%x)\n",
495568
__FUNCTION__, handle, agent_handle, controller_handle, attr);
496569
return UNSUPPORTED;
570+
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
571+
printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=0x%lx, agent_handle=0x%lx, "
572+
"controller_handle=0x%lx, attr=0x%x)\n",
573+
__FUNCTION__, handle, agent_handle, controller_handle, attr);
574+
if (intf != nullptr) {
575+
EfiDtFixupProtocol *fixup = nullptr;
576+
allocate_pool(BOOT_SERVICES_DATA, sizeof(EfiDtFixupProtocol),
577+
reinterpret_cast<void **>(&fixup));
578+
if (fixup == nullptr) {
579+
return OUT_OF_RESOURCES;
580+
}
581+
fixup->revision = EFI_DT_FIXUP_PROTOCOL_REVISION;
582+
fixup->fixup = efi_dt_fixup;
583+
*intf = reinterpret_cast<EfiHandle *>(fixup);
584+
}
585+
return SUCCESS;
586+
} else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
587+
printf("%s(EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, handle=0x%lx, "
588+
"agent_handle=0x%lx, "
589+
"controller_handle=0x%lx, attr=0x%x)\n",
590+
__FUNCTION__, handle, agent_handle, controller_handle, attr);
591+
GblEfiOsConfigurationProtocol *config = nullptr;
592+
allocate_pool(BOOT_SERVICES_DATA, sizeof(*config),
593+
reinterpret_cast<void **>(&config));
594+
if (config == nullptr) {
595+
return OUT_OF_RESOURCES;
596+
}
597+
config->revision = GBL_EFI_OS_CONFIGURATION_PROTOCOL_REVISION;
598+
config->fixup_bootconfig = fixup_bootconfig;
599+
config->fixup_kernel_commandline = fixup_kernel_commandline;
600+
config->select_device_trees = select_device_trees;
601+
*intf = reinterpret_cast<EfiHandle *>(config);
602+
return SUCCESS;
497603
}
498604
printf("%s is unsupported 0x%x 0x%x 0x%x 0x%llx\n", __FUNCTION__,
499605
protocol->data1, protocol->data2, protocol->data3,
@@ -519,6 +625,11 @@ EfiStatus close_protocol(EfiHandle handle, const EfiGuid *protocol,
519625
"controller_handle=0x%lx)\n",
520626
__FUNCTION__, handle, agent_handle, controller_handle);
521627
return SUCCESS;
628+
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
629+
printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=0x%lx, agent_handle=0x%lx, "
630+
"controller_handle=0x%lx)\n",
631+
__FUNCTION__, handle, agent_handle, controller_handle);
632+
return SUCCESS;
522633
}
523634
printf("%s is called\n", __FUNCTION__);
524635
return UNSUPPORTED;
@@ -557,13 +668,40 @@ EfiStatus locate_handle_buffer(EfiLocateHandleSearchType search_type,
557668
printf("%s(0x%x, EFI_TEXT_INPUT_PROTOCOL_GUID, search_key=0x%lx)\n",
558669
__FUNCTION__, search_type, search_key);
559670
return NOT_FOUND;
671+
} else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
672+
printf(
673+
"%s(0x%x, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, search_key=0x%lx)\n",
674+
__FUNCTION__, search_type, search_key);
675+
if (num_handles != nullptr) {
676+
*num_handles = 1;
677+
}
678+
if (buf != nullptr) {
679+
*buf = reinterpret_cast<EfiHandle *>(
680+
mspace_malloc(get_mspace(), sizeof(buf)));
681+
}
682+
return SUCCESS;
683+
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
684+
printf("%s(0x%x, EFI_DT_FIXUP_PROTOCOL_GUID, search_key=0x%lx)\n",
685+
__FUNCTION__, search_type, search_key);
686+
if (num_handles != nullptr) {
687+
*num_handles = 1;
688+
}
689+
if (buf != nullptr) {
690+
*buf = reinterpret_cast<EfiHandle *>(
691+
mspace_malloc(get_mspace(), sizeof(buf)));
692+
}
693+
return SUCCESS;
560694
}
561695
printf("%s(0x%x, (0x%x 0x%x 0x%x 0x%llx), search_key=0x%lx)\n", __FUNCTION__,
562696
search_type, protocol->data1, protocol->data2, protocol->data3,
563697
*(uint64_t *)&protocol->data4, search_key);
564698
return UNSUPPORTED;
565699
}
566700

701+
EfiStatus wait_for_event(size_t num_events, EfiEvent *event, size_t *index) {
702+
return UNSUPPORTED;
703+
}
704+
567705
} // namespace
568706

569707
void setup_boot_service_table(EfiBootService *service) {
@@ -589,4 +727,5 @@ void setup_boot_service_table(EfiBootService *service) {
589727
service->open_protocol = open_protocol;
590728
service->locate_handle_buffer = locate_handle_buffer;
591729
service->close_protocol = close_protocol;
730+
service->wait_for_event = wait_for_event;
592731
}

lib/uefi/boot_service_provider.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ static constexpr auto EFI_TEXT_INPUT_PROTOCOL_GUID =
7676
0x11d2,
7777
{0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
7878

79+
static constexpr auto EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID =
80+
EfiGuid{0xdda0d135,
81+
0xaa5b,
82+
0x42ff,
83+
{0x85, 0xac, 0xe3, 0xad, 0x6e, 0xfb, 0x46, 0x19}};
84+
85+
static constexpr auto EFI_DT_FIXUP_PROTOCOL_GUID =
86+
EfiGuid{0xe617d64c,
87+
0xfe08,
88+
0x46da,
89+
{0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00}};
90+
7991
using EFI_IMAGE_UNLOAD = EfiStatus (*)(EfiHandle);
8092

8193
//******************************************************
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
// This is a protocol proposed by U-boot and being used by Kernel UEFI stub.
19+
// https://github.com/U-Boot-EFI/EFI_DT_FIXUP_PROTOCOL
20+
// https://github.com/u-boot/u-boot/blob/master/include/efi_dt_fixup.h
21+
22+
#ifndef __EFI_DT_FIXUP_PROTOCOL_H__
23+
#define __EFI_DT_FIXUP_PROTOCOL_H__
24+
25+
#include "types.h"
26+
27+
constexpr uint64_t EFI_DT_FIXUP_PROTOCOL_REVISION = 0x00010000;
28+
29+
// Add nodes and update properties
30+
constexpr uint32_t EFI_DT_APPLY_FIXUPS = 0x00000001;
31+
// Reserve memory according to the /reserved-memory node and the memory
32+
// reservation block
33+
constexpr uint32_t EFI_DT_RESERVE_MEMORY = 0x00000002;
34+
// Install the device-tree as configuration table
35+
constexpr uint32_t EFI_DT_INSTALL_TABLE = 0x00000004;
36+
constexpr uint32_t EFI_DT_ALL =
37+
EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY | EFI_DT_INSTALL_TABLE;
38+
39+
typedef struct EfiDtFixupProtocol {
40+
uint64_t revision;
41+
EfiStatus (*fixup)(struct EfiDtFixupProtocol *self, void *fdt,
42+
size_t *buffer_size, uint32_t flags);
43+
} EfiDtFixupProtocol;
44+
45+
#endif // __EFI_DT_FIXUP_PROTOCOL_H__
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (C) 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
// This is a custom protocol introduced by GBL.
19+
// See gbl/docs/gbl_efi_os_configuration_protocol.md for details.
20+
21+
#ifndef __GBL_OS_CONFIGURATION_PROTOCOL_H__
22+
#define __GBL_OS_CONFIGURATION_PROTOCOL_H__
23+
24+
#include "types.h"
25+
26+
static constexpr size_t GBL_EFI_OS_CONFIGURATION_PROTOCOL_REVISION = 0x00000000;
27+
28+
typedef enum GBL_EFI_DEVICE_TREE_SOURCE {
29+
BOOT,
30+
VENDOR_BOOT,
31+
DTBO,
32+
DTB
33+
} GblEfiDeviceTreeSource;
34+
35+
typedef struct {
36+
// GblDeviceTreeSource
37+
uint32_t source;
38+
// Values are zeroed and must not be used in case of BOOT / VENDOR_BOOT source
39+
uint32_t id;
40+
uint32_t rev;
41+
uint32_t custom[4];
42+
// Make sure GblDeviceTreeMetadata size is 8-bytes aligned. Also reserved for
43+
// the future cases
44+
uint32_t reserved;
45+
} GblEfiDeviceTreeMetadata;
46+
47+
typedef struct {
48+
GblEfiDeviceTreeMetadata metadata;
49+
// Base device tree / overlay buffer (guaranteed to be 8-bytes aligned),
50+
// cannot be NULL. Device tree size can be identified by the header totalsize
51+
// field
52+
const void *device_tree;
53+
// Indicates whether this device tree (or overlay) must be included in the
54+
// final device tree. Set to true by a FW if this component must be used
55+
bool selected;
56+
} GblEfiVerifiedDeviceTree;
57+
58+
// Warning: API is UNSTABLE
59+
// Documentation:
60+
// https://cs.android.com/android/platform/superproject/main/+/main:bootable/libbootloader/gbl/docs/gbl_os_configuration_protocol.md
61+
typedef struct GblEfiOsConfigurationProtocol {
62+
uint64_t revision;
63+
64+
// Generates fixups for the kernel command line built by GBL.
65+
EfiStatus (*fixup_kernel_commandline)(
66+
struct GblEfiOsConfigurationProtocol *self, const char *command_line,
67+
char *fixup, size_t *fixup_buffer_size);
68+
69+
// Generates fixups for the bootconfig built by GBL.
70+
EfiStatus (*fixup_bootconfig)(struct GblEfiOsConfigurationProtocol *self,
71+
const char *bootconfig, size_t size,
72+
char *fixup, size_t *fixup_buffer_size);
73+
74+
// Selects which device trees and overlays to use from those loaded by GBL.
75+
EfiStatus (*select_device_trees)(struct GblEfiOsConfigurationProtocol *self,
76+
GblEfiVerifiedDeviceTree *device_trees,
77+
size_t num_device_trees);
78+
} GblEfiOsConfigurationProtocol;
79+
80+
#endif //__GBL_OS_CONFIGURATION_PROTOCOL_H__

lib/uefi/uefi.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ int load_sections_and_execute(bdev_t *dev,
299299
constexpr size_t kStackSize = 8 * 1024ul * 1024;
300300
auto stack = reinterpret_cast<char *>(alloc_page(kStackSize, 23));
301301
memset(stack, 0, kStackSize);
302+
printf("Calling kernel with stack [0x%lx, 0x%lx]\n", stack,
303+
stack + kStackSize - 1);
302304
return call_with_stack(stack + kStackSize, entry, image_base, &table);
303305
}
304306

0 commit comments

Comments
 (0)