diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 2 | ||||
-rw-r--r-- | lib/crc8.c | 33 | ||||
-rw-r--r-- | lib/efi/efi_stub.c | 5 | ||||
-rw-r--r-- | lib/efi_loader/Makefile | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 13 | ||||
-rw-r--r-- | lib/efi_loader/efi_gop.c | 152 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 5 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 29 | ||||
-rw-r--r-- | lib/physmem.c | 6 |
9 files changed, 219 insertions, 27 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 7a453362a1..2b97c2b0a4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -16,7 +16,7 @@ config USE_PRIVATE_LIBGCC depends on HAVE_PRIVATE_LIBGCC help This option allows you to use the built-in libgcc implementation - of U-Boot instead of the one privided by the compiler. + of U-Boot instead of the one provided by the compiler. If unsure, say N. config SYS_HZ diff --git a/lib/crc8.c b/lib/crc8.c index 8b68a29e40..51d540fbcb 100644 --- a/lib/crc8.c +++ b/lib/crc8.c @@ -6,20 +6,27 @@ #include "linux/crc8.h" -unsigned int crc8(const unsigned char *vptr, int len) +#define POLY (0x1070U << 3) + +static unsigned char _crc8(unsigned short data) { - const unsigned char *data = vptr; - unsigned int crc = 0; - int i, j; - - for (j = len; j; j--, data++) { - crc ^= (*data << 8); - for (i = 8; i; i--) { - if (crc & 0x8000) - crc ^= (0x1070 << 3); - crc <<= 1; - } + int i; + + for (i = 0; i < 8; i++) { + if (data & 0x8000) + data = data ^ POLY; + data = data << 1; } - return (crc >> 8) & 0xff; + return (unsigned char)(data >> 8); +} + +unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len) +{ + int i; + + for (i = 0; i < len; i++) + crc = _crc8((crc ^ vptr[i]) << 8); + + return crc; } diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c index e13870931e..8b4bb4e78f 100644 --- a/lib/efi/efi_stub.c +++ b/lib/efi/efi_stub.c @@ -65,6 +65,9 @@ void _debug_uart_init(void) void putc(const char ch) { + if (ch == '\n') + putc('\r'); + if (use_uart) { NS16550_t com_port = (NS16550_t)0x3f8; @@ -74,8 +77,6 @@ void putc(const char ch) } else { efi_putc(global_priv, ch); } - if (ch == '\n') - putc('\r'); } void puts(const char *str) diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 28725a27c7..83e31f6d1f 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -9,4 +9,5 @@ obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o +obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_PARTITIONS) += efi_disk.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 87400dee1a..9daca50a72 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -137,12 +137,20 @@ efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long *memory_map_size, static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size, void **buffer) { - return efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, (void*)buffer); + efi_status_t r; + + EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer); + r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, (void*)buffer); + return EFI_EXIT(r); } static efi_status_t EFIAPI efi_free_pool(void *buffer) { - return efi_free_pages((ulong)buffer, 0); + efi_status_t r; + + EFI_ENTRY("%p", buffer); + r = efi_free_pages((ulong)buffer, 0); + return EFI_EXIT(r); } /* @@ -706,7 +714,6 @@ static efi_status_t EFIAPI efi_handle_protocol(void *handle, efi_guid_t *protocol, void **protocol_interface) { - EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface); return efi_open_protocol(handle, protocol, protocol_interface, NULL, NULL, 0); } diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c new file mode 100644 index 0000000000..bdd62bc557 --- /dev/null +++ b/lib/efi_loader/efi_gop.c @@ -0,0 +1,152 @@ +/* + * EFI application disk support + * + * Copyright (c) 2016 Alexander Graf + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <efi_loader.h> +#include <inttypes.h> +#include <lcd.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const efi_guid_t efi_gop_guid = EFI_GOP_GUID; + +struct efi_gop_obj { + /* Generic EFI object parent class data */ + struct efi_object parent; + /* EFI Interface callback struct for gop */ + struct efi_gop ops; + /* The only mode we support */ + struct efi_gop_mode_info info; + struct efi_gop_mode mode; +}; + +static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number, + unsigned long *size_of_info, + struct efi_gop_mode_info **info) +{ + struct efi_gop_obj *gopobj; + + EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info); + + gopobj = container_of(this, struct efi_gop_obj, ops); + *size_of_info = sizeof(gopobj->info); + *info = &gopobj->info; + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number) +{ + EFI_ENTRY("%p, %x", this, mode_number); + + if (mode_number != 0) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI gop_blt(struct efi_gop *this, void *buffer, + unsigned long operation, unsigned long sx, + unsigned long sy, unsigned long dx, + unsigned long dy, unsigned long width, + unsigned long height, unsigned long delta) +{ + int i, j, line_len16, line_len32; + void *fb; + + EFI_ENTRY("%p, %p, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx", this, + buffer, operation, sx, sy, dx, dy, width, height, delta); + + if (operation != EFI_BLT_BUFFER_TO_VIDEO) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + fb = (void*)gd->fb_base; + line_len16 = panel_info.vl_col * sizeof(u16); + line_len32 = panel_info.vl_col * sizeof(u32); + + /* Copy the contents line by line */ + + switch (panel_info.vl_bpix) { + case LCD_COLOR32: + for (i = 0; i < height; i++) { + u32 *dest = fb + ((i + dy) * line_len32) + + (dx * sizeof(u32)); + u32 *src = buffer + ((i + sy) * line_len32) + + (sx * sizeof(u32)); + + /* Same color format, just memcpy */ + memcpy(dest, src, width * sizeof(u32)); + } + break; + case LCD_COLOR16: + for (i = 0; i < height; i++) { + u16 *dest = fb + ((i + dy) * line_len16) + + (dx * sizeof(u16)); + u32 *src = buffer + ((i + sy) * line_len32) + + (sx * sizeof(u32)); + + /* Convert from rgb888 to rgb565 */ + for (j = 0; j < width; j++) { + u32 rgb888 = src[j]; + dest[j] = ((((rgb888 >> (16 + 3)) & 0x1f) << 11) | + (((rgb888 >> (8 + 2)) & 0x3f) << 5) | + (((rgb888 >> (0 + 3)) & 0x1f) << 0)); + } + } + break; + } + + lcd_sync(); + + return EFI_EXIT(EFI_SUCCESS); +} + +/* This gets called from do_bootefi_exec(). */ +int efi_gop_register(void) +{ + struct efi_gop_obj *gopobj; + int line_len; + + switch (panel_info.vl_bpix) { + case LCD_COLOR32: + case LCD_COLOR16: + break; + default: + /* So far, we only work in 16 or 32 bit mode */ + return -1; + } + + gopobj = calloc(1, sizeof(*gopobj)); + + /* Fill in object data */ + gopobj->parent.protocols[0].guid = &efi_gop_guid; + gopobj->parent.protocols[0].open = efi_return_handle; + gopobj->parent.handle = &gopobj->ops; + gopobj->ops.query_mode = gop_query_mode; + gopobj->ops.set_mode = gop_set_mode; + gopobj->ops.blt = gop_blt; + gopobj->ops.mode = &gopobj->mode; + + gopobj->mode.max_mode = 1; + gopobj->mode.info = &gopobj->info; + gopobj->mode.info_size = sizeof(gopobj->info); + gopobj->mode.fb_base = gd->fb_base; + gopobj->mode.fb_size = lcd_get_size(&line_len); + + gopobj->info.version = 0; + gopobj->info.width = panel_info.vl_col; + gopobj->info.height = panel_info.vl_row; + gopobj->info.pixel_format = EFI_GOT_RGBA8; + gopobj->info.pixels_per_scanline = panel_info.vl_col; + + /* Hook up to the device list */ + list_add_tail(&gopobj->parent.link, &efi_obj_list); + + return 0; +} diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index d558f5a8a9..574b204f23 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -22,11 +22,8 @@ efi_status_t EFIAPI efi_return_handle(void *handle, efi_guid_t *protocol, void **protocol_interface, void *agent_handle, void *controller_handle, uint32_t attributes) { - EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol, - protocol_interface, agent_handle, controller_handle, - attributes); *protocol_interface = handle; - return EFI_EXIT(EFI_SUCCESS); + return EFI_SUCCESS; } static void efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c82b53f336..8a1e249430 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -13,6 +13,7 @@ #include <malloc.h> #include <asm/global_data.h> #include <libfdt_env.h> +#include <linux/list_sort.h> #include <inttypes.h> #include <watchdog.h> @@ -27,6 +28,31 @@ struct efi_mem_list { LIST_HEAD(efi_mem); /* + * Sorts the memory list from highest address to lowest address + * + * When allocating memory we should always start from the highest + * address chunk, so sort the memory list such that the first list + * iterator gets the highest address and goes lower from there. + */ +static int efi_mem_cmp(void *priv, struct list_head *a, struct list_head *b) +{ + struct efi_mem_list *mema = list_entry(a, struct efi_mem_list, link); + struct efi_mem_list *memb = list_entry(b, struct efi_mem_list, link); + + if (mema->desc.physical_start == memb->desc.physical_start) + return 0; + else if (mema->desc.physical_start < memb->desc.physical_start) + return 1; + else + return -1; +} + +static void efi_mem_sort(void) +{ + list_sort(NULL, &efi_mem, efi_mem_cmp); +} + +/* * Unmaps all memory occupied by the carve_desc region from the * list entry pointed to by map. * @@ -142,6 +168,9 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, /* Add our new map */ list_add_tail(&newlist->link, &efi_mem); + /* And make sure memory is listed in descending order */ + efi_mem_sort(); + return start; } diff --git a/lib/physmem.c b/lib/physmem.c index 0f035edcbe..f21ac243ed 100644 --- a/lib/physmem.c +++ b/lib/physmem.c @@ -10,8 +10,9 @@ #include <common.h> #include <physmem.h> +#include <linux/compiler.h> -static phys_addr_t __arch_phys_memset(phys_addr_t s, int c, phys_size_t n) +phys_addr_t __weak arch_phys_memset(phys_addr_t s, int c, phys_size_t n) { void *s_ptr = (void *)(uintptr_t)s; @@ -19,6 +20,3 @@ static phys_addr_t __arch_phys_memset(phys_addr_t s, int c, phys_size_t n) assert(((phys_addr_t)(uintptr_t)(s + n)) == s + n); return (phys_addr_t)(uintptr_t)memset(s_ptr, c, n); } - -phys_addr_t arch_phys_memset(phys_addr_t s, int c, phys_size_t n) - __attribute__((weak, alias("__arch_phys_memset"))); |