diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 6 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/asm-offsets.c | 2 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_bitblt.c | 83 | ||||
-rw-r--r-- | lib/lmb.c | 37 | ||||
-rw-r--r-- | lib/of_live.c | 141 |
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; } @@ -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; +} |