diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asm-offsets.c | 3 | ||||
-rw-r--r-- | lib/fdtdec.c | 116 | ||||
-rw-r--r-- | lib/strmhz.c | 4 | ||||
-rw-r--r-- | lib/vsprintf.c | 19 |
4 files changed, 125 insertions, 17 deletions
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 129bc3e2af..580f763da6 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -31,6 +31,9 @@ int main(void) #ifdef CONFIG_SYS_MALLOC_F_LEN DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base)); #endif +#ifdef CONFIG_X86 + DEFINE(GD_BIST, offsetof(struct global_data, arch.bist)); +#endif #if defined(CONFIG_ARM) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 9714620ab3..7c7e673aeb 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -73,6 +73,8 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"), COMPAT(PARADE_PS8625, "parade,ps8625"), COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), + COMPAT(INTEL_MICROCODE, "intel,microcode"), + COMPAT(MEMORY_SPD, "memory-spd"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) @@ -355,9 +357,9 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset, slash = strrchr(prop, '/'); if (strcmp(slash + 1, find_name)) continue; - for (p = name; *p; p++) { - if (isdigit(*p)) { - *seqp = simple_strtoul(p, NULL, 10); + for (p = name + strlen(name) - 1; p > name; p--) { + if (!isdigit(*p)) { + *seqp = simple_strtoul(p + 1, NULL, 10); debug("Found seq %d\n", *seqp); return 0; } @@ -485,6 +487,26 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, return err; } +int fdtdec_get_int_array_count(const void *blob, int node, + const char *prop_name, u32 *array, int count) +{ + const u32 *cell; + int len, elems; + int i; + + debug("%s: %s\n", __func__, prop_name); + cell = fdt_getprop(blob, node, prop_name, &len); + if (!cell) + return -FDT_ERR_NOTFOUND; + elems = len / sizeof(u32); + if (count > elems) + count = elems; + for (i = 0; i < count; i++) + array[i] = fdt32_to_cpu(cell[i]); + + return count; +} + const u32 *fdtdec_locate_array(const void *blob, int node, const char *prop_name, int count) { @@ -669,20 +691,25 @@ char *fdtdec_get_config_string(const void *blob, const char *prop_name) return (char *)nodep; } -int fdtdec_decode_region(const void *blob, int node, - const char *prop_name, void **ptrp, size_t *size) +int fdtdec_decode_region(const void *blob, int node, const char *prop_name, + fdt_addr_t *basep, fdt_size_t *sizep) { const fdt_addr_t *cell; int len; - debug("%s: %s\n", __func__, prop_name); + debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL), + prop_name); cell = fdt_getprop(blob, node, prop_name, &len); - if (!cell || (len != sizeof(fdt_addr_t) * 2)) + if (!cell || (len < sizeof(fdt_addr_t) * 2)) { + debug("cell=%p, len=%d\n", cell, len); return -1; + } + + *basep = fdt_addr_to_cpu(*cell); + *sizep = fdt_size_to_cpu(cell[1]); + debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, + (ulong)*sizep); - *ptrp = map_sysmem(fdt_addr_to_cpu(*cell), *size); - *size = fdt_size_to_cpu(cell[1]); - debug("%s: size=%zx\n", __func__, *size); return 0; } @@ -698,6 +725,7 @@ int fdtdec_decode_region(const void *blob, int node, int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, struct fmap_entry *entry) { + const char *prop; u32 reg[2]; if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) { @@ -706,6 +734,13 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, } entry->offset = reg[0]; entry->length = reg[1]; + entry->used = fdtdec_get_int(blob, node, "used", entry->length); + prop = fdt_getprop(blob, node, "compress", NULL); + entry->compress_algo = prop && !strcmp(prop, "lzo") ? + FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE; + prop = fdt_getprop(blob, node, "hash", &entry->hash_size); + entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE; + entry->hash = (uint8_t *)prop; return 0; } @@ -780,4 +815,65 @@ int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf) return 0; } + +int fdtdec_decode_memory_region(const void *blob, int config_node, + const char *mem_type, const char *suffix, + fdt_addr_t *basep, fdt_size_t *sizep) +{ + char prop_name[50]; + const char *mem; + fdt_size_t size, offset_size; + fdt_addr_t base, offset; + int node; + + if (config_node == -1) { + config_node = fdt_path_offset(blob, "/config"); + if (config_node < 0) { + debug("%s: Cannot find /config node\n", __func__); + return -ENOENT; + } + } + if (!suffix) + suffix = ""; + + snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, + suffix); + mem = fdt_getprop(blob, config_node, prop_name, NULL); + if (!mem) { + debug("%s: No memory type for '%s', using /memory\n", __func__, + prop_name); + mem = "/memory"; + } + + node = fdt_path_offset(blob, mem); + if (node < 0) { + debug("%s: Failed to find node '%s': %s\n", __func__, mem, + fdt_strerror(node)); + return -ENOENT; + } + + /* + * Not strictly correct - the memory may have multiple banks. We just + * use the first + */ + if (fdtdec_decode_region(blob, node, "reg", &base, &size)) { + debug("%s: Failed to decode memory region %s\n", __func__, + mem); + return -EINVAL; + } + + snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, + suffix); + if (fdtdec_decode_region(blob, config_node, prop_name, &offset, + &offset_size)) { + debug("%s: Failed to decode memory region '%s'\n", __func__, + prop_name); + return -EINVAL; + } + + *basep = base + offset; + *sizep = offset_size; + + return 0; +} #endif diff --git a/lib/strmhz.c b/lib/strmhz.c index f9a17727f5..5c16cc4fc7 100644 --- a/lib/strmhz.c +++ b/lib/strmhz.c @@ -11,11 +11,11 @@ char *strmhz (char *buf, unsigned long hz) long l, n; long m; - n = DIV_ROUND(hz, 1000) / 1000L; + n = DIV_ROUND_CLOSEST(hz, 1000) / 1000L; l = sprintf (buf, "%ld", n); hz -= n * 1000000L; - m = DIV_ROUND(hz, 1000L); + m = DIV_ROUND_CLOSEST(hz, 1000L); if (m != 0) sprintf (buf + l, ".%03ld", m); return (buf); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b585713b7c..e0f264850f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,9 +25,6 @@ #include <div64.h> #define noinline __attribute__((noinline)) -/* some reluctance to put this into a new limits.h, so it is here */ -#define INT_MAX ((int)(~0U>>1)) - unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { @@ -518,6 +515,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) { + u64 num = (uintptr_t)ptr; + /* * Being a boot loader, we explicitly allow pointers to * (physical) address null. @@ -530,6 +529,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, #ifdef CONFIG_CMD_NET switch (*fmt) { + case 'a': + flags |= SPECIAL | ZEROPAD; + + switch (fmt[1]) { + case 'p': + default: + field_width = sizeof(phys_addr_t) * 2 + 2; + num = *(phys_addr_t *)ptr; + break; + } + break; case 'm': flags |= SPECIAL; /* Fallthrough */ @@ -555,8 +565,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, field_width = 2*sizeof(void *); flags |= ZEROPAD; } - return number(buf, end, (unsigned long)ptr, 16, field_width, - precision, flags); + return number(buf, end, num, 16, field_width, precision, flags); } static int vsnprintf_internal(char *buf, size_t size, const char *fmt, |