Various minor sandbox iumprovements
Fixes for tracing with sandbox Refactoring for boot_get_fdt() -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAlzAfvkACgkQfxc6PpAI reYu9AgAjaFmydXjE8DxkSB3rR7DHZFTs1erVKAAL2v+Tdf7LDmz+j6u1M3v55WY 6r54f/gZ1UX5TEmQgEAKLa7QvvRO/lNvSGQnLHhZhv2IVWo7uWCKAUPdQ6XVZnUK zO5v+ucs9Ne4HxQJHMC509HUIIBbydiRvUm8W0SeBZy4kEyJDuub4L+rpARkXNks IZfKuY+VS4FK73D4M9PIhoXSubZgVS4AEcapakU1DvEz0kjsN4wr4idGrp3lutPC 455imz83JBq2+mx1oxclOGedkIDzTCq+nWQAwSftMehrJpGrp7RLNo0v4QZZUf4V LIXRqObIYse9yQLkYPpeBdePMc8/tQ== =0NJ2 -----END PGP SIGNATURE----- Merge tag 'pull-24apr19' of git://git.denx.de/u-boot-dm Various minor sandbox iumprovements Fixes for tracing with sandbox Refactoring for boot_get_fdt()
This commit is contained in:
commit
7d99406742
29 changed files with 335 additions and 152 deletions
|
@ -14,6 +14,7 @@ config ARMADA_32BIT
|
|||
select SPL_OF_CONTROL if SPL
|
||||
select SPL_SIMPLE_BUS if SPL
|
||||
select SUPPORT_SPL
|
||||
select TRANSLATION_OFFSET
|
||||
|
||||
config ARMADA_64BIT
|
||||
bool
|
||||
|
|
|
@ -93,15 +93,21 @@ void board_init_f(ulong dummy)
|
|||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use special translation offset for SPL. This needs to be
|
||||
* configured *before* spl_init() is called as this function
|
||||
* calls dm_init() which calls the bind functions of the
|
||||
* device drivers. Here the base address needs to be configured
|
||||
* (translated) correctly.
|
||||
*/
|
||||
gd->translation_offset = 0xd0000000 - 0xf1000000;
|
||||
|
||||
ret = spl_init();
|
||||
if (ret) {
|
||||
debug("spl_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
/* Use special translation offset for SPL */
|
||||
dm_set_translation_offset(0xd0000000 - 0xf1000000);
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
timer_init();
|
||||
|
|
|
@ -209,8 +209,8 @@ void os_tty_raw(int fd, bool allow_sigs)
|
|||
|
||||
void *os_malloc(size_t length)
|
||||
{
|
||||
struct os_mem_hdr *hdr;
|
||||
int page_size = getpagesize();
|
||||
struct os_mem_hdr *hdr;
|
||||
|
||||
/*
|
||||
* Use an address that is hopefully available to us so that pointers
|
||||
|
@ -229,30 +229,34 @@ void *os_malloc(size_t length)
|
|||
|
||||
void os_free(void *ptr)
|
||||
{
|
||||
struct os_mem_hdr *hdr = ptr;
|
||||
int page_size = getpagesize();
|
||||
struct os_mem_hdr *hdr;
|
||||
|
||||
hdr--;
|
||||
if (ptr)
|
||||
munmap(hdr, hdr->length + sizeof(*hdr));
|
||||
if (ptr) {
|
||||
hdr = ptr - page_size;
|
||||
munmap(hdr, hdr->length + page_size);
|
||||
}
|
||||
}
|
||||
|
||||
void *os_realloc(void *ptr, size_t length)
|
||||
{
|
||||
struct os_mem_hdr *hdr = ptr;
|
||||
int page_size = getpagesize();
|
||||
struct os_mem_hdr *hdr;
|
||||
void *buf = NULL;
|
||||
|
||||
hdr--;
|
||||
if (length != 0) {
|
||||
if (length) {
|
||||
buf = os_malloc(length);
|
||||
if (!buf)
|
||||
return buf;
|
||||
if (ptr) {
|
||||
hdr = ptr - page_size;
|
||||
if (length > hdr->length)
|
||||
length = hdr->length;
|
||||
memcpy(buf, ptr, length);
|
||||
}
|
||||
}
|
||||
os_free(ptr);
|
||||
if (ptr)
|
||||
os_free(ptr);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -786,3 +790,40 @@ int os_mprotect_allow(void *start, size_t len)
|
|||
|
||||
return mprotect(start, len, PROT_READ | PROT_WRITE);
|
||||
}
|
||||
|
||||
void *os_find_text_base(void)
|
||||
{
|
||||
char line[500];
|
||||
void *base = NULL;
|
||||
int len;
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* This code assumes that the first line of /proc/self/maps holds
|
||||
* information about the text, for example:
|
||||
*
|
||||
* 5622d9907000-5622d9a55000 r-xp 00000000 08:01 15067168 u-boot
|
||||
*
|
||||
* The first hex value is assumed to be the address.
|
||||
*
|
||||
* This is tested in Linux 4.15.
|
||||
*/
|
||||
fd = open("/proc/self/maps", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
len = read(fd, line, sizeof(line));
|
||||
if (len > 0) {
|
||||
char *end = memchr(line, '-', len);
|
||||
|
||||
if (end) {
|
||||
unsigned long long addr;
|
||||
|
||||
*end = '\0';
|
||||
if (sscanf(line, "%llx", &addr) == 1)
|
||||
base = (void *)addr;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
|
|
@ -303,10 +303,8 @@ int board_run_command(const char *cmdline)
|
|||
static void setup_ram_buf(struct sandbox_state *state)
|
||||
{
|
||||
/* Zero the RAM buffer if we didn't read it, to keep valgrind happy */
|
||||
if (!state->ram_buf_read) {
|
||||
if (!state->ram_buf_read)
|
||||
memset(state->ram_buf, '\0', state->ram_size);
|
||||
printf("clear %p %x\n", state->ram_buf, state->ram_size);
|
||||
}
|
||||
|
||||
gd->arch.ram_buf = state->ram_buf;
|
||||
gd->ram_size = state->ram_size;
|
||||
|
@ -328,6 +326,10 @@ int main(int argc, char *argv[])
|
|||
gd_t data;
|
||||
int ret;
|
||||
|
||||
memset(&data, '\0', sizeof(data));
|
||||
gd = &data;
|
||||
gd->arch.text_base = os_find_text_base();
|
||||
|
||||
ret = state_init();
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -340,8 +342,6 @@ int main(int argc, char *argv[])
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
memset(&data, '\0', sizeof(data));
|
||||
gd = &data;
|
||||
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
|
||||
gd->malloc_base = CONFIG_MALLOC_F_ADDR;
|
||||
#endif
|
||||
|
@ -350,6 +350,12 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
setup_ram_buf(state);
|
||||
|
||||
/*
|
||||
* Set up the relocation offset here, since sandbox symbols are always
|
||||
* relocated by the OS before sandbox is entered.
|
||||
*/
|
||||
gd->reloc_off = (ulong)gd->arch.text_base;
|
||||
|
||||
/* Do pre- and post-relocation init */
|
||||
board_init_f(0);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
/* Architecture-specific global data */
|
||||
struct arch_global_data {
|
||||
uint8_t *ram_buf; /* emulated RAM buffer */
|
||||
void *text_base; /* pointer to base of text region */
|
||||
};
|
||||
|
||||
#include <asm-generic/global_data.h>
|
||||
|
|
|
@ -392,6 +392,49 @@ state_setprop() which does this automatically and avoids running out of
|
|||
space. See existing code for examples.
|
||||
|
||||
|
||||
Debugging the init sequence
|
||||
---------------------------
|
||||
|
||||
If you get a failure in the initcall sequence, like this:
|
||||
|
||||
initcall sequence 0000560775957c80 failed at call 0000000000048134 (err=-96)
|
||||
|
||||
Then you use can use grep to see which init call failed, e.g.:
|
||||
|
||||
$ grep 0000000000048134 u-boot.map
|
||||
stdio_add_devices
|
||||
|
||||
Of course another option is to run it with a debugger such as gdb:
|
||||
|
||||
$ gdb u-boot
|
||||
...
|
||||
(gdb) br initcall.h:41
|
||||
Breakpoint 1 at 0x4db9d: initcall.h:41. (2 locations)
|
||||
|
||||
Note that two locations are reported, since this function is used in both
|
||||
board_init_f() and board_init_r().
|
||||
|
||||
(gdb) r
|
||||
Starting program: /tmp/b/sandbox/u-boot
|
||||
[Thread debugging using libthread_db enabled]
|
||||
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
|
||||
|
||||
U-Boot 2018.09-00264-ge0c2ba9814-dirty (Sep 22 2018 - 12:21:46 -0600)
|
||||
|
||||
DRAM: 128 MiB
|
||||
MMC:
|
||||
|
||||
Breakpoint 1, initcall_run_list (init_sequence=0x5555559619e0 <init_sequence_f>)
|
||||
at /scratch/sglass/cosarm/src/third_party/u-boot/files/include/initcall.h:41
|
||||
41 printf("initcall sequence %p failed at call %p (err=%d)\n",
|
||||
(gdb) print *init_fnc_ptr
|
||||
$1 = (const init_fnc_t) 0x55555559c114 <stdio_add_devices>
|
||||
(gdb)
|
||||
|
||||
|
||||
This approach can be used on normal boards as well as sandbox.
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
|
@ -434,6 +477,9 @@ that are mapped into that memory:
|
|||
0 CONFIG_SYS_FDT_LOAD_ADDR Device tree
|
||||
e000 CONFIG_BLOBLIST_ADDR Blob list
|
||||
10000 CONFIG_MALLOC_F_ADDR Early memory allocation
|
||||
f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer
|
||||
100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled)
|
||||
=
|
||||
|
||||
|
||||
--
|
||||
|
|
13
cmd/Kconfig
13
cmd/Kconfig
|
@ -53,6 +53,17 @@ config SYS_PROMPT
|
|||
This string is displayed in the command line to the left of the
|
||||
cursor.
|
||||
|
||||
config SYS_XTRACE
|
||||
string "Command execution tracer"
|
||||
depends on CMDLINE
|
||||
default y if CMDLINE
|
||||
help
|
||||
This option enables the possiblity to print all commands before
|
||||
executing them and after all variables are evaluated (similar
|
||||
to Bash's xtrace/'set -x' feature).
|
||||
To enable the tracer a variable "xtrace" needs to be defined in
|
||||
the environment.
|
||||
|
||||
menu "Autoboot options"
|
||||
|
||||
config AUTOBOOT
|
||||
|
@ -1900,7 +1911,7 @@ config CMD_TRACE
|
|||
Enables a command to control using of function tracing within
|
||||
U-Boot. This allows recording of call traces including timing
|
||||
information. The command can write data to memory for exporting
|
||||
for analsys (e.g. using bootchart). See doc/README.trace for full
|
||||
for analysis (e.g. using bootchart). See doc/README.trace for full
|
||||
details.
|
||||
|
||||
config CMD_AVB
|
||||
|
|
|
@ -714,7 +714,7 @@ static int setup_reloc(void)
|
|||
* just after the default vector table location, so at 0x400
|
||||
*/
|
||||
gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400);
|
||||
#else
|
||||
#elif !defined(CONFIG_SANDBOX)
|
||||
gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -99,6 +99,13 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name,
|
|||
struct bootstage_data *data = gd->bootstage;
|
||||
struct bootstage_record *rec;
|
||||
|
||||
/*
|
||||
* initf_bootstage() is called very early during boot but since hang()
|
||||
* calls bootstage_error() we can be called before bootstage is set up.
|
||||
* Add a check to avoid this.
|
||||
*/
|
||||
if (!data)
|
||||
return mark;
|
||||
if (flags & BOOTSTAGEF_ALLOC)
|
||||
id = data->next_id++;
|
||||
|
||||
|
|
|
@ -574,6 +574,20 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
|
|||
enum command_ret_t rc = CMD_RET_SUCCESS;
|
||||
cmd_tbl_t *cmdtp;
|
||||
|
||||
#if defined(CONFIG_SYS_XTRACE)
|
||||
char *xtrace;
|
||||
|
||||
xtrace = env_get("xtrace");
|
||||
if (xtrace) {
|
||||
puts("+");
|
||||
for (int i = 0; i < argc; i++) {
|
||||
puts(" ");
|
||||
puts(argv[i]);
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Look up command in command table */
|
||||
cmdtp = find_cmd(argv[0]);
|
||||
if (cmdtp == NULL) {
|
||||
|
|
|
@ -279,7 +279,6 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
|
|||
int fdt_noffset;
|
||||
#endif
|
||||
const char *select = NULL;
|
||||
int ok_no_fdt = 0;
|
||||
|
||||
*of_flat_tree = NULL;
|
||||
*of_size = 0;
|
||||
|
@ -462,17 +461,24 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
|
|||
struct andr_img_hdr *hdr = buf;
|
||||
ulong fdt_data, fdt_len;
|
||||
|
||||
if (android_image_get_second(hdr, &fdt_data, &fdt_len) != 0)
|
||||
goto no_fdt;
|
||||
if (!android_image_get_second(hdr, &fdt_data, &fdt_len) &&
|
||||
!fdt_check_header((char *)fdt_data)) {
|
||||
fdt_blob = (char *)fdt_data;
|
||||
if (fdt_totalsize(fdt_blob) != fdt_len)
|
||||
goto error;
|
||||
|
||||
fdt_blob = (char *)fdt_data;
|
||||
if (fdt_check_header(fdt_blob) != 0)
|
||||
goto no_fdt;
|
||||
debug("## Using FDT in Android image second area\n");
|
||||
} else {
|
||||
fdt_addr = env_get_hex("fdtaddr", 0);
|
||||
if (!fdt_addr)
|
||||
goto no_fdt;
|
||||
|
||||
if (fdt_totalsize(fdt_blob) != fdt_len)
|
||||
goto error;
|
||||
fdt_blob = map_sysmem(fdt_addr, 0);
|
||||
if (fdt_check_header(fdt_blob))
|
||||
goto no_fdt;
|
||||
|
||||
debug("## Using FDT found in Android image second area\n");
|
||||
debug("## Using FDT at ${fdtaddr}=Ox%lx\n", fdt_addr);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
debug("## No Flattened Device Tree\n");
|
||||
|
@ -487,14 +493,9 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
|
|||
return 0;
|
||||
|
||||
no_fdt:
|
||||
ok_no_fdt = 1;
|
||||
debug("Continuing to boot without FDT\n");
|
||||
return 0;
|
||||
error:
|
||||
*of_flat_tree = NULL;
|
||||
*of_size = 0;
|
||||
if (!select && ok_no_fdt) {
|
||||
debug("Continuing to boot without FDT\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ CONFIG_CONSOLE_RECORD=y
|
|||
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
||||
CONFIG_SILENT_CONSOLE=y
|
||||
CONFIG_PRE_CONSOLE_BUFFER=y
|
||||
CONFIG_PRE_CON_BUF_ADDR=0x100000
|
||||
CONFIG_PRE_CON_BUF_ADDR=0xf0000
|
||||
CONFIG_LOG_MAX_LEVEL=6
|
||||
CONFIG_LOG_ERROR_RETURN=y
|
||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
|
|
|
@ -225,6 +225,15 @@ config SPL_OF_TRANSLATE
|
|||
used for the address translation. This function is faster and
|
||||
smaller in size than fdt_translate_address().
|
||||
|
||||
config TRANSLATION_OFFSET
|
||||
bool "Platforms specific translation offset"
|
||||
depends on DM && OF_CONTROL
|
||||
help
|
||||
Some platforms need a special address translation. Those
|
||||
platforms (e.g. mvebu in SPL) can configure a translation
|
||||
offset by enabling this option and setting the translation_offset
|
||||
variable in the GD in their platform- / board-specific code.
|
||||
|
||||
config OF_ISA_BUS
|
||||
bool
|
||||
depends on OF_TRANSLATE
|
||||
|
|
|
@ -74,13 +74,16 @@ fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TRANSLATION_OFFSET)
|
||||
/*
|
||||
* Some platforms need a special address translation. Those
|
||||
* platforms (e.g. mvebu in SPL) can configure a translation
|
||||
* offset in the DM by calling dm_set_translation_offset() that
|
||||
* will get added to all addresses returned by devfdt_get_addr().
|
||||
* offset by setting this value in the GD and enaling this
|
||||
* feature via CONFIG_TRANSLATION_OFFSET. This value will
|
||||
* get added to all addresses returned by devfdt_get_addr().
|
||||
*/
|
||||
addr += dm_get_translation_offset();
|
||||
addr += gd->translation_offset;
|
||||
#endif
|
||||
|
||||
return addr;
|
||||
#else
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct root_priv {
|
||||
fdt_addr_t translation_offset; /* optional translation offset */
|
||||
};
|
||||
|
||||
static const struct driver_info root_info = {
|
||||
.name = "root_driver",
|
||||
};
|
||||
|
@ -52,22 +48,6 @@ void dm_fixup_for_gd_move(struct global_data *new_gd)
|
|||
}
|
||||
}
|
||||
|
||||
fdt_addr_t dm_get_translation_offset(void)
|
||||
{
|
||||
struct udevice *root = dm_root();
|
||||
struct root_priv *priv = dev_get_priv(root);
|
||||
|
||||
return priv->translation_offset;
|
||||
}
|
||||
|
||||
void dm_set_translation_offset(fdt_addr_t offs)
|
||||
{
|
||||
struct udevice *root = dm_root();
|
||||
struct root_priv *priv = dev_get_priv(root);
|
||||
|
||||
priv->translation_offset = offs;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
void fix_drivers(void)
|
||||
{
|
||||
|
@ -420,7 +400,6 @@ int dm_init_and_scan(bool pre_reloc_only)
|
|||
U_BOOT_DRIVER(root_driver) = {
|
||||
.name = "root_driver",
|
||||
.id = UCLASS_ROOT,
|
||||
.priv_auto_alloc_size = sizeof(struct root_priv),
|
||||
};
|
||||
|
||||
/* This is the root uclass */
|
||||
|
|
|
@ -60,4 +60,5 @@ U_BOOT_DRIVER(simple_bus_drv) = {
|
|||
.name = "generic_simple_bus",
|
||||
.id = UCLASS_SIMPLE_BUS,
|
||||
.of_match = generic_simple_bus_ids,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <fdtdec.h>
|
||||
#include <membuff.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
|
@ -133,6 +134,9 @@ typedef struct global_data {
|
|||
struct spl_handoff *spl_handoff;
|
||||
# endif
|
||||
#endif
|
||||
#if defined(CONFIG_TRANSLATION_OFFSET)
|
||||
fdt_addr_t translation_offset; /* optional translation offset */
|
||||
#endif
|
||||
} gd_t;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
|
||||
#ifdef FTRACE
|
||||
#define CONFIG_TRACE
|
||||
#define CONFIG_CMD_TRACE
|
||||
#define CONFIG_TRACE_BUFFER_SIZE (16 << 20)
|
||||
#define CONFIG_TRACE_EARLY_SIZE (8 << 20)
|
||||
#define CONFIG_TRACE_EARLY_SIZE (16 << 20)
|
||||
#define CONFIG_TRACE_EARLY
|
||||
#define CONFIG_TRACE_EARLY_ADDR 0x00100000
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
*
|
||||
* The semantics of do_div() are:
|
||||
*
|
||||
* uint32_t do_div(uint64_t *n, uint32_t base)
|
||||
* u32 do_div(u64 *n, u32 base)
|
||||
* {
|
||||
* uint32_t remainder = *n % base;
|
||||
* *n = *n / base;
|
||||
* return remainder;
|
||||
* u32 remainder = *n % base;
|
||||
* *n = *n / base;
|
||||
* return remainder;
|
||||
* }
|
||||
*
|
||||
* NOTE: macro parameter n is evaluated multiple times,
|
||||
|
@ -26,10 +26,10 @@
|
|||
#if BITS_PER_LONG == 64
|
||||
|
||||
# define do_div(n,base) ({ \
|
||||
uint32_t __base = (base); \
|
||||
uint32_t __rem; \
|
||||
__rem = ((uint64_t)(n)) % __base; \
|
||||
(n) = ((uint64_t)(n)) / __base; \
|
||||
u32 __base = (base); \
|
||||
u32 __rem; \
|
||||
__rem = ((u64)(n)) % __base; \
|
||||
(n) = ((u64)(n)) / __base; \
|
||||
__rem; \
|
||||
})
|
||||
|
||||
|
@ -62,8 +62,8 @@
|
|||
* Hence this monstrous macro (static inline doesn't always \
|
||||
* do the trick here). \
|
||||
*/ \
|
||||
uint64_t ___res, ___x, ___t, ___m, ___n = (n); \
|
||||
uint32_t ___p, ___bias; \
|
||||
u64 ___res, ___x, ___t, ___m, ___n = (n); \
|
||||
u32 ___p, ___bias; \
|
||||
\
|
||||
/* determine MSB of b */ \
|
||||
___p = 1 << ilog2(___b); \
|
||||
|
@ -110,7 +110,7 @@
|
|||
* possible, otherwise that'll need extra overflow \
|
||||
* handling later. \
|
||||
*/ \
|
||||
uint32_t ___bits = -(___m & -___m); \
|
||||
u32 ___bits = -(___m & -___m); \
|
||||
___bits |= ___m >> 32; \
|
||||
___bits = (~___bits) << 1; \
|
||||
/* \
|
||||
|
@ -150,61 +150,61 @@
|
|||
/*
|
||||
* Default C implementation for __arch_xprod_64()
|
||||
*
|
||||
* Prototype: uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
|
||||
* Prototype: u64 __arch_xprod_64(const u64 m, u64 n, bool bias)
|
||||
* Semantic: retval = ((bias ? m : 0) + m * n) >> 64
|
||||
*
|
||||
* The product is a 128-bit value, scaled down to 64 bits.
|
||||
* Assuming constant propagation to optimize away unused conditional code.
|
||||
* Architectures may provide their own optimized assembly implementation.
|
||||
*/
|
||||
static inline uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
|
||||
static inline u64 __arch_xprod_64(const u64 m, u64 n, bool bias)
|
||||
{
|
||||
uint32_t m_lo = m;
|
||||
uint32_t m_hi = m >> 32;
|
||||
uint32_t n_lo = n;
|
||||
uint32_t n_hi = n >> 32;
|
||||
uint64_t res, tmp;
|
||||
u32 m_lo = m;
|
||||
u32 m_hi = m >> 32;
|
||||
u32 n_lo = n;
|
||||
u32 n_hi = n >> 32;
|
||||
u64 res, tmp;
|
||||
|
||||
if (!bias) {
|
||||
res = ((uint64_t)m_lo * n_lo) >> 32;
|
||||
res = ((u64)m_lo * n_lo) >> 32;
|
||||
} else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
|
||||
/* there can't be any overflow here */
|
||||
res = (m + (uint64_t)m_lo * n_lo) >> 32;
|
||||
res = (m + (u64)m_lo * n_lo) >> 32;
|
||||
} else {
|
||||
res = m + (uint64_t)m_lo * n_lo;
|
||||
res = m + (u64)m_lo * n_lo;
|
||||
tmp = (res < m) ? (1ULL << 32) : 0;
|
||||
res = (res >> 32) + tmp;
|
||||
}
|
||||
|
||||
if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
|
||||
/* there can't be any overflow here */
|
||||
res += (uint64_t)m_lo * n_hi;
|
||||
res += (uint64_t)m_hi * n_lo;
|
||||
res += (u64)m_lo * n_hi;
|
||||
res += (u64)m_hi * n_lo;
|
||||
res >>= 32;
|
||||
} else {
|
||||
tmp = res += (uint64_t)m_lo * n_hi;
|
||||
res += (uint64_t)m_hi * n_lo;
|
||||
tmp = res += (u64)m_lo * n_hi;
|
||||
res += (u64)m_hi * n_lo;
|
||||
tmp = (res < tmp) ? (1ULL << 32) : 0;
|
||||
res = (res >> 32) + tmp;
|
||||
}
|
||||
|
||||
res += (uint64_t)m_hi * n_hi;
|
||||
res += (u64)m_hi * n_hi;
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __div64_32
|
||||
extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
|
||||
extern u32 __div64_32(u64 *dividend, u32 divisor);
|
||||
#endif
|
||||
|
||||
/* The unnecessary pointer compare is there
|
||||
* to check for type safety (n must be 64bit)
|
||||
*/
|
||||
# define do_div(n,base) ({ \
|
||||
uint32_t __base = (base); \
|
||||
uint32_t __rem; \
|
||||
(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \
|
||||
u32 __base = (base); \
|
||||
u32 __rem; \
|
||||
(void)(((typeof((n)) *)0) == ((u64 *)0)); \
|
||||
if (__builtin_constant_p(__base) && \
|
||||
is_power_of_2(__base)) { \
|
||||
__rem = (n) & (__base - 1); \
|
||||
|
@ -212,14 +212,14 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
|
|||
} else if (__div64_const32_is_OK && \
|
||||
__builtin_constant_p(__base) && \
|
||||
__base != 0) { \
|
||||
uint32_t __res_lo, __n_lo = (n); \
|
||||
u32 __res_lo, __n_lo = (n); \
|
||||
(n) = __div64_const32(n, __base); \
|
||||
/* the remainder can be computed with 32-bit regs */ \
|
||||
__res_lo = (n); \
|
||||
__rem = __n_lo - __res_lo * __base; \
|
||||
} else if (likely(((n) >> 32) == 0)) { \
|
||||
__rem = (uint32_t)(n) % __base; \
|
||||
(n) = (uint32_t)(n) / __base; \
|
||||
__rem = (u32)(n) % __base; \
|
||||
(n) = (u32)(n) / __base; \
|
||||
} else \
|
||||
__rem = __div64_32(&(n), __base); \
|
||||
__rem; \
|
||||
|
@ -234,9 +234,9 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
|
|||
/* Wrapper for do_div(). Doesn't modify dividend and returns
|
||||
* the result, not remainder.
|
||||
*/
|
||||
static inline uint64_t lldiv(uint64_t dividend, uint32_t divisor)
|
||||
static inline u64 lldiv(u64 dividend, u32 divisor)
|
||||
{
|
||||
uint64_t __res = dividend;
|
||||
u64 __res = dividend;
|
||||
do_div(__res, divisor);
|
||||
return(__res);
|
||||
}
|
||||
|
|
|
@ -120,25 +120,4 @@ fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index,
|
|||
*/
|
||||
fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name);
|
||||
|
||||
/**
|
||||
* dm_set_translation_offset() - Set translation offset
|
||||
* @offs: Translation offset
|
||||
*
|
||||
* Some platforms need a special address translation. Those
|
||||
* platforms (e.g. mvebu in SPL) can configure a translation
|
||||
* offset in the DM by calling this function. It will be
|
||||
* added to all addresses returned in devfdt_get_addr().
|
||||
*/
|
||||
void dm_set_translation_offset(fdt_addr_t offs);
|
||||
|
||||
/**
|
||||
* dm_get_translation_offset() - Get translation offset
|
||||
*
|
||||
* This function returns the translation offset that can
|
||||
* be configured by calling dm_set_translation_offset().
|
||||
*
|
||||
* @return translation offset for the device address (0 as default).
|
||||
*/
|
||||
fdt_addr_t dm_get_translation_offset(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1029,7 +1029,10 @@ int fdtdec_setup_memory_banksize(void);
|
|||
* @param phandle phandle to set for the given node
|
||||
* @return 0 on success or a negative error code on failure
|
||||
*/
|
||||
int fdtdec_set_phandle(void *blob, int node, uint32_t phandle);
|
||||
static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle)
|
||||
{
|
||||
return fdt_setprop_u32(blob, node, "phandle", phandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* fdtdec_add_reserved_memory() - add or find a reserved-memory node
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
typedef int (*init_fnc_t)(void);
|
||||
|
||||
#include <common.h>
|
||||
#include <initcall.h>
|
||||
#include <efi.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* To enable debugging. add #define DEBUG at the top of the including file.
|
||||
*
|
||||
* To find a symbol, use grep on u-boot.map
|
||||
*/
|
||||
static inline int initcall_run_list(const init_fnc_t init_sequence[])
|
||||
{
|
||||
const init_fnc_t *init_fnc_ptr;
|
||||
|
@ -22,13 +21,17 @@ static inline int initcall_run_list(const init_fnc_t init_sequence[])
|
|||
unsigned long reloc_ofs = 0;
|
||||
int ret;
|
||||
|
||||
if (gd->flags & GD_FLG_RELOC)
|
||||
/*
|
||||
* Sandbox is relocated by the OS, so symbols always appear at
|
||||
* the relocated address.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_SANDBOX) || (gd->flags & GD_FLG_RELOC))
|
||||
reloc_ofs = gd->reloc_off;
|
||||
#ifdef CONFIG_EFI_APP
|
||||
reloc_ofs = (unsigned long)image_base;
|
||||
#endif
|
||||
debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs);
|
||||
if (gd->flags & GD_FLG_RELOC)
|
||||
if (reloc_ofs)
|
||||
debug(" (relocated to %p)\n", (char *)*init_fnc_ptr);
|
||||
else
|
||||
debug("\n");
|
||||
|
|
11
include/os.h
11
include/os.h
|
@ -364,4 +364,15 @@ int os_write_file(const char *name, const void *buf, int size);
|
|||
*/
|
||||
int os_read_file(const char *name, void **bufp, int *sizep);
|
||||
|
||||
/*
|
||||
* os_find_text_base() - Find the text section in this running process
|
||||
*
|
||||
* This tries to find the address of the text section in this running process.
|
||||
* It can be useful to map the address of functions to the address listed in
|
||||
* the u-boot.map file.
|
||||
*
|
||||
* @return address if found, else NULL
|
||||
*/
|
||||
void *os_find_text_base(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -405,6 +405,7 @@
|
|||
#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
|
||||
#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
|
||||
#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
|
||||
#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */
|
||||
#define PCI_MSI_RFU 3 /* Rest of capability flags */
|
||||
#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
|
||||
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
|
||||
|
|
57
lib/Kconfig
57
lib/Kconfig
|
@ -165,6 +165,63 @@ config RBTREE
|
|||
config BITREVERSE
|
||||
bool "Bit reverse library from Linux"
|
||||
|
||||
config TRACE
|
||||
bool "Support for tracing of function calls and timing"
|
||||
imply CMD_TRACE
|
||||
help
|
||||
Enables function tracing within U-Boot. This allows recording of call
|
||||
traces including timing information. The command can write data to
|
||||
memory for exporting for analysis (e.g. using bootchart).
|
||||
See doc/README.trace for full details.
|
||||
|
||||
config TRACE_BUFFER_SIZE
|
||||
hex "Size of trace buffer in U-Boot"
|
||||
depends on TRACE
|
||||
default 0x01000000
|
||||
help
|
||||
Sets the size of the trace buffer in U-Boot. This is allocated from
|
||||
memory during relocation. If this buffer is too small, the trace
|
||||
history will be truncated, with later records omitted.
|
||||
|
||||
If early trace is enabled (i.e. before relocation), this buffer must
|
||||
be large enough to include all the data from the early trace buffer as
|
||||
well, since this is copied over to the main buffer during relocation.
|
||||
|
||||
A trace record is emitted for each function call and each record is
|
||||
12 bytes (see struct trace_call). A suggested minimum size is 1MB. If
|
||||
the size is too small then 'trace stats' will show a message saying
|
||||
how many records were dropped due to buffer overflow.
|
||||
|
||||
config TRACE_EARLY
|
||||
bool "Enable tracing before relocation"
|
||||
depends on TRACE
|
||||
help
|
||||
Sometimes it is helpful to trace execution of U-Boot before
|
||||
relocation. This is possible by using a arch-specific, fixed buffer
|
||||
position in memory. Enable this option to start tracing as early as
|
||||
possible after U-Boot starts.
|
||||
|
||||
config TRACE_EARLY_SIZE
|
||||
hex "Size of early trace buffer in U-Boot"
|
||||
depends on TRACE_EARLY
|
||||
default 0x00100000
|
||||
help
|
||||
Sets the size of the early trace buffer in bytes. This is used to hold
|
||||
tracing information before relocation.
|
||||
|
||||
config TRACE_EARLY_ADDR
|
||||
hex "Address of early trace buffer in U-Boot"
|
||||
depends on TRACE_EARLY
|
||||
default 0x00100000
|
||||
help
|
||||
Sets the address of the early trace buffer in U-Boot. This memory
|
||||
must be accessible before relocation.
|
||||
|
||||
A trace record is emitted for each function call and each record is
|
||||
12 bytes (see struct trace_call). A suggested minimum size is 1MB. If
|
||||
the size is too small then the message which says the amount of early
|
||||
data being coped will the the same as the
|
||||
|
||||
source lib/dhry/Kconfig
|
||||
|
||||
menu "Security support"
|
||||
|
|
20
lib/div64.c
20
lib/div64.c
|
@ -25,19 +25,25 @@
|
|||
#if BITS_PER_LONG == 32
|
||||
|
||||
#ifndef __div64_32
|
||||
uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
|
||||
/*
|
||||
* Don't instrument this function as it may be called from tracing code, since
|
||||
* it needs to read the timer and this often requires calling do_div(), which
|
||||
* calls this function.
|
||||
*/
|
||||
uint32_t __attribute__((weak, no_instrument_function)) __div64_32(u64 *n,
|
||||
u32 base)
|
||||
{
|
||||
uint64_t rem = *n;
|
||||
uint64_t b = base;
|
||||
uint64_t res, d = 1;
|
||||
uint32_t high = rem >> 32;
|
||||
u64 rem = *n;
|
||||
u64 b = base;
|
||||
u64 res, d = 1;
|
||||
u32 high = rem >> 32;
|
||||
|
||||
/* Reduce the thing a bit first */
|
||||
res = 0;
|
||||
if (high >= base) {
|
||||
high /= base;
|
||||
res = (uint64_t) high << 32;
|
||||
rem -= (uint64_t) (high*base) << 32;
|
||||
res = (u64)high << 32;
|
||||
rem -= (u64)(high * base) << 32;
|
||||
}
|
||||
|
||||
while ((int64_t)b > 0 && b < rem) {
|
||||
|
|
|
@ -1261,13 +1261,6 @@ __weak void *board_fdt_blob_setup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
int fdtdec_set_phandle(void *blob, int node, uint32_t phandle)
|
||||
{
|
||||
fdt32_t value = cpu_to_fdt32(phandle);
|
||||
|
||||
return fdt_setprop(blob, node, "phandle", &value, sizeof(value));
|
||||
}
|
||||
|
||||
static int fdtdec_init_reserved_memory(void *blob)
|
||||
{
|
||||
int na, ns, node, err;
|
||||
|
|
17
lib/trace.c
17
lib/trace.c
|
@ -183,7 +183,8 @@ int trace_list_functions(void *buff, int buff_size, unsigned int *needed)
|
|||
/* Work out how must of the buffer we used */
|
||||
*needed = ptr - buff;
|
||||
if (ptr > end)
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -227,7 +228,8 @@ int trace_list_calls(void *buff, int buff_size, unsigned *needed)
|
|||
/* Work out how must of the buffer we used */
|
||||
*needed = ptr - buff;
|
||||
if (ptr > end)
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -294,7 +296,8 @@ int __attribute__((no_instrument_function)) trace_init(void *buff,
|
|||
trace_enabled = 0;
|
||||
hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR,
|
||||
CONFIG_TRACE_EARLY_SIZE);
|
||||
end = (char *)&hdr->ftrace[hdr->ftrace_count];
|
||||
end = (char *)&hdr->ftrace[min(hdr->ftrace_count,
|
||||
hdr->ftrace_size)];
|
||||
used = end - (char *)hdr;
|
||||
printf("trace: copying %08lx bytes of early data from %x to %08lx\n",
|
||||
used, CONFIG_TRACE_EARLY_ADDR,
|
||||
|
@ -302,7 +305,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff,
|
|||
memcpy(buff, hdr, used);
|
||||
#else
|
||||
puts("trace: already enabled\n");
|
||||
return -1;
|
||||
return -EALREADY;
|
||||
#endif
|
||||
}
|
||||
hdr = (struct trace_hdr *)buff;
|
||||
|
@ -310,7 +313,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff,
|
|||
if (needed > buff_size) {
|
||||
printf("trace: buffer size %zd bytes: at least %zd needed\n",
|
||||
buff_size, needed);
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (was_disabled)
|
||||
|
@ -327,6 +330,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff,
|
|||
hdr->depth_limit = 15;
|
||||
trace_enabled = 1;
|
||||
trace_inited = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -346,7 +350,7 @@ int __attribute__((no_instrument_function)) trace_early_init(void)
|
|||
if (needed > buff_size) {
|
||||
printf("trace: buffer size is %zd bytes, at least %zd needed\n",
|
||||
buff_size, needed);
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
memset(hdr, '\0', needed);
|
||||
|
@ -361,6 +365,7 @@ int __attribute__((no_instrument_function)) trace_early_init(void)
|
|||
printf("trace: early enable at %08x\n", CONFIG_TRACE_EARLY_ADDR);
|
||||
|
||||
trace_enabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4401,11 +4401,6 @@ CONFIG_TMU_TIMER
|
|||
CONFIG_TPL_PAD_TO
|
||||
CONFIG_TPM_TIS_BASE_ADDRESS
|
||||
CONFIG_TPS6586X_POWER
|
||||
CONFIG_TRACE
|
||||
CONFIG_TRACE_BUFFER_SIZE
|
||||
CONFIG_TRACE_EARLY
|
||||
CONFIG_TRACE_EARLY_ADDR
|
||||
CONFIG_TRACE_EARLY_SIZE
|
||||
CONFIG_TRAILBLAZER
|
||||
CONFIG_TRATS
|
||||
CONFIG_TSEC
|
||||
|
|
Loading…
Reference in a new issue