Compare commits
7 Commits
wip/pico-u
...
pr/uefi-wa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31448f52db | ||
|
|
6d9a0b5c35 | ||
|
|
e7b71623c4 | ||
|
|
f9a5a16db5 | ||
|
|
5c066ae52c | ||
|
|
0c1cb6bf03 | ||
|
|
1103fd5575 |
17
README.md
17
README.md
@@ -43,3 +43,20 @@ Note: for ubuntu x86-64
|
||||
sudo apt-get install gcc-aarch64-linux-gnu
|
||||
or fetch a prebuilt toolchain from
|
||||
https://newos.org/toolchains/aarch64-elf-14.1.0-Linux-x86_64.tar.xz
|
||||
|
||||
|
||||
### Building with LLVM-based toolchains
|
||||
|
||||
To build LK with a LLVM-based toolchain you will have to manually specify the compiler and linker in the environemnt.
|
||||
Unlike GCC clang is a cross-compiler by default, so the target needs to be specified as part of the CC/CXX/CPP variables.
|
||||
For example, assuming LLVM is in `/opt/llvm/bin/`, the following command will work to build for 64-bit RISC-V:
|
||||
|
||||
```
|
||||
gmake qemu-virt-riscv64-test 'CC=/opt/llvm/bin/clang --target=riscv64-unknown-elf' 'CPP=/opt/llvm/bin/clang-cpp --target=riscv64-unknown-elf' 'CXX=/opt/llvm/bin/clang++ --target=riscv64-unknown-elf' 'LD=/opt/llvm/bin/ld.lld' TOOLCHAIN_PREFIX=/opt/llvm/bin/llvm- CPPFILT=/opt/llvm/bin/llvm-cxxfilt
|
||||
```
|
||||
TOOLCHAIN_PREFIX can be set to use the LLVM binutils, but due to the different naming of `llvm-cxxfilt` vs `c++filt` it needs to be set explicitly.
|
||||
|
||||
To build for AArch64 the command looks similar, just with a different `--target=` flag.
|
||||
```
|
||||
gmake qemu-virt-arm64-test 'CC=/opt/llvm/bin/clang --target=aarch64-unknown-elf' 'CPP=/opt/llvm/bin/clang-cpp --target=aarch64-unknown-elf' 'CXX=/opt/llvm/bin/clang++ --target=aarch64-unknown-elf' 'LD=/opt/llvm/bin/ld.lld' TOOLCHAIN_PREFIX=/opt/llvm/bin/llvm- CPPFILT=/opt/llvm/bin/llvm-cxxfilt
|
||||
```
|
||||
|
||||
@@ -96,16 +96,31 @@ int printf_tests(int argc, const console_cmd_args *argv) {
|
||||
/* make sure snprintf terminates at the right spot */
|
||||
char buf[32];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(buf, 0x99, sizeof(buf));
|
||||
err = sprintf(buf, "0123456789abcdef012345678");
|
||||
printf("sprintf returns %d\n", err);
|
||||
hexdump8(buf, sizeof(buf));
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(buf, 0x99, sizeof(buf));
|
||||
err = snprintf(buf, 15, "0123456789abcdef012345678");
|
||||
printf("snprintf returns %d\n", err);
|
||||
hexdump8(buf, sizeof(buf));
|
||||
|
||||
memset(buf, 0x99, sizeof(buf));
|
||||
err = snprintf(buf, 1, "0123456789abcdef012345678");
|
||||
printf("snprintf returns %d\n", err);
|
||||
hexdump8(buf, sizeof(buf));
|
||||
|
||||
/* zero length is special case, should not write anything */
|
||||
memset(buf, 0x99, sizeof(buf));
|
||||
err = snprintf(buf, 0, "0123456789abcdef012345678");
|
||||
printf("snprintf returns %d\n", err);
|
||||
hexdump8(buf, sizeof(buf));
|
||||
|
||||
/* shold be able to pass null to the output buffer if zero length */
|
||||
err = snprintf(NULL, 0, "0123456789abcdef012345678");
|
||||
printf("snprintf returns %d\n", err);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -534,6 +534,17 @@ void bio_unregister_device(bdev_t *dev) {
|
||||
bdev_dec_ref(dev); // remove the ref the list used to have
|
||||
}
|
||||
|
||||
void bio_iter_devices(bool (*callback)(void *, bdev_t *), void *cookie) {
|
||||
bdev_t *entry = NULL;
|
||||
mutex_acquire(&bdevs.lock);
|
||||
list_for_every_entry(&bdevs.list, entry, bdev_t, node) {
|
||||
if (!callback(cookie, entry)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_release(&bdevs.lock);
|
||||
}
|
||||
|
||||
void bio_dump_devices(void) {
|
||||
printf("block devices:\n");
|
||||
bdev_t *entry;
|
||||
|
||||
@@ -130,4 +130,23 @@ enum bio_ioctl_num {
|
||||
BIO_IOCTL_IS_MAPPED, /* if supported, returns whether or not the device is memory mapped. */
|
||||
};
|
||||
|
||||
__END_CDECLS
|
||||
// The callback will be called once for every block device, with the cookie and pointer
|
||||
// to the bdev structure. Note callback would be called with internal mutex held, which
|
||||
// prevents other process/threads from using APIs such as bio_open, so kindly ask callers
|
||||
// not to do any long blocking operations in callback functions. If the callback function
|
||||
// returns |false|, iteration stop immediately, and bio_iter_devices returns.
|
||||
void bio_iter_devices(bool (*callback)(void *, bdev_t *), void *cookie);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#ifdef __cplusplus
|
||||
template <typename Callable>
|
||||
bool iter_device_callback(void *cookie, bdev_t *dev) {
|
||||
auto func = reinterpret_cast<Callable *>(cookie);
|
||||
return (*func)(dev);
|
||||
}
|
||||
|
||||
template <typename Callable> void bio_iter_devices(Callable &&func) {
|
||||
bio_iter_devices(&iter_device_callback<Callable>, &func);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,8 @@ static int _vsnprintf_output(const char *str, size_t len, void *state) {
|
||||
count++;
|
||||
}
|
||||
|
||||
// Return the count of the number of bytes that would be written even if the buffer
|
||||
// wasn't large enough.
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -78,10 +80,13 @@ int vsnprintf(char *str, size_t len, const char *fmt, va_list ap) {
|
||||
args.pos = 0;
|
||||
|
||||
wlen = _printf_engine(&_vsnprintf_output, (void *)&args, fmt, ap);
|
||||
if (args.pos >= len)
|
||||
if (len == 0) {
|
||||
// do nothing, we can't null terminate the output
|
||||
} else if (args.pos >= len) {
|
||||
str[len-1] = '\0';
|
||||
else
|
||||
} else {
|
||||
str[wlen] = '\0';
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
|
||||
@@ -458,6 +458,44 @@ bool snprintf_truncation_test() {
|
||||
END_TEST;
|
||||
}
|
||||
|
||||
// Test snprintf() with zero length.
|
||||
bool snprintf_truncation_test_zero_length() {
|
||||
BEGIN_TEST;
|
||||
|
||||
char buf[32];
|
||||
|
||||
memset(buf, 'x', sizeof(buf));
|
||||
static const char str[26] = "0123456789abcdef012345678";
|
||||
|
||||
// Write with len = 0 a little ways into the buffer (to make sure it doesn't
|
||||
// write to len -1).
|
||||
int result = snprintf(buf + 4, 0, "%s", str);
|
||||
|
||||
// Check that snprintf() returns the length of the string that it would
|
||||
// have written if the buffer was big enough.
|
||||
EXPECT_EQ(result, (int)strlen(str));
|
||||
|
||||
// Check that snprintf() did not write anything.
|
||||
for (auto c : buf)
|
||||
EXPECT_EQ(c, 'x');
|
||||
|
||||
END_TEST;
|
||||
}
|
||||
|
||||
// Test snprintf() with null pointer and zero length.
|
||||
bool snprintf_truncation_test_null_buffer() {
|
||||
BEGIN_TEST;
|
||||
|
||||
static const char str[26] = "0123456789abcdef012345678";
|
||||
int result = snprintf(nullptr, 0, "%s", str);
|
||||
|
||||
// Check that snprintf() returns the length of the string that it would
|
||||
// have written if the buffer was big enough.
|
||||
EXPECT_EQ(result, (int)strlen(str));
|
||||
|
||||
END_TEST;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BEGIN_TEST_CASE(printf_tests)
|
||||
@@ -467,4 +505,6 @@ RUN_TEST(alt_and_sign)
|
||||
RUN_TEST(formatting)
|
||||
//RUN_TEST(printf_field_width_and_precision_test)
|
||||
RUN_TEST(snprintf_truncation_test)
|
||||
RUN_TEST(snprintf_truncation_test_zero_length)
|
||||
RUN_TEST(snprintf_truncation_test_null_buffer)
|
||||
END_TEST_CASE(printf_tests)
|
||||
|
||||
@@ -15,13 +15,26 @@
|
||||
*
|
||||
*/
|
||||
#include "boot_service_provider.h"
|
||||
#include "arch/defines.h"
|
||||
#include "boot_service.h"
|
||||
|
||||
#include "defer.h"
|
||||
#include "kernel/thread.h"
|
||||
#include "kernel/vm.h"
|
||||
#include "lib/bio.h"
|
||||
#include "lib/dlmalloc.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 "switch_stack.h"
|
||||
#include "types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
static vmm_aspace_t *old_aspace = nullptr;
|
||||
|
||||
@@ -62,7 +75,8 @@ void *identity_map(void *addr, size_t size) {
|
||||
printf("Failed to identity map physical address 0x%lx\n", pa);
|
||||
return nullptr;
|
||||
}
|
||||
printf("Identity mapped physical address 0x%lx flags 0x%x\n", pa, flags);
|
||||
printf("Identity mapped physical address 0x%lx size %zu flags 0x%x\n", pa,
|
||||
size, flags);
|
||||
|
||||
return reinterpret_cast<void *>(pa);
|
||||
}
|
||||
@@ -108,14 +122,32 @@ bool guid_eq(const EfiGuid *a, const EfiGuid &b) {
|
||||
return memcmp(a, &b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
constexpr size_t kHeapSize = 256ul * 1024 * 1024;
|
||||
|
||||
void *get_heap() {
|
||||
static auto heap = alloc_page(kHeapSize);
|
||||
return heap;
|
||||
}
|
||||
|
||||
mspace create_mspace_with_base_limit(void *base, size_t capacity, int locked) {
|
||||
auto space = create_mspace_with_base(get_heap(), kHeapSize, 1);
|
||||
mspace_set_footprint_limit(space, capacity);
|
||||
return space;
|
||||
}
|
||||
|
||||
mspace get_mspace() {
|
||||
static auto space = create_mspace_with_base_limit(get_heap(), kHeapSize, 1);
|
||||
return space;
|
||||
}
|
||||
|
||||
EfiStatus handle_protocol(EfiHandle handle, const EfiGuid *protocol,
|
||||
void **intf) {
|
||||
if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
|
||||
printf("handle_protocol(%p, LOADED_IMAGE_PROTOCOL_GUID, %p);\n", handle,
|
||||
intf);
|
||||
auto loaded_image = static_cast<EFI_LOADED_IMAGE_PROTOCOL *>(
|
||||
malloc(sizeof(EFI_LOADED_IMAGE_PROTOCOL)));
|
||||
loaded_image = {};
|
||||
const auto loaded_image = static_cast<EFI_LOADED_IMAGE_PROTOCOL *>(
|
||||
mspace_malloc(get_mspace(), sizeof(EFI_LOADED_IMAGE_PROTOCOL)));
|
||||
*loaded_image = {};
|
||||
loaded_image->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
|
||||
loaded_image->ParentHandle = nullptr;
|
||||
loaded_image->SystemTable = nullptr;
|
||||
@@ -136,23 +168,6 @@ EfiStatus handle_protocol(EfiHandle handle, const EfiGuid *protocol,
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
constexpr size_t kHeapSize = 8ul * 1024 * 1024;
|
||||
void *get_heap() {
|
||||
static auto heap = alloc_page(kHeapSize);
|
||||
return heap;
|
||||
}
|
||||
|
||||
mspace create_mspace_with_base_limit(void *base, size_t capacity, int locked) {
|
||||
auto space = create_mspace_with_base(get_heap(), kHeapSize, 1);
|
||||
mspace_set_footprint_limit(space, capacity);
|
||||
return space;
|
||||
}
|
||||
|
||||
mspace get_mspace() {
|
||||
static auto space = create_mspace_with_base_limit(get_heap(), kHeapSize, 1);
|
||||
return space;
|
||||
}
|
||||
|
||||
EfiStatus allocate_pool(EfiMemoryType pool_type, size_t size, void **buf) {
|
||||
if (buf == nullptr) {
|
||||
return INVALID_PARAMETER;
|
||||
@@ -323,7 +338,7 @@ EfiStatus allocate_pages(EfiAllocatorType type, EfiMemoryType memory_type,
|
||||
if (memory == nullptr) {
|
||||
return INVALID_PARAMETER;
|
||||
}
|
||||
if (type == ALLOCATE_MAX_ADDRESS && *memory != 0xffffffffffffffff) {
|
||||
if (type == ALLOCATE_MAX_ADDRESS && *memory < 0xFFFFFFFF) {
|
||||
printf("allocate_pages(%d, %d, %zu, 0x%llx) unsupported\n", type,
|
||||
memory_type, pages, *memory);
|
||||
return UNSUPPORTED;
|
||||
@@ -382,6 +397,311 @@ EfiStatus exit_boot_services(EfiHandle image_handle, size_t map_key) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void copy_mem(void *dest, const void *src, size_t len) {
|
||||
memcpy(dest, src, len);
|
||||
}
|
||||
void set_mem(void *buf, size_t len, uint8_t val) { memset(buf, val, len); }
|
||||
|
||||
EfiTpl raise_tpl(EfiTpl new_tpl) {
|
||||
printf("%s is called %zu\n", __FUNCTION__, new_tpl);
|
||||
return APPLICATION;
|
||||
}
|
||||
|
||||
EfiStatus reset(EfiBlockIoProtocol *self, bool extended_verification) {
|
||||
printf("%s is called\n", __FUNCTION__);
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
EfiStatus read_blocks(EfiBlockIoProtocol *self, uint32_t media_id, uint64_t lba,
|
||||
size_t buffer_size, void *buffer) {
|
||||
auto interface = reinterpret_cast<EfiBlockIoInterface *>(self);
|
||||
auto dev = reinterpret_cast<bdev_t *>(interface->dev);
|
||||
if (lba >= dev->block_count) {
|
||||
printf("OOB read %llu %u\n", lba, dev->block_count);
|
||||
return END_OF_MEDIA;
|
||||
}
|
||||
|
||||
const size_t bytes_read =
|
||||
call_with_stack(interface->io_stack, bio_read_block, dev, buffer, lba,
|
||||
buffer_size / dev->block_size);
|
||||
if (bytes_read != buffer_size) {
|
||||
printf("Failed to read %ld bytes from %s\n", buffer_size, dev->name);
|
||||
return DEVICE_ERROR;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
EfiStatus write_blocks(EfiBlockIoProtocol *self, uint32_t media_id,
|
||||
uint64_t lba, size_t buffer_size, const void *buffer) {
|
||||
printf("%s is called\n", __FUNCTION__);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
EfiStatus flush_blocks(EfiBlockIoProtocol *self) {
|
||||
printf("%s is called\n", __FUNCTION__);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
EfiStatus open_block_device(EfiHandle handle, void **intf) {
|
||||
static constexpr size_t kIoStackSize = 1024ul * 1024 * 64;
|
||||
static void *io_stack = nullptr;
|
||||
if (io_stack == nullptr) {
|
||||
vmm_alloc(vmm_get_kernel_aspace(), "uefi_io_stack", kIoStackSize, &io_stack,
|
||||
PAGE_SIZE_SHIFT, 0, 0);
|
||||
}
|
||||
printf("%s(%p)\n", __FUNCTION__, handle);
|
||||
const auto interface = reinterpret_cast<EfiBlockIoInterface *>(
|
||||
mspace_malloc(get_mspace(), sizeof(EfiBlockIoInterface)));
|
||||
memset(interface, 0, sizeof(EfiBlockIoInterface));
|
||||
auto dev = bio_open(reinterpret_cast<const char *>(handle));
|
||||
interface->dev = dev;
|
||||
interface->protocol.reset = reset;
|
||||
interface->protocol.read_blocks = read_blocks;
|
||||
interface->protocol.write_blocks = write_blocks;
|
||||
interface->protocol.flush_blocks = flush_blocks;
|
||||
interface->protocol.media = &interface->media;
|
||||
interface->media.block_size = dev->block_size;
|
||||
interface->media.io_align = interface->media.block_size;
|
||||
interface->media.last_block = dev->block_count - 1;
|
||||
interface->io_stack = reinterpret_cast<char *>(io_stack) + kIoStackSize;
|
||||
*intf = interface;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
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,
|
||||
EfiOpenProtocolAttributes attr) {
|
||||
if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
|
||||
auto interface = reinterpret_cast<EfiLoadedImageProtocol *>(
|
||||
mspace_malloc(get_mspace(), sizeof(EfiLoadedImageProtocol)));
|
||||
memset(interface, 0, sizeof(*interface));
|
||||
interface->parent_handle = handle;
|
||||
interface->image_base = handle;
|
||||
*intf = interface;
|
||||
printf("%s(LOADED_IMAGE_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_DEVICE_PATH_PROTOCOL_GUID)) {
|
||||
printf(
|
||||
"%s(EFI_DEVICE_PATH_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
return UNSUPPORTED;
|
||||
} else if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_BLOCK_IO_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
return open_block_device(handle, intf);
|
||||
} else if (guid_eq(protocol, EFI_BLOCK_IO2_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_BLOCK_IO2_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
return UNSUPPORTED;
|
||||
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
if (intf != nullptr) {
|
||||
EfiDtFixupProtocol *fixup = nullptr;
|
||||
allocate_pool(BOOT_SERVICES_DATA, sizeof(EfiDtFixupProtocol),
|
||||
reinterpret_cast<void **>(&fixup));
|
||||
if (fixup == nullptr) {
|
||||
return OUT_OF_RESOURCES;
|
||||
}
|
||||
fixup->revision = EFI_DT_FIXUP_PROTOCOL_REVISION;
|
||||
fixup->fixup = efi_dt_fixup;
|
||||
*intf = reinterpret_cast<EfiHandle *>(fixup);
|
||||
}
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, handle=%p, "
|
||||
"agent_handle=%p, "
|
||||
"controller_handle=%p, attr=0x%x)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle, attr);
|
||||
GblEfiOsConfigurationProtocol *config = nullptr;
|
||||
allocate_pool(BOOT_SERVICES_DATA, sizeof(*config),
|
||||
reinterpret_cast<void **>(&config));
|
||||
if (config == nullptr) {
|
||||
return OUT_OF_RESOURCES;
|
||||
}
|
||||
config->revision = GBL_EFI_OS_CONFIGURATION_PROTOCOL_REVISION;
|
||||
config->fixup_bootconfig = fixup_bootconfig;
|
||||
config->fixup_kernel_commandline = fixup_kernel_commandline;
|
||||
config->select_device_trees = select_device_trees;
|
||||
*intf = reinterpret_cast<EfiHandle *>(config);
|
||||
return SUCCESS;
|
||||
}
|
||||
printf("%s is unsupported 0x%x 0x%x 0x%x 0x%llx\n", __FUNCTION__,
|
||||
protocol->data1, protocol->data2, protocol->data3,
|
||||
*(uint64_t *)&protocol->data4);
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
EfiStatus close_protocol(EfiHandle handle, const EfiGuid *protocol,
|
||||
EfiHandle agent_handle, EfiHandle controller_handle) {
|
||||
if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
|
||||
printf("%s(LOADED_IMAGE_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle);
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_DEVICE_PATH_PROTOCOL_GUID)) {
|
||||
printf(
|
||||
"%s(EFI_DEVICE_PATH_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle);
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_BLOCK_IO_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle);
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
|
||||
printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
|
||||
"controller_handle=%p)\n",
|
||||
__FUNCTION__, handle, agent_handle, controller_handle);
|
||||
return SUCCESS;
|
||||
}
|
||||
printf("%s is called\n", __FUNCTION__);
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
EfiStatus list_block_devices(size_t *num_handles, EfiHandle **buf) {
|
||||
size_t device_count = 0;
|
||||
bio_iter_devices([&device_count](bdev_t *dev) {
|
||||
device_count++;
|
||||
return true;
|
||||
});
|
||||
auto devices = reinterpret_cast<char **>(
|
||||
mspace_malloc(get_mspace(), sizeof(char *) * device_count));
|
||||
size_t i = 0;
|
||||
bio_iter_devices([&i, devices, device_count](bdev_t *dev) {
|
||||
devices[i] = dev->name;
|
||||
i++;
|
||||
return i < device_count;
|
||||
});
|
||||
*num_handles = i;
|
||||
*buf = reinterpret_cast<EfiHandle *>(devices);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
EfiStatus locate_handle_buffer(EfiLocateHandleSearchType search_type,
|
||||
const EfiGuid *protocol, void *search_key,
|
||||
size_t *num_handles, EfiHandle **buf) {
|
||||
if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
|
||||
if (search_type == BY_PROTOCOL) {
|
||||
return list_block_devices(num_handles, buf);
|
||||
}
|
||||
printf("%s(0x%x, EFI_BLOCK_IO_PROTOCOL_GUID, search_key=%p)\n",
|
||||
__FUNCTION__, search_type, search_key);
|
||||
return UNSUPPORTED;
|
||||
} else if (guid_eq(protocol, EFI_TEXT_INPUT_PROTOCOL_GUID)) {
|
||||
printf("%s(0x%x, EFI_TEXT_INPUT_PROTOCOL_GUID, search_key=%p)\n",
|
||||
__FUNCTION__, search_type, search_key);
|
||||
return NOT_FOUND;
|
||||
} else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
|
||||
printf(
|
||||
"%s(0x%x, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, search_key=%p)\n",
|
||||
__FUNCTION__, search_type, search_key);
|
||||
if (num_handles != nullptr) {
|
||||
*num_handles = 1;
|
||||
}
|
||||
if (buf != nullptr) {
|
||||
*buf = reinterpret_cast<EfiHandle *>(
|
||||
mspace_malloc(get_mspace(), sizeof(buf)));
|
||||
}
|
||||
return SUCCESS;
|
||||
} else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
|
||||
printf("%s(0x%x, EFI_DT_FIXUP_PROTOCOL_GUID, search_key=%p)\n",
|
||||
__FUNCTION__, search_type, search_key);
|
||||
if (num_handles != nullptr) {
|
||||
*num_handles = 1;
|
||||
}
|
||||
if (buf != nullptr) {
|
||||
*buf = reinterpret_cast<EfiHandle *>(
|
||||
mspace_malloc(get_mspace(), sizeof(buf)));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
printf("%s(0x%x, (0x%x 0x%x 0x%x 0x%llx), search_key=%p)\n", __FUNCTION__,
|
||||
search_type, protocol->data1, protocol->data2, protocol->data3,
|
||||
*(uint64_t *)&protocol->data4, search_key);
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
EfiStatus wait_for_event(size_t num_events, EfiEvent *event, size_t *index) {
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup_boot_service_table(EfiBootService *service) {
|
||||
@@ -402,4 +722,10 @@ void setup_boot_service_table(EfiBootService *service) {
|
||||
service->locate_device_path = locate_device_path;
|
||||
service->install_configuration_table = install_configuration_table;
|
||||
service->exit_boot_services = exit_boot_services;
|
||||
service->copy_mem = copy_mem;
|
||||
service->set_mem = set_mem;
|
||||
service->open_protocol = open_protocol;
|
||||
service->locate_handle_buffer = locate_handle_buffer;
|
||||
service->close_protocol = close_protocol;
|
||||
service->wait_for_event = wait_for_event;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ static constexpr auto LOADED_IMAGE_PROTOCOL_GUID =
|
||||
{0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
|
||||
|
||||
static constexpr auto EFI_DEVICE_PATH_PROTOCOL_GUID =
|
||||
EfiGuid{0x09576e91,
|
||||
EfiGuid{0x9576e91,
|
||||
0x6d3f,
|
||||
0x11d2,
|
||||
{0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
|
||||
@@ -58,6 +58,36 @@ static constexpr auto EFI_LOAD_FILE2_PROTOCOL_GUID =
|
||||
0xfcb3,
|
||||
0x403e,
|
||||
{0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d}};
|
||||
static constexpr auto EFI_BLOCK_IO_PROTOCOL_GUID =
|
||||
EfiGuid{0x964e5b21,
|
||||
0x6459,
|
||||
0x11d2,
|
||||
{0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
|
||||
|
||||
static constexpr auto EFI_BLOCK_IO2_PROTOCOL_GUID =
|
||||
EfiGuid{0xa77b2472,
|
||||
0xe282,
|
||||
0x4e9f,
|
||||
{0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1}};
|
||||
|
||||
static constexpr auto EFI_TEXT_INPUT_PROTOCOL_GUID =
|
||||
EfiGuid{0x387477c1,
|
||||
0x69c7,
|
||||
0x11d2,
|
||||
{0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
|
||||
|
||||
static constexpr auto EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID =
|
||||
EfiGuid{0xdda0d135,
|
||||
0xaa5b,
|
||||
0x42ff,
|
||||
{0x85, 0xac, 0xe3, 0xad, 0x6e, 0xfb, 0x46, 0x19}};
|
||||
|
||||
static constexpr auto EFI_DT_FIXUP_PROTOCOL_GUID =
|
||||
EfiGuid{0xe617d64c,
|
||||
0xfe08,
|
||||
0x46da,
|
||||
{0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00}};
|
||||
|
||||
using EFI_IMAGE_UNLOAD = EfiStatus (*)(EfiHandle);
|
||||
|
||||
//******************************************************
|
||||
|
||||
@@ -17,15 +17,25 @@
|
||||
|
||||
#include "configuration_table.h"
|
||||
#include "boot_service_provider.h"
|
||||
#include "libfdt.h"
|
||||
#include "platform.h"
|
||||
#include "system_table.h"
|
||||
#include <string.h>
|
||||
|
||||
void setup_configuration_table(EfiSystemTable *table) {
|
||||
auto &rng = table->configuration_table[0];
|
||||
auto &rng = table->configuration_table[table->number_of_table_entries++];
|
||||
rng.vendor_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
|
||||
rng.vendor_table = alloc_page(PAGE_SIZE);
|
||||
auto rng_seed = reinterpret_cast<linux_efi_random_seed *>(rng.vendor_table);
|
||||
rng_seed->size = 512;
|
||||
memset(&rng_seed->bits, 0, rng_seed->size);
|
||||
table->number_of_table_entries = 1;
|
||||
|
||||
const void *fdt = get_fdt();
|
||||
if (fdt != nullptr) {
|
||||
auto &dtb = table->configuration_table[table->number_of_table_entries++];
|
||||
dtb.vendor_guid = DEVICE_TREE_GUID;
|
||||
const auto fdt_size = fdt_totalsize(fdt);
|
||||
dtb.vendor_table = alloc_page(fdt_size);
|
||||
memcpy(dtb.vendor_table, fdt, fdt_size);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,11 @@ static constexpr auto LINUX_EFI_RANDOM_SEED_TABLE_GUID =
|
||||
0x7ceb,
|
||||
0x42f2,
|
||||
{0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b}};
|
||||
static constexpr auto DEVICE_TREE_GUID =
|
||||
EfiGuid{0xb1b621d5,
|
||||
0xf19c,
|
||||
0x41a5,
|
||||
{0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}};
|
||||
|
||||
void setup_configuration_table(EfiSystemTable *table);
|
||||
|
||||
|
||||
@@ -25,13 +25,14 @@ typedef struct EfiBlockIoProtocol EfiBlockIoProtocol;
|
||||
|
||||
struct EfiBlockIoProtocol {
|
||||
uint64_t revision;
|
||||
EfiBlockIoMedia* media;
|
||||
EfiStatus (*reset)(EfiBlockIoProtocol* self, bool extended_verification);
|
||||
EfiStatus (*read_blocks)(EfiBlockIoProtocol* self, uint32_t media_id, uint64_t lba,
|
||||
size_t buffer_size, void* buffer);
|
||||
EfiStatus (*write_blocks)(EfiBlockIoProtocol* self, uint32_t media_id, uint64_t lba,
|
||||
size_t buffer_size, const void* buffer);
|
||||
EfiStatus (*flush_blocks)(EfiBlockIoProtocol* self);
|
||||
EfiBlockIoMedia *media;
|
||||
EfiStatus (*reset)(EfiBlockIoProtocol *self, bool extended_verification);
|
||||
EfiStatus (*read_blocks)(EfiBlockIoProtocol *self, uint32_t media_id,
|
||||
uint64_t lba, size_t buffer_size, void *buffer);
|
||||
EfiStatus (*write_blocks)(EfiBlockIoProtocol *self, uint32_t media_id,
|
||||
uint64_t lba, size_t buffer_size,
|
||||
const void *buffer);
|
||||
EfiStatus (*flush_blocks)(EfiBlockIoProtocol *self);
|
||||
};
|
||||
|
||||
struct EfiBlockIoMedia {
|
||||
@@ -54,4 +55,11 @@ struct EfiBlockIoMedia {
|
||||
uint32_t optimal_transfer_length_granularity;
|
||||
};
|
||||
|
||||
#endif //__BLOCK_IO_PROTOCOL_H__
|
||||
struct EfiBlockIoInterface {
|
||||
EfiBlockIoProtocol protocol;
|
||||
void *dev;
|
||||
EfiBlockIoMedia media;
|
||||
void *io_stack;
|
||||
};
|
||||
|
||||
#endif //__BLOCK_IO_PROTOCOL_H__
|
||||
|
||||
45
lib/uefi/local/include/protocols/dt_fixup_protocol.h
Normal file
45
lib/uefi/local/include/protocols/dt_fixup_protocol.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// This is a protocol proposed by U-boot and being used by Kernel UEFI stub.
|
||||
// https://github.com/U-Boot-EFI/EFI_DT_FIXUP_PROTOCOL
|
||||
// https://github.com/u-boot/u-boot/blob/master/include/efi_dt_fixup.h
|
||||
|
||||
#ifndef __EFI_DT_FIXUP_PROTOCOL_H__
|
||||
#define __EFI_DT_FIXUP_PROTOCOL_H__
|
||||
|
||||
#include "types.h"
|
||||
|
||||
constexpr uint64_t EFI_DT_FIXUP_PROTOCOL_REVISION = 0x00010000;
|
||||
|
||||
// Add nodes and update properties
|
||||
constexpr uint32_t EFI_DT_APPLY_FIXUPS = 0x00000001;
|
||||
// Reserve memory according to the /reserved-memory node and the memory
|
||||
// reservation block
|
||||
constexpr uint32_t EFI_DT_RESERVE_MEMORY = 0x00000002;
|
||||
// Install the device-tree as configuration table
|
||||
constexpr uint32_t EFI_DT_INSTALL_TABLE = 0x00000004;
|
||||
constexpr uint32_t EFI_DT_ALL =
|
||||
EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY | EFI_DT_INSTALL_TABLE;
|
||||
|
||||
typedef struct EfiDtFixupProtocol {
|
||||
uint64_t revision;
|
||||
EfiStatus (*fixup)(struct EfiDtFixupProtocol *self, void *fdt,
|
||||
size_t *buffer_size, uint32_t flags);
|
||||
} EfiDtFixupProtocol;
|
||||
|
||||
#endif // __EFI_DT_FIXUP_PROTOCOL_H__
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// This is a custom protocol introduced by GBL.
|
||||
// See gbl/docs/gbl_efi_os_configuration_protocol.md for details.
|
||||
|
||||
#ifndef __GBL_OS_CONFIGURATION_PROTOCOL_H__
|
||||
#define __GBL_OS_CONFIGURATION_PROTOCOL_H__
|
||||
|
||||
#include "types.h"
|
||||
|
||||
static constexpr size_t GBL_EFI_OS_CONFIGURATION_PROTOCOL_REVISION = 0x00000000;
|
||||
|
||||
typedef enum GBL_EFI_DEVICE_TREE_SOURCE {
|
||||
BOOT,
|
||||
VENDOR_BOOT,
|
||||
DTBO,
|
||||
DTB
|
||||
} GblEfiDeviceTreeSource;
|
||||
|
||||
typedef struct {
|
||||
// GblDeviceTreeSource
|
||||
uint32_t source;
|
||||
// Values are zeroed and must not be used in case of BOOT / VENDOR_BOOT source
|
||||
uint32_t id;
|
||||
uint32_t rev;
|
||||
uint32_t custom[4];
|
||||
// Make sure GblDeviceTreeMetadata size is 8-bytes aligned. Also reserved for
|
||||
// the future cases
|
||||
uint32_t reserved;
|
||||
} GblEfiDeviceTreeMetadata;
|
||||
|
||||
typedef struct {
|
||||
GblEfiDeviceTreeMetadata metadata;
|
||||
// Base device tree / overlay buffer (guaranteed to be 8-bytes aligned),
|
||||
// cannot be NULL. Device tree size can be identified by the header totalsize
|
||||
// field
|
||||
const void *device_tree;
|
||||
// Indicates whether this device tree (or overlay) must be included in the
|
||||
// final device tree. Set to true by a FW if this component must be used
|
||||
bool selected;
|
||||
} GblEfiVerifiedDeviceTree;
|
||||
|
||||
// Warning: API is UNSTABLE
|
||||
// Documentation:
|
||||
// https://cs.android.com/android/platform/superproject/main/+/main:bootable/libbootloader/gbl/docs/gbl_os_configuration_protocol.md
|
||||
typedef struct GblEfiOsConfigurationProtocol {
|
||||
uint64_t revision;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
} GblEfiOsConfigurationProtocol;
|
||||
|
||||
#endif //__GBL_OS_CONFIGURATION_PROTOCOL_H__
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto &&kSecureBoot = L"SecureBoot";
|
||||
|
||||
EFI_STATUS GetVariable(char16_t *VariableName, EfiGuid *VendorGuid,
|
||||
@@ -62,6 +64,8 @@ EFI_STATUS SetVariable(char16_t *VariableName, EfiGuid *VendorGuid,
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup_runtime_service_table(EfiRuntimeService *service) {
|
||||
service->GetVariable = GetVariable;
|
||||
service->SetVariable = SetVariable;
|
||||
|
||||
@@ -14,25 +14,27 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <lk/asm.h>
|
||||
|
||||
|
||||
// int call_with_stack(void *stack, int (*fp)(), int param1, int param2);
|
||||
FUNCTION(call_with_stack)
|
||||
// int call_with_stack_asm(void *stack, int (*fp)(), int arg1, int arg2, int arg3, int arg4);
|
||||
FUNCTION(call_with_stack_asm)
|
||||
stp fp, lr, [sp, #-16]!
|
||||
mov fp, sp
|
||||
|
||||
sub x0,x0,16
|
||||
mov x6,sp
|
||||
str x6,[x0]
|
||||
mov x7,sp
|
||||
str x7,[x0]
|
||||
mov sp,x0
|
||||
mov x5,x1
|
||||
mov x6,x1
|
||||
mov x0,x2
|
||||
mov x1,x3
|
||||
blr x5
|
||||
ldr x6,[sp]
|
||||
mov sp,x6
|
||||
mov x2,x4
|
||||
mov x3,x5
|
||||
blr x6
|
||||
ldr x7,[sp]
|
||||
mov sp,x7
|
||||
|
||||
ldp fp, lr, [sp], 16
|
||||
ret lr
|
||||
END_FUNCTION(call_with_stack_asm)
|
||||
|
||||
@@ -15,13 +15,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include <lk/compiler.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#endif
|
||||
__BEGIN_CDECLS
|
||||
|
||||
size_t call_with_stack_asm(void *stack, const void *function, void *param1,
|
||||
void *param2, void *param3, void *param4);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
int call_with_stack(void *stack, int (*fp)(void *, void *), void *param1,
|
||||
void *param2);
|
||||
#ifdef __cplusplus
|
||||
template <typename Function, typename P1, typename P2, typename P3, typename P4>
|
||||
size_t call_with_stack(void *stack, Function &&fp, P1 &¶m1, P2 &¶m2,
|
||||
P3 &¶m3, P4 &¶m4) {
|
||||
return call_with_stack_asm(
|
||||
stack, reinterpret_cast<const void *>(fp),
|
||||
reinterpret_cast<void *>(param1), reinterpret_cast<void *>(param2),
|
||||
reinterpret_cast<void *>(param3), reinterpret_cast<void *>(param4));
|
||||
}
|
||||
|
||||
template <typename Function, typename P1, typename P2>
|
||||
size_t call_with_stack(void *stack, Function &&fp, P1 &¶m1, P2 &¶m2) {
|
||||
return call_with_stack_asm(
|
||||
stack, reinterpret_cast<const void *>(fp),
|
||||
reinterpret_cast<void *>(param1), reinterpret_cast<void *>(param2), 0, 0);
|
||||
}
|
||||
#endif
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "system_table.h"
|
||||
#include "text_protocol.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto EFI_SYSTEM_TABLE_SIGNATURE =
|
||||
static_cast<u64>(0x5453595320494249ULL);
|
||||
|
||||
@@ -56,9 +58,9 @@ template <typename T> void fill(T *data, size_t skip, uint8_t begin = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t BIT26 = 1 << 26;
|
||||
static constexpr size_t BIT11 = 1 << 11;
|
||||
static constexpr size_t BIT10 = 1 << 10;
|
||||
constexpr size_t BIT26 = 1 << 26;
|
||||
constexpr size_t BIT11 = 1 << 11;
|
||||
constexpr size_t BIT10 = 1 << 10;
|
||||
|
||||
/**
|
||||
Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and
|
||||
@@ -288,6 +290,7 @@ int load_sections_and_execute(bdev_t *dev,
|
||||
table.runtime_service = &runtime_service;
|
||||
table.boot_services = &boot_service;
|
||||
table.header.signature = EFI_SYSTEM_TABLE_SIGNATURE;
|
||||
table.header.revision = 2 << 16;
|
||||
EfiSimpleTextOutputProtocol console_out = get_text_output_protocol();
|
||||
table.con_out = &console_out;
|
||||
table.configuration_table =
|
||||
@@ -297,6 +300,8 @@ int load_sections_and_execute(bdev_t *dev,
|
||||
constexpr size_t kStackSize = 8 * 1024ul * 1024;
|
||||
auto stack = reinterpret_cast<char *>(alloc_page(kStackSize, 23));
|
||||
memset(stack, 0, kStackSize);
|
||||
printf("Calling kernel with stack [%p, %p]\n", stack,
|
||||
stack + kStackSize - 1);
|
||||
return call_with_stack(stack + kStackSize, entry, image_base, &table);
|
||||
}
|
||||
|
||||
@@ -306,7 +311,10 @@ int load_pe_file(const char *blkdev) {
|
||||
printf("error opening block device %s\n", blkdev);
|
||||
return -1;
|
||||
}
|
||||
DEFER { bio_close(dev); };
|
||||
DEFER {
|
||||
bio_close(dev);
|
||||
dev = nullptr;
|
||||
};
|
||||
constexpr size_t kBlocKSize = 4096;
|
||||
|
||||
lk_time_t t = current_time();
|
||||
@@ -366,3 +374,5 @@ int cmd_uefi_load(int argc, const console_cmd_args *argv) {
|
||||
STATIC_COMMAND_START
|
||||
STATIC_COMMAND("uefi_load", "load UEFI application and run it", &cmd_uefi_load)
|
||||
STATIC_COMMAND_END(uefi);
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -82,5 +82,8 @@ void platform_init(void);
|
||||
/* called by the arch init code to get the platform to set up any mmu mappings it may need */
|
||||
void platform_init_mmu_mappings(void);
|
||||
|
||||
/* Called by LK to get the device tree */
|
||||
const void *get_fdt(void);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
|
||||
@@ -27,3 +27,8 @@ __WEAK void platform_init(void) {
|
||||
__WEAK void platform_quiesce(void) {
|
||||
}
|
||||
|
||||
|
||||
__WEAK const void *get_fdt(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ struct mmu_initial_mapping mmu_initial_mappings[] = {
|
||||
|
||||
const void *fdt = (void *)KERNEL_BASE;
|
||||
|
||||
const void *get_fdt(void) {
|
||||
return fdt;
|
||||
}
|
||||
|
||||
void platform_early_init(void) {
|
||||
const struct pl011_config uart_config = {
|
||||
.base = UART_BASE,
|
||||
|
||||
Reference in New Issue
Block a user