summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig2
-rw-r--r--lib/crc8.c33
-rw-r--r--lib/efi/efi_stub.c5
-rw-r--r--lib/efi_loader/Makefile1
-rw-r--r--lib/efi_loader/efi_boottime.c13
-rw-r--r--lib/efi_loader/efi_gop.c152
-rw-r--r--lib/efi_loader/efi_image_loader.c5
-rw-r--r--lib/efi_loader/efi_memory.c29
-rw-r--r--lib/physmem.c6
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")));