#define EFI_RUNTIME_DATA __attribute__ ((section ("efi_runtime_data")))
#define EFI_RUNTIME_TEXT __attribute__ ((section ("efi_runtime_text")))
+/* Call this with mmio_ptr as the _pointer_ to a pointer to an MMIO region
+ * to make it available at runtime */
+void efi_add_runtime_mmio(void *mmio_ptr, u64 len);
+
+/* Boards may provide the functions below to implement RTS functionality */
+
+void 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);
+void efi_reset_system_init(void);
+
+efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_get_time(
+ struct efi_time *time,
+ struct efi_time_cap *capabilities);
+void efi_get_time_init(void);
+
#else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
#define EFI_RUNTIME_DATA
#define EFI_RUNTIME_TEXT
+static inline void efi_add_runtime_mmio(void **mmio_ptr, u64 len) { }
/* No loader configured, stub out EFI_ENTRY */
static inline void efi_restore_gd(void) { }
/* 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);
* 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);
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;
#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;
{
/* 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,
}, {
/* 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,
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
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
.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,
.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,
};