aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/Makefile1
-rw-r--r--lib/asm-offsets.c2
-rw-r--r--lib/efi_selftest/efi_selftest_bitblt.c83
-rw-r--r--lib/lmb.c37
-rw-r--r--lib/of_live.c141
6 files changed, 245 insertions, 25 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index bc106e2b6f..19649517a3 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -691,6 +691,12 @@ config SPL_CRC8
checksum with feedback to produce an 8-bit result. The code is small
and it does not require a lookup table (unlike CRC32).
+config SPL_CRC16
+ bool "Support CRC16 in SPL"
+ depends on SPL
+ help
+ Enables CRC16 support in SPL. This is not normally required.
+
config CRC32
def_bool y
help
diff --git a/lib/Makefile b/lib/Makefile
index 1c31ad9531..2a76acf100 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_TPM_V2) += tpm-v2.o
endif
obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
+obj-$(CONFIG_$(SPL_TPL_)CRC16) += crc16.o
obj-y += crypto/
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index 0808cd4b0c..216d9716d0 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -32,7 +32,7 @@ int main(void)
DEFINE(GD_FLAGS, offsetof(struct global_data, flags));
-#if CONFIG_VAL(SYS_MALLOC_F_LEN)
+#if CONFIG_IS_ENABLED(SYS_MALLOC_F)
DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base));
#endif
diff --git a/lib/efi_selftest/efi_selftest_bitblt.c b/lib/efi_selftest/efi_selftest_bitblt.c
index 1def843505..605078b722 100644
--- a/lib/efi_selftest/efi_selftest_bitblt.c
+++ b/lib/efi_selftest/efi_selftest_bitblt.c
@@ -14,6 +14,12 @@
#define HEIGHT 120
#define DEPTH 60
+struct pos {
+ efi_uintn_t x;
+ efi_uintn_t y;
+ int redrawn;
+};
+
static const struct efi_gop_pixel BLACK = { 0, 0, 0, 0};
static const struct efi_gop_pixel RED = { 0, 0, 255, 0};
static const struct efi_gop_pixel ORANGE = { 0, 128, 255, 0};
@@ -27,7 +33,7 @@ static efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
static struct efi_gop *gop;
static struct efi_gop_pixel *bitmap;
static struct efi_event *event;
-static efi_uintn_t xpos;
+static struct pos pos;
static void ellipse(efi_uintn_t x, efi_uintn_t y,
efi_uintn_t x0, efi_uintn_t y0,
@@ -62,31 +68,33 @@ static void rectangle(efi_uintn_t x, efi_uintn_t y,
*/
static void EFIAPI notify(struct efi_event *event, void *context)
{
- efi_uintn_t *pos = context;
+ struct pos *pos = context;
efi_uintn_t dx, sx, width;
if (!pos)
return;
/* Increment position */
- *pos += 5;
- if (*pos >= WIDTH + gop->mode->info->width)
- *pos = 0;
+ pos->x += 5;
+ if (pos->x >= WIDTH + gop->mode->info->width)
+ pos->x = 0;
width = WIDTH;
- dx = *pos - WIDTH;
+ dx = pos->x - WIDTH;
sx = 0;
- if (*pos >= gop->mode->info->width) {
- width = WIDTH + gop->mode->info->width - *pos;
- } else if (*pos < WIDTH) {
+ if (pos->x >= gop->mode->info->width) {
+ width = WIDTH + gop->mode->info->width - pos->x;
+ } else if (pos->x < WIDTH) {
dx = 0;
- sx = WIDTH - *pos;
- width = *pos;
+ sx = WIDTH - pos->x;
+ width = pos->x;
}
/* Copy image to video */
- gop->blt(gop, bitmap, EFI_BLT_BUFFER_TO_VIDEO, sx, 0, dx, DEPTH,
+ gop->blt(gop, bitmap, EFI_BLT_BUFFER_TO_VIDEO, sx, 0, dx, pos->y,
width, HEIGHT, WIDTH * sizeof(struct efi_gop_pixel));
+
+ pos->redrawn = 1;
}
/*
@@ -107,7 +115,7 @@ static int setup(const efi_handle_t handle,
/* Create event */
ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK, notify, (void *)&xpos,
+ TPL_CALLBACK, notify, (void *)&pos,
&event);
if (ret != EFI_SUCCESS) {
efi_st_error("could not create event\n");
@@ -247,6 +255,9 @@ static int execute(void)
return EFI_ST_FAILURE;
}
+ con_out->set_attribute(con_out, EFI_WHITE | EFI_BACKGROUND_BLUE);
+ con_out->clear_screen(con_out);
+
/* Fill background */
ret = gop->blt(gop, bitmap, EFI_BLT_VIDEO_FILL, 0, 0, 0, 0,
info->width, info->height, 0);
@@ -281,21 +292,53 @@ static int execute(void)
return EFI_ST_FAILURE;
}
- /* Set 250ms timer */
- xpos = WIDTH;
+ /* Set 25ms timer */
+ pos.x = WIDTH;
+ pos.y = DEPTH;
ret = boottime->set_timer(event, EFI_TIMER_PERIODIC, 250000);
if (ret != EFI_SUCCESS) {
efi_st_error("Could not set timer\n");
return EFI_ST_FAILURE;
}
- con_out->set_cursor_position(con_out, 0, 0);
- con_out->set_attribute(con_out, EFI_WHITE | EFI_BACKGROUND_BLUE);
efi_st_printf("The submarine should have three yellow port holes.\n");
- efi_st_printf("Press any key to continue");
- efi_st_get_key();
+ efi_st_printf("UP, DOWN to navigate, any other key to quit");
+ for (;;) {
+ struct efi_input_key input_key;
+
+ ret = boottime->check_event(con_in->wait_for_key);
+ if (ret == EFI_NOT_READY)
+ continue;
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("CheckEvent failed %x\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ ret = con_in->read_key_stroke(con_in, &input_key);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Key not available %x\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+ switch (input_key.scan_code) {
+ case 0x01: /* UP */
+ if (pos.redrawn && pos.y >= 5) {
+ pos.y -= 5;
+ pos.redrawn = 0;
+ }
+ continue;
+ case 0x02: /* DOWN */
+ if (pos.redrawn &&
+ pos.y + HEIGHT + 5 < gop->mode->info->height) {
+ pos.y += 5;
+ pos.redrawn = 0;
+ }
+ continue;
+ }
+ break;
+ }
con_out->set_attribute(con_out, EFI_LIGHTGRAY);
- efi_st_printf("\n");
+ con_out->clear_screen(con_out);
return EFI_ST_SUCCESS;
}
diff --git a/lib/lmb.c b/lib/lmb.c
index b2c233edb6..da924c6789 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -74,6 +74,16 @@ static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1,
return 0;
}
+static long lmb_regions_overlap(struct lmb_region *rgn, unsigned long r1,
+ unsigned long r2)
+{
+ phys_addr_t base1 = rgn->region[r1].base;
+ phys_size_t size1 = rgn->region[r1].size;
+ phys_addr_t base2 = rgn->region[r2].base;
+ phys_size_t size2 = rgn->region[r2].size;
+
+ return lmb_addrs_overlap(base1, size1, base2, size2);
+}
static long lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1,
unsigned long r2)
{
@@ -81,7 +91,6 @@ static long lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1,
phys_size_t size1 = rgn->region[r1].size;
phys_addr_t base2 = rgn->region[r2].base;
phys_size_t size2 = rgn->region[r2].size;
-
return lmb_addrs_adjacent(base1, size1, base2, size2);
}
@@ -105,6 +114,23 @@ static void lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1,
lmb_remove_region(rgn, r2);
}
+/*Assumption : base addr of region 1 < base addr of region 2*/
+static void lmb_fix_over_lap_regions(struct lmb_region *rgn, unsigned long r1,
+ unsigned long r2)
+{
+ phys_addr_t base1 = rgn->region[r1].base;
+ phys_size_t size1 = rgn->region[r1].size;
+ phys_addr_t base2 = rgn->region[r2].base;
+ phys_size_t size2 = rgn->region[r2].size;
+
+ if (base1 + size1 > base2 + size2) {
+ printf("This will not be a case any time\n");
+ return;
+ }
+ rgn->region[r1].size = base2 + size2 - base1;
+ lmb_remove_region(rgn, r2);
+}
+
void lmb_init(struct lmb *lmb)
{
#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
@@ -249,7 +275,6 @@ static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
phys_size_t rgnflags = rgn->region[i].flags;
phys_addr_t end = base + size - 1;
phys_addr_t rgnend = rgnbase + rgnsize - 1;
-
if (rgnbase <= base && end <= rgnend) {
if (flags == rgnflags)
/* Already have this region, so we're done */
@@ -278,10 +303,14 @@ static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
}
}
- if ((i < rgn->cnt - 1) && lmb_regions_adjacent(rgn, i, i + 1)) {
- if (rgn->region[i].flags == rgn->region[i + 1].flags) {
+ if (i < rgn->cnt - 1 && rgn->region[i].flags == rgn->region[i + 1].flags) {
+ if (lmb_regions_adjacent(rgn, i, i + 1)) {
lmb_coalesce_regions(rgn, i, i + 1);
coalesced++;
+ } else if (lmb_regions_overlap(rgn, i, i + 1)) {
+ /* fix overlapping area */
+ lmb_fix_over_lap_regions(rgn, i, i + 1);
+ coalesced++;
}
}
diff --git a/lib/of_live.c b/lib/of_live.c
index 25f7af6106..812c488f60 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -8,13 +8,21 @@
* Copyright (c) 2017 Google, Inc
*/
+#define LOG_CATEGORY LOGC_DT
+
#include <common.h>
+#include <abuf.h>
#include <log.h>
#include <linux/libfdt.h>
#include <of_live.h>
#include <malloc.h>
#include <dm/of_access.h>
#include <linux/err.h>
+#include <linux/sizes.h>
+
+enum {
+ BUF_STEP = SZ_64K,
+};
static void *unflatten_dt_alloc(void **mem, unsigned long size,
unsigned long align)
@@ -336,3 +344,136 @@ void of_live_free(struct device_node *root)
/* the tree is stored as a contiguous block of memory */
free(root);
}
+
+int of_live_create_empty(struct device_node **rootp)
+{
+ struct device_node *root;
+
+ root = calloc(1, sizeof(struct device_node));
+ if (!root)
+ return -ENOMEM;
+ root->name = strdup("");
+ if (!root->name) {
+ free(root);
+ return -ENOMEM;
+ }
+ root->type = "<NULL>";
+ root->full_name = "";
+ *rootp = root;
+
+ return 0;
+}
+
+static int check_space(int ret, struct abuf *buf)
+{
+ if (ret == -FDT_ERR_NOSPACE) {
+ if (!abuf_realloc_inc(buf, BUF_STEP))
+ return log_msg_ret("spc", -ENOMEM);
+ ret = fdt_resize(abuf_data(buf), abuf_data(buf),
+ abuf_size(buf));
+ if (ret)
+ return log_msg_ret("res", -EFAULT);
+
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+/**
+ * flatten_node() - Write out the node and its properties into a flat tree
+ */
+static int flatten_node(struct abuf *buf, const struct device_node *node)
+{
+ const struct device_node *np;
+ const struct property *pp;
+ int ret;
+
+ ret = fdt_begin_node(abuf_data(buf), node->name);
+ ret = check_space(ret, buf);
+ if (ret == -EAGAIN) {
+ ret = fdt_begin_node(abuf_data(buf), node->name);
+ if (ret) {
+ log_debug("Internal error a %d\n", ret);
+ return -EFAULT;
+ }
+ }
+ if (ret)
+ return log_msg_ret("beg", ret);
+
+ /* First write out the properties */
+ for (pp = node->properties; !ret && pp; pp = pp->next) {
+ ret = fdt_property(abuf_data(buf), pp->name, pp->value,
+ pp->length);
+ ret = check_space(ret, buf);
+ if (ret == -EAGAIN) {
+ ret = fdt_property(abuf_data(buf), pp->name, pp->value,
+ pp->length);
+ }
+ }
+
+ /* Next write out the subnodes */
+ for (np = node->child; np; np = np->sibling) {
+ ret = flatten_node(buf, np);
+ if (ret)
+ return log_msg_ret("sub", ret);
+ }
+
+ ret = fdt_end_node(abuf_data(buf));
+ ret = check_space(ret, buf);
+ if (ret == -EAGAIN) {
+ ret = fdt_end_node(abuf_data(buf));
+ if (ret) {
+ log_debug("Internal error b %d\n", ret);
+ return -EFAULT;
+ }
+ }
+ if (ret)
+ return log_msg_ret("end", ret);
+
+ return 0;
+}
+
+int of_live_flatten(const struct device_node *root, struct abuf *buf)
+{
+ int ret;
+
+ abuf_init(buf);
+ if (!abuf_realloc(buf, BUF_STEP))
+ return log_msg_ret("ini", -ENOMEM);
+
+ ret = fdt_create(abuf_data(buf), abuf_size(buf));
+ if (!ret)
+ ret = fdt_finish_reservemap(abuf_data(buf));
+ if (ret) {
+ log_debug("Failed to start FDT (err=%d)\n", ret);
+ return log_msg_ret("sta", -EINVAL);
+ }
+
+ ret = flatten_node(buf, root);
+ if (ret)
+ return log_msg_ret("flt", ret);
+
+ ret = fdt_finish(abuf_data(buf));
+ ret = check_space(ret, buf);
+ if (ret == -EAGAIN) {
+ ret = fdt_finish(abuf_data(buf));
+ if (ret) {
+ log_debug("Internal error c %d\n", ret);
+ return -EFAULT;
+ }
+ }
+ if (ret)
+ return log_msg_ret("fin", ret);
+
+ ret = fdt_pack(abuf_data(buf));
+ if (ret) {
+ log_debug("Failed to pack (err=%d)\n", ret);
+ return log_msg_ret("pac", -EFAULT);
+ }
+
+ if (!abuf_realloc(buf, fdt_totalsize(abuf_data(buf))))
+ return log_msg_ret("abu", -EFAULT);
+
+ return 0;
+}