diff --git a/MAINTAINERS b/MAINTAINERS index 85babd1908..ed5e354873 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -959,6 +959,7 @@ SANDBOX M: Simon Glass S: Maintained F: arch/sandbox/ +F: doc/arch/sandbox.rst SH M: Marek Vasut diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c index 6416cab96c..7dc3dab32e 100644 --- a/arch/sandbox/cpu/sdl.c +++ b/arch/sandbox/cpu/sdl.c @@ -172,33 +172,7 @@ int sandbox_sdl_sync(void *lcd_base) } static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = { - [SDL_SCANCODE_A] = KEY_A, - [SDL_SCANCODE_B] = KEY_B, - [SDL_SCANCODE_C] = KEY_C, - [SDL_SCANCODE_D] = KEY_D, - [SDL_SCANCODE_E] = KEY_E, - [SDL_SCANCODE_F] = KEY_F, - [SDL_SCANCODE_G] = KEY_G, - [SDL_SCANCODE_H] = KEY_H, - [SDL_SCANCODE_I] = KEY_I, - [SDL_SCANCODE_J] = KEY_J, - [SDL_SCANCODE_K] = KEY_K, - [SDL_SCANCODE_L] = KEY_L, - [SDL_SCANCODE_M] = KEY_M, - [SDL_SCANCODE_N] = KEY_N, - [SDL_SCANCODE_O] = KEY_O, - [SDL_SCANCODE_P] = KEY_P, - [SDL_SCANCODE_Q] = KEY_Q, - [SDL_SCANCODE_R] = KEY_R, - [SDL_SCANCODE_S] = KEY_S, - [SDL_SCANCODE_T] = KEY_T, - [SDL_SCANCODE_U] = KEY_U, - [SDL_SCANCODE_V] = KEY_V, - [SDL_SCANCODE_W] = KEY_W, - [SDL_SCANCODE_X] = KEY_X, - [SDL_SCANCODE_Y] = KEY_Y, - [SDL_SCANCODE_Z] = KEY_Z, - + [SDL_SCANCODE_ESCAPE] = KEY_ESC, [SDL_SCANCODE_1] = KEY_1, [SDL_SCANCODE_2] = KEY_2, [SDL_SCANCODE_3] = KEY_3, @@ -209,25 +183,53 @@ static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = { [SDL_SCANCODE_8] = KEY_8, [SDL_SCANCODE_9] = KEY_9, [SDL_SCANCODE_0] = KEY_0, - - [SDL_SCANCODE_RETURN] = KEY_ENTER, - [SDL_SCANCODE_ESCAPE] = KEY_ESC, - [SDL_SCANCODE_BACKSPACE] = KEY_BACKSPACE, - [SDL_SCANCODE_TAB] = KEY_TAB, - [SDL_SCANCODE_SPACE] = KEY_SPACE, - [SDL_SCANCODE_MINUS] = KEY_MINUS, [SDL_SCANCODE_EQUALS] = KEY_EQUAL, - [SDL_SCANCODE_BACKSLASH] = KEY_BACKSLASH, + [SDL_SCANCODE_BACKSPACE] = KEY_BACKSPACE, + [SDL_SCANCODE_TAB] = KEY_TAB, + [SDL_SCANCODE_Q] = KEY_Q, + [SDL_SCANCODE_W] = KEY_W, + [SDL_SCANCODE_E] = KEY_E, + [SDL_SCANCODE_R] = KEY_R, + [SDL_SCANCODE_T] = KEY_T, + [SDL_SCANCODE_Y] = KEY_Y, + [SDL_SCANCODE_U] = KEY_U, + [SDL_SCANCODE_I] = KEY_I, + [SDL_SCANCODE_O] = KEY_O, + [SDL_SCANCODE_P] = KEY_P, + [SDL_SCANCODE_LEFTBRACKET] = KEY_LEFTBRACE, + [SDL_SCANCODE_RIGHTBRACKET] = KEY_RIGHTBRACE, + [SDL_SCANCODE_RETURN] = KEY_ENTER, + [SDL_SCANCODE_LCTRL] = KEY_LEFTCTRL, + [SDL_SCANCODE_A] = KEY_A, + [SDL_SCANCODE_S] = KEY_S, + [SDL_SCANCODE_D] = KEY_D, + [SDL_SCANCODE_F] = KEY_F, + [SDL_SCANCODE_G] = KEY_G, + [SDL_SCANCODE_H] = KEY_H, + [SDL_SCANCODE_J] = KEY_J, + [SDL_SCANCODE_K] = KEY_K, + [SDL_SCANCODE_L] = KEY_L, [SDL_SCANCODE_SEMICOLON] = KEY_SEMICOLON, [SDL_SCANCODE_APOSTROPHE] = KEY_APOSTROPHE, [SDL_SCANCODE_GRAVE] = KEY_GRAVE, + [SDL_SCANCODE_LSHIFT] = KEY_LEFTSHIFT, + [SDL_SCANCODE_BACKSLASH] = KEY_BACKSLASH, + [SDL_SCANCODE_Z] = KEY_Z, + [SDL_SCANCODE_X] = KEY_X, + [SDL_SCANCODE_C] = KEY_C, + [SDL_SCANCODE_V] = KEY_V, + [SDL_SCANCODE_B] = KEY_B, + [SDL_SCANCODE_N] = KEY_N, + [SDL_SCANCODE_M] = KEY_M, [SDL_SCANCODE_COMMA] = KEY_COMMA, [SDL_SCANCODE_PERIOD] = KEY_DOT, [SDL_SCANCODE_SLASH] = KEY_SLASH, - + [SDL_SCANCODE_RSHIFT] = KEY_RIGHTSHIFT, + [SDL_SCANCODE_KP_MULTIPLY] = KEY_KPASTERISK, + [SDL_SCANCODE_LALT] = KEY_LEFTALT, + [SDL_SCANCODE_SPACE] = KEY_SPACE, [SDL_SCANCODE_CAPSLOCK] = KEY_CAPSLOCK, - [SDL_SCANCODE_F1] = KEY_F1, [SDL_SCANCODE_F2] = KEY_F2, [SDL_SCANCODE_F3] = KEY_F3, @@ -238,45 +240,65 @@ static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = { [SDL_SCANCODE_F8] = KEY_F8, [SDL_SCANCODE_F9] = KEY_F9, [SDL_SCANCODE_F10] = KEY_F10, - [SDL_SCANCODE_F11] = KEY_F11, - [SDL_SCANCODE_F12] = KEY_F12, - - [SDL_SCANCODE_PRINTSCREEN] = KEY_PRINT, - [SDL_SCANCODE_SCROLLLOCK] = KEY_SCROLLLOCK, - [SDL_SCANCODE_PAUSE] = KEY_PAUSE, - [SDL_SCANCODE_INSERT] = KEY_INSERT, - [SDL_SCANCODE_HOME] = KEY_HOME, - [SDL_SCANCODE_PAGEUP] = KEY_PAGEUP, - [SDL_SCANCODE_DELETE] = KEY_DELETE, - [SDL_SCANCODE_END] = KEY_END, - [SDL_SCANCODE_PAGEDOWN] = KEY_PAGEDOWN, - [SDL_SCANCODE_RIGHT] = KEY_RIGHT, - [SDL_SCANCODE_LEFT] = KEY_LEFT, - [SDL_SCANCODE_DOWN] = KEY_DOWN, - [SDL_SCANCODE_UP] = KEY_UP, - [SDL_SCANCODE_NUMLOCKCLEAR] = KEY_NUMLOCK, - [SDL_SCANCODE_KP_DIVIDE] = KEY_KPSLASH, - [SDL_SCANCODE_KP_MULTIPLY] = KEY_KPASTERISK, - [SDL_SCANCODE_KP_MINUS] = KEY_KPMINUS, - [SDL_SCANCODE_KP_PLUS] = KEY_KPPLUS, - [SDL_SCANCODE_KP_ENTER] = KEY_KPENTER, - [SDL_SCANCODE_KP_1] = KEY_KP1, - [SDL_SCANCODE_KP_2] = KEY_KP2, - [SDL_SCANCODE_KP_3] = KEY_KP3, - [SDL_SCANCODE_KP_4] = KEY_KP4, - [SDL_SCANCODE_KP_5] = KEY_KP5, - [SDL_SCANCODE_KP_6] = KEY_KP6, + [SDL_SCANCODE_SCROLLLOCK] = KEY_SCROLLLOCK, [SDL_SCANCODE_KP_7] = KEY_KP7, [SDL_SCANCODE_KP_8] = KEY_KP8, [SDL_SCANCODE_KP_9] = KEY_KP9, + [SDL_SCANCODE_KP_MINUS] = KEY_KPMINUS, + [SDL_SCANCODE_KP_4] = KEY_KP4, + [SDL_SCANCODE_KP_5] = KEY_KP5, + [SDL_SCANCODE_KP_6] = KEY_KP6, + [SDL_SCANCODE_KP_PLUS] = KEY_KPPLUS, + [SDL_SCANCODE_KP_1] = KEY_KP1, + [SDL_SCANCODE_KP_2] = KEY_KP2, + [SDL_SCANCODE_KP_3] = KEY_KP3, [SDL_SCANCODE_KP_0] = KEY_KP0, [SDL_SCANCODE_KP_PERIOD] = KEY_KPDOT, - - [SDL_SCANCODE_KP_EQUALS] = KEY_KPEQUAL, - [SDL_SCANCODE_KP_COMMA] = KEY_KPCOMMA, - + /* key 84 does not exist linux_input.h */ + [SDL_SCANCODE_LANG5] = KEY_ZENKAKUHANKAKU, + [SDL_SCANCODE_NONUSBACKSLASH] = KEY_102ND, + [SDL_SCANCODE_F11] = KEY_F11, + [SDL_SCANCODE_F12] = KEY_F12, + [SDL_SCANCODE_INTERNATIONAL1] = KEY_RO, + [SDL_SCANCODE_LANG3] = KEY_KATAKANA, + [SDL_SCANCODE_LANG4] = KEY_HIRAGANA, + [SDL_SCANCODE_INTERNATIONAL4] = KEY_HENKAN, + [SDL_SCANCODE_INTERNATIONAL2] = KEY_KATAKANAHIRAGANA, + [SDL_SCANCODE_INTERNATIONAL5] = KEY_MUHENKAN, + /* [SDL_SCANCODE_INTERNATIONAL5] -> [KEY_KPJPCOMMA] */ + [SDL_SCANCODE_KP_ENTER] = KEY_KPENTER, + [SDL_SCANCODE_RCTRL] = KEY_RIGHTCTRL, + [SDL_SCANCODE_KP_DIVIDE] = KEY_KPSLASH, [SDL_SCANCODE_SYSREQ] = KEY_SYSRQ, + [SDL_SCANCODE_RALT] = KEY_RIGHTALT, + /* KEY_LINEFEED */ + [SDL_SCANCODE_HOME] = KEY_HOME, + [SDL_SCANCODE_UP] = KEY_UP, + [SDL_SCANCODE_PAGEUP] = KEY_PAGEUP, + [SDL_SCANCODE_LEFT] = KEY_LEFT, + [SDL_SCANCODE_RIGHT] = KEY_RIGHT, + [SDL_SCANCODE_END] = KEY_END, + [SDL_SCANCODE_DOWN] = KEY_DOWN, + [SDL_SCANCODE_PAGEDOWN] = KEY_PAGEDOWN, + [SDL_SCANCODE_INSERT] = KEY_INSERT, + [SDL_SCANCODE_DELETE] = KEY_DELETE, + /* KEY_MACRO */ + [SDL_SCANCODE_MUTE] = KEY_MUTE, + [SDL_SCANCODE_VOLUMEDOWN] = KEY_VOLUMEDOWN, + [SDL_SCANCODE_VOLUMEUP] = KEY_VOLUMEUP, + [SDL_SCANCODE_POWER] = KEY_POWER, + [SDL_SCANCODE_KP_EQUALS] = KEY_KPEQUAL, + [SDL_SCANCODE_KP_PLUSMINUS] = KEY_KPPLUSMINUS, + [SDL_SCANCODE_PAUSE] = KEY_PAUSE, + /* KEY_SCALE */ + [SDL_SCANCODE_KP_COMMA] = KEY_KPCOMMA, + [SDL_SCANCODE_LANG1] = KEY_HANGUEL, + [SDL_SCANCODE_LANG2] = KEY_HANJA, + [SDL_SCANCODE_INTERNATIONAL3] = KEY_YEN, + [SDL_SCANCODE_LGUI] = KEY_LEFTMETA, + [SDL_SCANCODE_RGUI] = KEY_RIGHTMETA, + [SDL_SCANCODE_APPLICATION] = KEY_COMPOSE, }; int sandbox_sdl_scan_keys(int key[], int max_keys) diff --git a/arch/sandbox/dts/cros-ec-keyboard.dtsi b/arch/sandbox/dts/cros-ec-keyboard.dtsi index 9c7fb0acae..d885a5ecd2 100644 --- a/arch/sandbox/dts/cros-ec-keyboard.dtsi +++ b/arch/sandbox/dts/cros-ec-keyboard.dtsi @@ -1,12 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Keyboard dts fragment for devices that use cros-ec-keyboard * * Copyright (c) 2014 Google, Inc * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ + * This file is taken from Linux + * arch/arm/boot/dts/cros-ec-keyboard.dtsi. + * + * A duplicate KEY_BACKSLASH key had to be removed. + */ #include @@ -22,6 +24,7 @@ MATRIX_KEY(0x00, 0x02, KEY_F1) MATRIX_KEY(0x00, 0x03, KEY_B) MATRIX_KEY(0x00, 0x04, KEY_F10) + MATRIX_KEY(0x00, 0x05, KEY_RO) MATRIX_KEY(0x00, 0x06, KEY_N) MATRIX_KEY(0x00, 0x08, KEY_EQUAL) MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT) @@ -34,6 +37,7 @@ MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE) MATRIX_KEY(0x01, 0x09, KEY_F9) MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE) + MATRIX_KEY(0x01, 0x0c, KEY_HENKAN) MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL) MATRIX_KEY(0x02, 0x01, KEY_TAB) @@ -45,6 +49,7 @@ MATRIX_KEY(0x02, 0x07, KEY_102ND) MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE) MATRIX_KEY(0x02, 0x09, KEY_F8) + MATRIX_KEY(0x02, 0x0a, KEY_YEN) MATRIX_KEY(0x03, 0x01, KEY_GRAVE) MATRIX_KEY(0x03, 0x02, KEY_F2) @@ -52,7 +57,9 @@ MATRIX_KEY(0x03, 0x04, KEY_F5) MATRIX_KEY(0x03, 0x06, KEY_6) MATRIX_KEY(0x03, 0x08, KEY_MINUS) + MATRIX_KEY(0x03, 0x09, KEY_F13) MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH) + MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN) MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL) MATRIX_KEY(0x04, 0x01, KEY_A) @@ -63,7 +70,10 @@ MATRIX_KEY(0x04, 0x06, KEY_J) MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON) MATRIX_KEY(0x04, 0x09, KEY_L) - MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH) + /* + * Do not map any key twice + * MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH) + */ MATRIX_KEY(0x04, 0x0b, KEY_ENTER) MATRIX_KEY(0x05, 0x01, KEY_Z) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e6da47d592..cc372806a0 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -131,6 +131,7 @@ str-value = "test string"; interrupts-extended = <&irq 3 0>; acpi,name = "GHIJ"; + phandle-value = <&gpio_c 10>, <0xFFFFFFFF 20>, <&gpio_a 30>; }; junk { diff --git a/arch/x86/cpu/intel_common/acpi.c b/arch/x86/cpu/intel_common/acpi.c index a4d5fbd38a..4496bbfd99 100644 --- a/arch/x86/cpu/intel_common/acpi.c +++ b/arch/x86/cpu/intel_common/acpi.c @@ -198,7 +198,7 @@ int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx) struct acpi_global_nvs *gnvs; int ret; - ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs), + ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs), 0, (void **)&gnvs); if (ret) return log_msg_ret("bloblist", ret); diff --git a/arch/x86/cpu/intel_common/intel_opregion.c b/arch/x86/cpu/intel_common/intel_opregion.c index 4e6c64d9aa..c95ae04992 100644 --- a/arch/x86/cpu/intel_common/intel_opregion.c +++ b/arch/x86/cpu/intel_common/intel_opregion.c @@ -108,7 +108,7 @@ int intel_gma_init_igd_opregion(struct udevice *dev, struct optionrom_vbt *ext_vbt; ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT, - vbt->hdr_vbt_size, + vbt->hdr_vbt_size, 0, (void **)&ext_vbt); if (ret) { log_err("GMA: Unable to add Ext VBT to bloblist\n"); diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 3b677d339b..03a19af930 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -314,7 +314,7 @@ static int board_check_usb_power(void) * for each of them */ adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd", - "#io-channel-cells"); + "#io-channel-cells", 0); if (adc_count < 0) { if (adc_count == -ENOENT) return 0; diff --git a/cmd/Kconfig b/cmd/Kconfig index 999b6cf239..b25d2b02ed 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -631,6 +631,15 @@ config CMD_BINOP Compute binary operations (xor, or, and) of byte arrays of arbitrary size from memory and store the result in memory or the environment. +config CMD_BLOBLIST + bool "bloblist" + default y if BLOBLIST + help + Show information about the bloblist, a collection of binary blobs + held in memory that persist between SPL and U-Boot. In the case of + x86 devices the bloblist can be used to hold ACPI tables so that they + remain available in memory. + config CMD_CRC32 bool "crc32" default y diff --git a/cmd/Makefile b/cmd/Makefile index c7a08ed109..015b83764c 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BDI) += bdinfo.o obj-$(CONFIG_CMD_BEDBUG) += bedbug.o obj-$(CONFIG_CMD_BIND) += bind.o obj-$(CONFIG_CMD_BINOP) += binop.o +obj-$(CONFIG_CMD_BLOBLIST) += bloblist.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o diff --git a/cmd/bloblist.c b/cmd/bloblist.c new file mode 100644 index 0000000000..bb2e682ff8 --- /dev/null +++ b/cmd/bloblist.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Command-line access to bloblist features + * + * Copyright 2020 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static int do_bloblist_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bloblist_show_stats(); + + return 0; +} + +static int do_bloblist_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bloblist_show_list(); + + return 0; +} + +static char bloblist_help_text[] = + "info - show information about the bloblist\n" + "bloblist list - list blobs in the bloblist"; + +U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text, + U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info), + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_bloblist_list)); diff --git a/common/bloblist.c b/common/bloblist.c index 99501951e0..33b5862380 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -11,17 +11,47 @@ #include #include +/* + * A bloblist is a single contiguous chunk of memory with a header + * (struct bloblist_hdr) and a number of blobs in it. + * + * Each blob starts on a BLOBLIST_ALIGN boundary relative to the start of the + * bloblist and consists of a struct bloblist_rec, some padding to the required + * alignment for the blog and then the actual data. The padding ensures that the + * start address of the data in each blob is aligned as required. Note that + * each blob's *data* is aligned to BLOBLIST_ALIGN regardless of the alignment + * of the bloblist itself or the blob header. + * + * So far, only BLOBLIST_ALIGN alignment is supported. + */ + DECLARE_GLOBAL_DATA_PTR; -struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr) +static const char *const tag_name[] = { + [BLOBLISTT_NONE] = "(none)", + [BLOBLISTT_EC_HOSTEVENT] = "EC host event", + [BLOBLISTT_SPL_HANDOFF] = "SPL hand-off", + [BLOBLISTT_VBOOT_CTX] = "Chrome OS vboot context", + [BLOBLISTT_VBOOT_HANDOFF] = "Chrome OS vboot hand-off", +}; + +const char *bloblist_tag_name(enum bloblist_tag_t tag) +{ + if (tag < 0 || tag >= BLOBLISTT_COUNT) + return "invalid"; + + return tag_name[tag]; +} + +static struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr) { if (hdr->alloced <= hdr->hdr_size) return NULL; return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size); } -struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr, - struct bloblist_rec *rec) +static struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr, + struct bloblist_rec *rec) { ulong offset; @@ -53,13 +83,25 @@ static struct bloblist_rec *bloblist_findrec(uint tag) return NULL; } -static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp) +static int bloblist_addrec(uint tag, int size, int align, + struct bloblist_rec **recp) { struct bloblist_hdr *hdr = gd->bloblist; struct bloblist_rec *rec; - int new_alloced; + int data_start, new_alloced; + + if (!align) + align = BLOBLIST_ALIGN; + + /* Figure out where the new data will start */ + data_start = map_to_sysmem(hdr) + hdr->alloced + sizeof(*rec); + + /* Align the address and then calculate the offset from ->alloced */ + data_start = ALIGN(data_start, align) - map_to_sysmem(hdr); + + /* Calculate the new allocated total */ + new_alloced = data_start + ALIGN(size, align); - new_alloced = hdr->alloced + sizeof(*rec) + ALIGN(size, BLOBLIST_ALIGN); if (new_alloced >= hdr->size) { log(LOGC_BLOBLIST, LOGL_ERR, "Failed to allocate %x bytes size=%x, need size=%x\n", @@ -67,21 +109,23 @@ static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp) return log_msg_ret("bloblist add", -ENOSPC); } rec = (void *)hdr + hdr->alloced; - hdr->alloced = new_alloced; rec->tag = tag; - rec->hdr_size = sizeof(*rec); + rec->hdr_size = data_start - hdr->alloced; rec->size = size; rec->spare = 0; /* Zero the record data */ - memset(rec + 1, '\0', rec->size); + memset((void *)rec + rec->hdr_size, '\0', rec->size); + + hdr->alloced = new_alloced; *recp = rec; return 0; } -static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size) +static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size, + int align) { struct bloblist_rec *rec; @@ -94,7 +138,7 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size) } else { int ret; - ret = bloblist_addrec(tag, size, &rec); + ret = bloblist_addrec(tag, size, align, &rec); if (ret) return ret; } @@ -116,22 +160,22 @@ void *bloblist_find(uint tag, int size) return (void *)rec + rec->hdr_size; } -void *bloblist_add(uint tag, int size) +void *bloblist_add(uint tag, int size, int align) { struct bloblist_rec *rec; - if (bloblist_addrec(tag, size, &rec)) + if (bloblist_addrec(tag, size, align, &rec)) return NULL; - return rec + 1; + return (void *)rec + rec->hdr_size; } -int bloblist_ensure_size(uint tag, int size, void **blobp) +int bloblist_ensure_size(uint tag, int size, int align, void **blobp) { struct bloblist_rec *rec; int ret; - ret = bloblist_ensurerec(tag, &rec, size); + ret = bloblist_ensurerec(tag, &rec, size, align); if (ret) return ret; *blobp = (void *)rec + rec->hdr_size; @@ -143,7 +187,7 @@ void *bloblist_ensure(uint tag, int size) { struct bloblist_rec *rec; - if (bloblist_ensurerec(tag, &rec, size)) + if (bloblist_ensurerec(tag, &rec, size, 0)) return NULL; return (void *)rec + rec->hdr_size; @@ -154,7 +198,7 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp) struct bloblist_rec *rec; int ret; - ret = bloblist_ensurerec(tag, &rec, *sizep); + ret = bloblist_ensurerec(tag, &rec, *sizep, 0); if (ret == -ESPIPE) *sizep = rec->size; else if (ret) @@ -233,6 +277,46 @@ int bloblist_finish(void) return 0; } +void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp) +{ + struct bloblist_hdr *hdr = gd->bloblist; + + *basep = map_to_sysmem(gd->bloblist); + *sizep = hdr->size; + *allocedp = hdr->alloced; +} + +static void show_value(const char *prompt, ulong value) +{ + printf("%s:%*s %-5lx ", prompt, 8 - (int)strlen(prompt), "", value); + print_size(value, "\n"); +} + +void bloblist_show_stats(void) +{ + ulong base, size, alloced; + + bloblist_get_stats(&base, &size, &alloced); + printf("base: %lx\n", base); + show_value("size", size); + show_value("alloced", alloced); + show_value("free", size - alloced); +} + +void bloblist_show_list(void) +{ + struct bloblist_hdr *hdr = gd->bloblist; + struct bloblist_rec *rec; + + printf("%-8s %8s Tag Name\n", "Address", "Size"); + for (rec = bloblist_first_blob(hdr); rec; + rec = bloblist_next_blob(hdr, rec)) { + printf("%08lx %8x %3d %s\n", + (ulong)map_to_sysmem((void *)rec + rec->hdr_size), + rec->size, rec->tag, bloblist_tag_name(rec->tag)); + } +} + int bloblist_init(void) { bool expected; diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst index 360f22461a..4674c420ac 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -97,30 +97,39 @@ Command-line Options -------------------- Various options are available, mostly for test purposes. Use -h to see -available options. Some of these are described below. +available options. Some of these are described below: -The terminal is normally in what is called 'raw-with-sigs' mode. This means -that you can use arrow keys for command editing and history, but if you -press Ctrl-C, U-Boot will exit instead of handling this as a keypress. +* -t, --terminal + - The terminal is normally in what is called 'raw-with-sigs' mode. This means + that you can use arrow keys for command editing and history, but if you + press Ctrl-C, U-Boot will exit instead of handling this as a keypress. + Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked' + (where the terminal is in cooked mode and cursor keys will not work, Ctrl-C + will exit). -Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked' -(where the terminal is in cooked mode and cursor keys will not work, Ctrl-C -will exit). +* -l + - Show the LCD emulation window. -As mentioned above, -l causes the LCD emulation window to be shown. +* -d + - A device tree binary file can be provided with -d. If you edit the source + (it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to + recreate the binary file. -A device tree binary file can be provided with -d. If you edit the source -(it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to -recreate the binary file. +* -D + - To use the default device tree, use -D. -To use the default device tree, use -D. To use the test device tree, use -T. +* -T + - To use the test device tree, use -T. -To execute commands directly, use the -c option. You can specify a single -command, or multiple commands separated by a semicolon, as is normal in -U-Boot. Be careful with quoting as the shell will normally process and -swallow quotes. When -c is used, U-Boot exits after the command is complete, -but you can force it to go to interactive mode instead with -i. +* -c [;] + - To execute commands directly, use the -c option. You can specify a single + command, or multiple commands separated by a semicolon, as is normal in + U-Boot. Be careful with quoting as the shell will normally process and + swallow quotes. When -c is used, U-Boot exits after the command is complete, + but you can force it to go to interactive mode instead with -i. +* -i + - Go to interactive mode after executing the commands specified by -c. Memory Emulation ---------------- diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 4076535271..31c5997aea 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -161,7 +161,7 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) bulk->count = 0; - count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0); if (count < 1) return count; @@ -213,7 +213,7 @@ static int clk_set_default_parents(struct udevice *dev, int stage) int ret; num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents", - "#clock-cells"); + "#clock-cells", 0); if (num_parents < 0) { debug("%s: could not read assigned-clock-parents for %p\n", __func__, dev); diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index bcf1644d05..0a12e9b26f 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -756,10 +756,11 @@ int of_parse_phandle_with_args(const struct device_node *np, } int of_count_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name) + const char *list_name, const char *cells_name, + int cell_count) { - return __of_parse_phandle_with_args(np, list_name, cells_name, 0, - -1, NULL); + return __of_parse_phandle_with_args(np, list_name, cells_name, + cell_count, -1, NULL); } static void of_alias_add(struct alias_prop *ap, struct device_node *np, diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 79fcdf5ce2..7d1b89514c 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -432,15 +432,15 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, } int ofnode_count_phandle_with_args(ofnode node, const char *list_name, - const char *cells_name) + const char *cells_name, int cell_count) { if (ofnode_is_np(node)) return of_count_phandle_with_args(ofnode_to_np(node), - list_name, cells_name); + list_name, cells_name, cell_count); else return fdtdec_parse_phandle_with_args(gd->fdt_blob, ofnode_to_offset(node), list_name, cells_name, - 0, -1, NULL); + cell_count, -1, NULL); } ofnode ofnode_path(const char *path) diff --git a/drivers/core/read.c b/drivers/core/read.c index 86f3f88170..076125824c 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -214,10 +214,11 @@ int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name, } int dev_count_phandle_with_args(const struct udevice *dev, - const char *list_name, const char *cells_name) + const char *list_name, const char *cells_name, + int cell_count) { return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name, - cells_name); + cells_name, cell_count); } int dev_read_addr_cells(const struct udevice *dev) diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 1c0e829407..4c19abbaf0 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -688,7 +688,8 @@ int designware_eth_probe(struct udevice *dev) int i, clock_nb; priv->clock_count = 0; - clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", + 0); if (clock_nb > 0) { priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), GFP_KERNEL); diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index 8f456f33d2..f344e94b43 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -214,7 +214,7 @@ int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk) if (!dev_read_prop(dev, "phys", NULL)) return 0; - count = dev_count_phandle_with_args(dev, "phys", "#phy-cells"); + count = dev_count_phandle_with_args(dev, "phys", "#phy-cells", 0); if (count < 1) return count; diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c index c2c7c3bd50..af829db9da 100644 --- a/drivers/power/domain/power-domain-uclass.c +++ b/drivers/power/domain/power-domain-uclass.c @@ -117,7 +117,7 @@ static int dev_power_domain_ctrl(struct udevice *dev, bool on) int i, count, ret = 0; count = dev_count_phandle_with_args(dev, "power-domains", - "#power-domain-cells"); + "#power-domain-cells", 0); for (i = 0; i < count; i++) { ret = power_domain_get_by_index(dev, &pd, i); if (ret) diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index e7e407ca35..071c389ca0 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -108,7 +108,8 @@ static int __reset_get_bulk(struct udevice *dev, ofnode node, bulk->count = 0; - count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells"); + count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells", + 0); if (count < 1) return count; diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 304a3437d5..c93a7051a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -86,7 +86,7 @@ static int ehci_usb_probe(struct udevice *dev) err = 0; priv->clock_count = 0; clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", - "#clock-cells"); + "#clock-cells", 0); if (clock_nb > 0) { priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), GFP_KERNEL); @@ -116,7 +116,7 @@ static int ehci_usb_probe(struct udevice *dev) priv->reset_count = 0; reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", - "#reset-cells"); + "#reset-cells", 0); if (reset_nb > 0) { priv->resets = devm_kcalloc(dev, reset_nb, sizeof(struct reset_ctl), diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 22e7b565b5..aa1eba262a 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -95,7 +95,8 @@ static int ohci_da8xx_probe(struct udevice *dev) err = 0; priv->clock_count = 0; - clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", + 0); if (clock_nb < 0) return clock_nb; diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index ed5e500b2c..ac9b7e1e3c 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -85,7 +85,8 @@ static int ohci_usb_probe(struct udevice *dev) err = 0; priv->clock_count = 0; - clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", + 0); if (clock_nb > 0) { priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), GFP_KERNEL); @@ -111,7 +112,8 @@ static int ohci_usb_probe(struct udevice *dev) } priv->reset_count = 0; - reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); + reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells", + 0); if (reset_nb > 0) { priv->resets = devm_kcalloc(dev, reset_nb, sizeof(struct reset_ctl), diff --git a/include/bloblist.h b/include/bloblist.h index 5784c2226e..2b4b669689 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -19,6 +19,7 @@ enum { BLOBLIST_ALIGN = 16, }; +/* Supported tags - add new ones to tag_name in bloblist.c */ enum bloblist_tag_t { BLOBLISTT_NONE = 0, @@ -35,6 +36,8 @@ enum bloblist_tag_t { BLOBLISTT_INTEL_VBT, /* Intel Video-BIOS table */ BLOBLISTT_TPM2_TCG_LOG, /* TPM v2 log space */ BLOBLISTT_TCPA_LOG, /* TPM log space */ + + BLOBLISTT_COUNT }; /** @@ -65,7 +68,7 @@ enum bloblist_tag_t { * the bloblist can grow up to this size. This starts out as * sizeof(bloblist_hdr) since we need at least that much space to store a * valid bloblist - * @spare: Space space + * @spare: Spare space (for future use) * @chksum: CRC32 for the entire bloblist allocated area. Since any of the * blobs can be altered after being created, this checksum is only valid * when the bloblist is finalised before jumping to the next stage of boot. @@ -112,7 +115,7 @@ struct bloblist_rec { * Searches the bloblist and returns the blob with the matching tag * * @tag: Tag to search for (enum bloblist_tag_t) - * @size: Expected size of the blob + * @size: Expected size of the blob, or 0 for any size * @return pointer to blob if found, or NULL if not found, or a blob was found * but it is the wrong size */ @@ -129,10 +132,11 @@ void *bloblist_find(uint tag, int size); * * @tag: Tag to add (enum bloblist_tag_t) * @size: Size of the blob + * @align: Alignment of the blob (in bytes), 0 for default * @return pointer to the newly added block, or NULL if there is not enough * space for the blob */ -void *bloblist_add(uint tag, int size); +void *bloblist_add(uint tag, int size, int align); /** * bloblist_ensure_size() - Find or add a blob @@ -142,10 +146,11 @@ void *bloblist_add(uint tag, int size); * @tag: Tag to add (enum bloblist_tag_t) * @size: Size of the blob * @blobp: Returns a pointer to blob on success + * @align: Alignment of the blob (in bytes), 0 for default * @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack * of space, or -ESPIPE it exists but has the wrong size */ -int bloblist_ensure_size(uint tag, int size, void **blobp); +int bloblist_ensure_size(uint tag, int size, int align, void **blobp); /** * bloblist_ensure() - Find or add a blob @@ -206,6 +211,35 @@ int bloblist_check(ulong addr, uint size); */ int bloblist_finish(void); +/** + * bloblist_get_stats() - Get information about the bloblist + * + * This returns useful information about the bloblist + */ +void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp); + +/** + * bloblist_show_stats() - Show information about the bloblist + * + * This shows useful information about the bloblist on the console + */ +void bloblist_show_stats(void); + +/** + * bloblist_show_list() - Show a list of blobs in the bloblist + * + * This shows a list of blobs, showing their address, size and tag. + */ +void bloblist_show_list(void); + +/** + * bloblist_tag_name() - Get the name for a tag + * + * @tag: Tag to check + * @return name of tag, or "invalid" if an invalid tag is provided + */ +const char *bloblist_tag_name(enum bloblist_tag_t tag); + /** * bloblist_init() - Init the bloblist system with a single bloblist * diff --git a/include/dm/of_access.h b/include/dm/of_access.h index 2fa65c9332..cc382b1671 100644 --- a/include/dm/of_access.h +++ b/include/dm/of_access.h @@ -450,6 +450,7 @@ int of_parse_phandle_with_args(const struct device_node *np, * @np: pointer to a device tree node containing a list * @list_name: property name that contains a list * @cells_name: property name that specifies phandles' arguments count + * @cells_count: Cell count to use if @cells_name is NULL * @return number of phandle found, -ENOENT if * @list_name does not exist, -EINVAL if a phandle was not found, * @cells_name could not be found, the arguments were truncated or there @@ -460,7 +461,8 @@ int of_parse_phandle_with_args(const struct device_node *np, * */ int of_count_phandle_with_args(const struct device_node *np, - const char *list_name, const char *cells_name); + const char *list_name, const char *cells_name, + int cells_count); /** * of_alias_scan() - Scan all properties of the 'aliases' node diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 8df2facf99..4b7af37056 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -10,6 +10,7 @@ /* TODO(sjg@chromium.org): Drop fdtdec.h include */ #include #include +#include /* Enable checks to protect against invalid calls */ #undef OF_CHECKS @@ -84,7 +85,7 @@ struct ofprop { }; /** - * _ofnode_to_np() - convert an ofnode to a live DT node pointer + * ofnode_to_np() - convert an ofnode to a live DT node pointer * * This cannot be called if the reference contains an offset. * @@ -127,7 +128,7 @@ static inline bool ofnode_valid(ofnode node) if (of_live_active()) return node.np != NULL; else - return node.of_offset != -1; + return node.of_offset >= 0; } /** @@ -182,8 +183,8 @@ static inline bool ofnode_is_np(ofnode node) * live tree is in use. */ assert(!ofnode_valid(node) || - (of_live_active() ? _ofnode_to_np(node) - : _ofnode_to_np(node))); + (of_live_active() ? ofnode_to_np(node) + : ofnode_to_np(node))); #endif return of_live_active() && ofnode_valid(node); } @@ -555,12 +556,13 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, * @node: device tree node containing a list * @list_name: property name that contains a list * @cells_name: property name that specifies phandles' arguments count + * @cells_count: Cell count to use if @cells_name is NULL * @return number of phandle on success, -ENOENT if @list_name does not * exist, -EINVAL if a phandle was not found, @cells_name could not * be found. */ int ofnode_count_phandle_with_args(ofnode node, const char *list_name, - const char *cells_name); + const char *cells_name, int cell_count); /** * ofnode_path() - find a node by full path diff --git a/include/dm/read.h b/include/dm/read.h index 67db94adfc..0585eb1228 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -429,12 +429,14 @@ int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name, * @dev: device whose node containing a list * @list_name: property name that contains a list * @cells_name: property name that specifies phandles' arguments count + * @cells_count: Cell count to use if @cells_name is NULL * @Returns number of phandle found on success, on error returns appropriate * errno value. */ int dev_count_phandle_with_args(const struct udevice *dev, - const char *list_name, const char *cells_name); + const char *list_name, const char *cells_name, + int cell_count); /** * dev_read_addr_cells() - Get the number of address cells for a device's node @@ -880,10 +882,10 @@ static inline int dev_read_phandle_with_args(const struct udevice *dev, } static inline int dev_count_phandle_with_args(const struct udevice *dev, - const char *list_name, const char *cells_name) + const char *list_name, const char *cells_name, int cell_count) { return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name, - cells_name); + cells_name, cell_count); } static inline int dev_read_addr_cells(const struct udevice *dev) diff --git a/include/test/ut.h b/include/test/ut.h index 3295cd4e54..3f2ee7514b 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -224,6 +224,19 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); } \ } +/* Assert that two addresses (converted from pointers) are equal */ +#define ut_asserteq_addr(expr1, expr2) { \ + ulong _val1 = map_to_sysmem(expr1); \ + ulong _val2 = map_to_sysmem(expr2); \ + \ + if (_val1 != _val2) { \ + ut_failf(uts, __FILE__, __LINE__, __func__, \ + #expr1 " = " #expr2, \ + "Expected %lx, got %lx", _val1, _val2); \ + return CMD_RET_FAILURE; \ + } \ +} + /* Assert that a pointer is NULL */ #define ut_assertnull(expr) { \ const void *_val = (expr); \ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b8fc5e2bff..ee1bd41b08 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -746,7 +746,7 @@ int fdtdec_parse_phandle_with_args(const void *blob, int src_node, if (cells_name || cur_index == index) { node = fdt_node_offset_by_phandle(blob, phandle); - if (!node) { + if (node < 0) { debug("%s: could not find phandle\n", fdt_get_name(blob, src_node, NULL)); diff --git a/test/bloblist.c b/test/bloblist.c index 4e537ee1b9..0bb9e2d81e 100644 --- a/test/bloblist.c +++ b/test/bloblist.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -24,10 +25,12 @@ enum { TEST_SIZE = 10, TEST_SIZE2 = 20, - TEST_SIZE_LARGE = 0xe0, + TEST_SIZE_LARGE = 0x3e0, TEST_ADDR = CONFIG_BLOBLIST_ADDR, - TEST_BLOBLIST_SIZE = 0x100, + TEST_BLOBLIST_SIZE = 0x400, + + ERASE_BYTE = '\xff', }; static struct bloblist_hdr *clear_bloblist(void) @@ -40,7 +43,7 @@ static struct bloblist_hdr *clear_bloblist(void) * to 0xff for testing purposes. */ hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE); - memset(hdr, '\xff', TEST_BLOBLIST_SIZE); + memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); memset(hdr, '\0', sizeof(*hdr)); return hdr; @@ -94,26 +97,27 @@ static int bloblist_test_blob(struct unit_test_state *uts) hdr = clear_bloblist(); ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + ut_asserteq(map_to_sysmem(hdr), TEST_ADDR); /* Add a record and check that we can find it */ - data = bloblist_add(TEST_TAG, TEST_SIZE); + data = bloblist_add(TEST_TAG, TEST_SIZE, 0); rec = (void *)(hdr + 1); - ut_asserteq_ptr(rec + 1, data); + ut_asserteq_addr(rec + 1, data); data = bloblist_find(TEST_TAG, TEST_SIZE); - ut_asserteq_ptr(rec + 1, data); + ut_asserteq_addr(rec + 1, data); /* Check the data is zeroed */ ut_assertok(check_zero(data, TEST_SIZE)); /* Check the 'ensure' method */ - ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); + ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2)); rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN)); ut_assertok(check_zero(data, TEST_SIZE)); /* Check for a non-existent record */ - ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); - ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2)); + ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); + ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2)); ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0)); return 0; @@ -139,7 +143,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts) /* Check that we get the same thing again */ ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2)); ut_asserteq(TEST_SIZE, size); - ut_asserteq_ptr(data, data2); + ut_asserteq_addr(data, data2); /* Check that the size remains the same */ size = TEST_SIZE2; @@ -163,8 +167,8 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts) ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); data = hdr + 1; data += sizeof(struct bloblist_rec); - ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); - ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); + ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); + ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); return 0; } @@ -202,10 +206,10 @@ static int bloblist_test_checksum(struct unit_test_state *uts) hdr->chksum--; /* Make sure the checksum changes when we add blobs */ - data = bloblist_add(TEST_TAG, TEST_SIZE); + data = bloblist_add(TEST_TAG, TEST_SIZE, 0); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); - data2 = bloblist_add(TEST_TAG2, TEST_SIZE2); + data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_assertok(bloblist_finish()); @@ -231,9 +235,123 @@ static int bloblist_test_checksum(struct unit_test_state *uts) return 0; } - BLOBLIST_TEST(bloblist_test_checksum, 0); +/* Test the 'bloblist info' command */ +static int bloblist_test_cmd_info(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct bloblist_hdr *hdr; + char *data, *data2; + + hdr = clear_bloblist(); + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + data = bloblist_ensure(TEST_TAG, TEST_SIZE); + data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); + + console_record_reset_enable(); + if (!state->show_test_output) + gd->flags |= GD_FLG_SILENT; + console_record_reset(); + run_command("bloblist info", 0); + ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr)); + ut_assert_nextline("size: 400 1 KiB"); + ut_assert_nextline("alloced: 70 112 Bytes"); + ut_assert_nextline("free: 390 912 Bytes"); + ut_assert_console_end(); + gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + + return 0; +} +BLOBLIST_TEST(bloblist_test_cmd_info, 0); + +/* Test the 'bloblist list' command */ +static int bloblist_test_cmd_list(struct unit_test_state *uts) +{ + struct sandbox_state *state = state_get_current(); + struct bloblist_hdr *hdr; + char *data, *data2; + + hdr = clear_bloblist(); + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + data = bloblist_ensure(TEST_TAG, TEST_SIZE); + data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); + + console_record_reset_enable(); + if (!state->show_test_output) + gd->flags |= GD_FLG_SILENT; + console_record_reset(); + run_command("bloblist list", 0); + ut_assert_nextline("Address Size Tag Name"); + ut_assert_nextline("%08lx %8x 1 EC host event", + (ulong)map_to_sysmem(data), TEST_SIZE); + ut_assert_nextline("%08lx %8x 2 SPL hand-off", + (ulong)map_to_sysmem(data2), TEST_SIZE2); + ut_assert_console_end(); + gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); + + return 0; +} +BLOBLIST_TEST(bloblist_test_cmd_list, 0); + +/* Test alignment of bloblist blobs */ +static int bloblist_test_align(struct unit_test_state *uts) +{ + struct bloblist_hdr *hdr; + ulong addr; + char *data; + int i; + + /* At the start there should be no records */ + hdr = clear_bloblist(); + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); + + /* Check the default alignment */ + for (i = 0; i < 3; i++) { + int size = i * 3; + ulong addr; + char *data; + int j; + + data = bloblist_add(i, size, 0); + ut_assertnonnull(data); + addr = map_to_sysmem(data); + ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1)); + + /* Only the bytes in the blob data should be zeroed */ + for (j = 0; j < size; j++) + ut_asserteq(0, data[j]); + for (; j < BLOBLIST_ALIGN; j++) + ut_asserteq(ERASE_BYTE, data[j]); + } + + /* Check larger alignment */ + for (i = 0; i < 3; i++) { + int align = 32 << i; + + data = bloblist_add(3 + i, i * 4, align); + ut_assertnonnull(data); + addr = map_to_sysmem(data); + ut_asserteq(0, addr & (align - 1)); + } + + /* Check alignment with an bloblist starting on a smaller alignment */ + hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE); + memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); + memset(hdr, '\0', sizeof(*hdr)); + ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE, + 0)); + + data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2); + ut_assertnonnull(data); + addr = map_to_sysmem(data); + ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1)); + + return 0; +} +BLOBLIST_TEST(bloblist_test_align, 0); + int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 8bfb706602..01ac3c2094 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -19,6 +19,22 @@ static int dm_test_ofnode_compatible(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_compatible, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts) +{ + /* test invalid phandle */ + ut_assert(!ofnode_valid(ofnode_get_by_phandle(0))); + ut_assert(!ofnode_valid(ofnode_get_by_phandle(-1))); + + /* test first valid phandle */ + ut_assert(ofnode_valid(ofnode_get_by_phandle(1))); + + /* test unknown phandle */ + ut_assert(!ofnode_valid(ofnode_get_by_phandle(0x1000000))); + + return 0; +} +DM_TEST(dm_test_ofnode_get_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts) { const char propname[] = "compatible"; @@ -87,6 +103,81 @@ static int dm_test_ofnode_read(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_phandle(struct unit_test_state *uts) +{ + struct ofnode_phandle_args args; + ofnode node; + int ret; + const char prop[] = "test-gpios"; + const char cell[] = "#gpio-cells"; + const char prop2[] = "phandle-value"; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_valid(node)); + + /* Test ofnode_count_phandle_with_args with cell name */ + ret = ofnode_count_phandle_with_args(node, "missing", cell, 0); + ut_asserteq(-ENOENT, ret); + ret = ofnode_count_phandle_with_args(node, prop, "#invalid", 0); + ut_asserteq(-EINVAL, ret); + ret = ofnode_count_phandle_with_args(node, prop, cell, 0); + ut_asserteq(5, ret); + + /* Test ofnode_parse_phandle_with_args with cell name */ + ret = ofnode_parse_phandle_with_args(node, "missing", cell, 0, 0, + &args); + ut_asserteq(-ENOENT, ret); + ret = ofnode_parse_phandle_with_args(node, prop, "#invalid", 0, 0, + &args); + ut_asserteq(-EINVAL, ret); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 0, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(1, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 1, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(4, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 2, &args); + ut_assertok(ret); + ut_asserteq(5, args.args_count); + ut_asserteq(5, args.args[0]); + ut_asserteq(1, args.args[4]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 3, &args); + ut_asserteq(-ENOENT, ret); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 4, &args); + ut_assertok(ret); + ut_asserteq(1, args.args_count); + ut_asserteq(12, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 5, &args); + ut_asserteq(-ENOENT, ret); + + /* Test ofnode_count_phandle_with_args with cell count */ + ret = ofnode_count_phandle_with_args(node, "missing", NULL, 2); + ut_asserteq(-ENOENT, ret); + ret = ofnode_count_phandle_with_args(node, prop2, NULL, 1); + ut_asserteq(3, ret); + + /* Test ofnode_parse_phandle_with_args with cell count */ + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 0, &args); + ut_assertok(ret); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(10, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 1, &args); + ut_asserteq(-EINVAL, ret); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 2, &args); + ut_assertok(ret); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(30, args.args[0]); + ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 3, &args); + ut_asserteq(-ENOENT, ret); + + return 0; +} +DM_TEST(dm_test_ofnode_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + static int dm_test_ofnode_read_chosen(struct unit_test_state *uts) { const char *str; diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 26d57f40d1..cc12419ea0 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -968,6 +968,71 @@ static int dm_test_read_int_index(struct unit_test_state *uts) } DM_TEST(dm_test_read_int_index, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_read_phandle(struct unit_test_state *uts) +{ + struct udevice *dev; + struct ofnode_phandle_args args; + int ret; + const char prop[] = "test-gpios"; + const char cell[] = "#gpio-cells"; + const char prop2[] = "phandle-value"; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev)); + ut_asserteq_str("a-test", dev->name); + + /* Test dev_count_phandle_with_args with cell name */ + ret = dev_count_phandle_with_args(dev, "missing", cell, 0); + ut_asserteq(-ENOENT, ret); + ret = dev_count_phandle_with_args(dev, prop, "#invalid", 0); + ut_asserteq(-EINVAL, ret); + ut_asserteq(5, dev_count_phandle_with_args(dev, prop, cell, 0)); + + /* Test dev_read_phandle_with_args with cell name */ + ret = dev_read_phandle_with_args(dev, "missing", cell, 0, 0, &args); + ut_asserteq(-ENOENT, ret); + ret = dev_read_phandle_with_args(dev, prop, "#invalid", 0, 0, &args); + ut_asserteq(-EINVAL, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 0, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(1, args.args[0]); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 1, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(4, args.args[0]); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 2, &args)); + ut_asserteq(5, args.args_count); + ut_asserteq(5, args.args[0]); + ut_asserteq(1, args.args[4]); + ret = dev_read_phandle_with_args(dev, prop, cell, 0, 3, &args); + ut_asserteq(-ENOENT, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 4, &args)); + ut_asserteq(1, args.args_count); + ut_asserteq(12, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop, cell, 0, 5, &args); + ut_asserteq(-ENOENT, ret); + + /* Test dev_count_phandle_with_args with cell count */ + ret = dev_count_phandle_with_args(dev, "missing", NULL, 2); + ut_asserteq(-ENOENT, ret); + ut_asserteq(3, dev_count_phandle_with_args(dev, prop2, NULL, 1)); + + /* Test dev_read_phandle_with_args with cell count */ + ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 0, &args)); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(10, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 1, &args); + ut_asserteq(-EINVAL, ret); + ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 2, &args)); + ut_asserteq(1, ofnode_valid(args.node)); + ut_asserteq(1, args.args_count); + ut_asserteq(30, args.args[0]); + ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 3, &args); + ut_asserteq(-ENOENT, ret); + + return 0; +} +DM_TEST(dm_test_read_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + /* Test iteration through devices by drvdata */ static int dm_test_uclass_drvdata(struct unit_test_state *uts) {