|
@@ -16,6 +16,16 @@
|
|
|
/* For manual relocation support */
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
+struct efi_runtime_mmio_list {
|
|
|
+ struct list_head link;
|
|
|
+ void **ptr;
|
|
|
+ u64 paddr;
|
|
|
+ u64 len;
|
|
|
+};
|
|
|
+
|
|
|
+/* This list contains all runtime available mmio regions */
|
|
|
+LIST_HEAD(efi_runtime_mmio);
|
|
|
+
|
|
|
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void);
|
|
|
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void);
|
|
|
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void);
|
|
@@ -55,9 +65,10 @@ struct elf_rela {
|
|
|
* handle a good number of runtime callbacks
|
|
|
*/
|
|
|
|
|
|
-static void EFIAPI efi_reset_system(enum efi_reset_type reset_type,
|
|
|
- efi_status_t reset_status,
|
|
|
- unsigned long data_size, void *reset_data)
|
|
|
+static void EFIAPI efi_reset_system_boottime(
|
|
|
+ enum efi_reset_type reset_type,
|
|
|
+ efi_status_t reset_status,
|
|
|
+ unsigned long data_size, void *reset_data)
|
|
|
{
|
|
|
EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
|
|
|
reset_data);
|
|
@@ -72,11 +83,12 @@ static void EFIAPI efi_reset_system(enum efi_reset_type reset_type,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- EFI_EXIT(EFI_SUCCESS);
|
|
|
+ while (1) { }
|
|
|
}
|
|
|
|
|
|
-static efi_status_t EFIAPI efi_get_time(struct efi_time *time,
|
|
|
- struct efi_time_cap *capabilities)
|
|
|
+static efi_status_t EFIAPI efi_get_time_boottime(
|
|
|
+ struct efi_time *time,
|
|
|
+ struct efi_time_cap *capabilities)
|
|
|
{
|
|
|
#if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC)
|
|
|
struct rtc_time tm;
|
|
@@ -107,6 +119,33 @@ static efi_status_t EFIAPI efi_get_time(struct efi_time *time,
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+/* Boards may override the helpers below to implement RTS functionality */
|
|
|
+
|
|
|
+void __weak EFI_RUNTIME_TEXT EFIAPI efi_reset_system(
|
|
|
+ enum efi_reset_type reset_type,
|
|
|
+ efi_status_t reset_status,
|
|
|
+ unsigned long data_size, void *reset_data)
|
|
|
+{
|
|
|
+ /* Nothing we can do */
|
|
|
+ while (1) { }
|
|
|
+}
|
|
|
+
|
|
|
+void __weak efi_reset_system_init(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+efi_status_t __weak EFI_RUNTIME_TEXT EFIAPI efi_get_time(
|
|
|
+ struct efi_time *time,
|
|
|
+ struct efi_time_cap *capabilities)
|
|
|
+{
|
|
|
+ /* Nothing we can do */
|
|
|
+ return EFI_DEVICE_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
+void __weak efi_get_time_init(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
struct efi_runtime_detach_list_struct {
|
|
|
void *ptr;
|
|
|
void *patchto;
|
|
@@ -116,7 +155,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
|
|
{
|
|
|
/* do_reset is gone */
|
|
|
.ptr = &efi_runtime_services.reset_system,
|
|
|
- .patchto = NULL,
|
|
|
+ .patchto = efi_reset_system,
|
|
|
}, {
|
|
|
/* invalidate_*cache_all are gone */
|
|
|
.ptr = &efi_runtime_services.set_virtual_address_map,
|
|
@@ -124,7 +163,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
|
|
}, {
|
|
|
/* RTC accessors are gone */
|
|
|
.ptr = &efi_runtime_services.get_time,
|
|
|
- .patchto = &efi_device_error,
|
|
|
+ .patchto = &efi_get_time,
|
|
|
}, {
|
|
|
/* Clean up system table */
|
|
|
.ptr = &systab.con_in,
|
|
@@ -233,12 +272,39 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
|
|
EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
|
|
|
descriptor_version, virtmap);
|
|
|
|
|
|
+ /* Rebind mmio pointers */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ struct efi_mem_desc *map = (void*)virtmap +
|
|
|
+ (descriptor_size * i);
|
|
|
+ struct list_head *lhandle;
|
|
|
+ efi_physical_addr_t map_start = map->physical_start;
|
|
|
+ efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT;
|
|
|
+ efi_physical_addr_t map_end = map_start + map_len;
|
|
|
+
|
|
|
+ /* Adjust all mmio pointers in this region */
|
|
|
+ list_for_each(lhandle, &efi_runtime_mmio) {
|
|
|
+ struct efi_runtime_mmio_list *lmmio;
|
|
|
+
|
|
|
+ lmmio = list_entry(lhandle,
|
|
|
+ struct efi_runtime_mmio_list,
|
|
|
+ link);
|
|
|
+ if ((map_start <= lmmio->paddr) &&
|
|
|
+ (map_end >= lmmio->paddr)) {
|
|
|
+ u64 off = map->virtual_start - map_start;
|
|
|
+ uintptr_t new_addr = lmmio->paddr + off;
|
|
|
+ *lmmio->ptr = (void *)new_addr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Move the actual runtime code over */
|
|
|
for (i = 0; i < n; i++) {
|
|
|
struct efi_mem_desc *map;
|
|
|
|
|
|
map = (void*)virtmap + (descriptor_size * i);
|
|
|
if (map->type == EFI_RUNTIME_SERVICES_CODE) {
|
|
|
- ulong new_offset = map->virtual_start - (runtime_start - gd->relocaddr);
|
|
|
+ ulong new_offset = map->virtual_start -
|
|
|
+ (runtime_start - gd->relocaddr);
|
|
|
|
|
|
efi_runtime_relocate(new_offset, map);
|
|
|
/* Once we're virtual, we can no longer handle
|
|
@@ -251,6 +317,20 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
|
|
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
|
|
}
|
|
|
|
|
|
+void efi_add_runtime_mmio(void *mmio_ptr, u64 len)
|
|
|
+{
|
|
|
+ struct efi_runtime_mmio_list *newmmio;
|
|
|
+
|
|
|
+ u64 pages = (len + EFI_PAGE_SIZE - 1) >> EFI_PAGE_SHIFT;
|
|
|
+ efi_add_memory_map(*(uintptr_t *)mmio_ptr, pages, EFI_MMAP_IO, false);
|
|
|
+
|
|
|
+ newmmio = calloc(1, sizeof(*newmmio));
|
|
|
+ newmmio->ptr = mmio_ptr;
|
|
|
+ newmmio->paddr = *(uintptr_t *)mmio_ptr;
|
|
|
+ newmmio->len = len;
|
|
|
+ list_add_tail(&newmmio->link, &efi_runtime_mmio);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* In the second stage, U-Boot has disappeared. To isolate our runtime code
|
|
|
* that at this point still exists from the rest, we put it into a special
|
|
@@ -292,7 +372,7 @@ struct efi_runtime_services EFI_RUNTIME_DATA efi_runtime_services = {
|
|
|
.revision = EFI_RUNTIME_SERVICES_REVISION,
|
|
|
.headersize = sizeof(struct efi_table_hdr),
|
|
|
},
|
|
|
- .get_time = &efi_get_time,
|
|
|
+ .get_time = &efi_get_time_boottime,
|
|
|
.set_time = (void *)&efi_device_error,
|
|
|
.get_wakeup_time = (void *)&efi_unimplemented,
|
|
|
.set_wakeup_time = (void *)&efi_unimplemented,
|
|
@@ -302,5 +382,5 @@ struct efi_runtime_services EFI_RUNTIME_DATA efi_runtime_services = {
|
|
|
.get_next_variable = (void *)&efi_device_error,
|
|
|
.set_variable = (void *)&efi_device_error,
|
|
|
.get_next_high_mono_count = (void *)&efi_device_error,
|
|
|
- .reset_system = &efi_reset_system,
|
|
|
+ .reset_system = &efi_reset_system_boottime,
|
|
|
};
|