Merge branch '2021-01-15-assorted-improvements'

- Add MBR partition layout writing supporting, clean up code.
- A large number of assorted console/iomux cleanups
- A large number of board_r related cleanups.
- Log enhancements
This commit is contained in:
Tom Rini 2021-01-16 11:14:21 -05:00
commit 14ea1b3635
45 changed files with 1237 additions and 424 deletions

View File

@ -642,7 +642,7 @@ int syscall(int call, int *retval, ...)
return 1;
}
void api_init(void)
int api_init(void)
{
struct api_signature *sig;
@ -679,7 +679,7 @@ void api_init(void)
sig = malloc(sizeof(struct api_signature));
if (sig == NULL) {
printf("API: could not allocate memory for the signature!\n");
return;
return -ENOMEM;
}
env_set_hex("api_address", (unsigned long)sig);
@ -691,6 +691,8 @@ void api_init(void)
sig->checksum = crc32(0, (unsigned char *)sig,
sizeof(struct api_signature));
debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
return 0;
}
void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,

View File

@ -8,7 +8,7 @@
#ifndef _API_PRIVATE_H_
#define _API_PRIVATE_H_
void api_init(void);
int api_init(void);
void platform_set_mr(struct sys_info *, unsigned long, unsigned long, int);
int platform_sys_info(struct sys_info *);

View File

@ -628,7 +628,18 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
enum dcache_option option);
#ifdef CONFIG_SYS_NONCACHED_MEMORY
void noncached_init(void);
/**
* noncached_init() - Initialize non-cached memory region
*
* Initialize non-cached memory area. This memory region will be typically
* located right below the malloc() area and mapped uncached in the MMU.
*
* It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int noncached_init(void);
phys_addr_t noncached_alloc(size_t size, size_t align);
#endif /* CONFIG_SYS_NONCACHED_MEMORY */

View File

@ -86,7 +86,7 @@ void noncached_set_region(void)
#endif
}
void noncached_init(void)
int noncached_init(void)
{
phys_addr_t start, end;
size_t size;
@ -103,6 +103,8 @@ void noncached_init(void)
noncached_next = start;
noncached_set_region();
return 0;
}
phys_addr_t noncached_alloc(size_t size, size_t align)

View File

@ -40,7 +40,7 @@ void exc_handler(struct pt_regs *fp) {
for(;;);
}
void trap_init(ulong value) {
static void trap_init(ulong value) {
unsigned long *vec = (ulong *)value;
int i;
@ -59,3 +59,10 @@ void trap_init(ulong value) {
setvbr(value); /* set vector base register to new table */
}
int arch_initr_trap(void)
{
trap_init(CONFIG_SYS_SDRAM_BASE);
return 0;
}

View File

@ -99,7 +99,7 @@ static void set_handler(unsigned long offset, void *addr, unsigned long size)
flush_cache(ebase + offset, size);
}
void trap_init(ulong reloc_addr)
static void trap_init(ulong reloc_addr)
{
unsigned long ebase = gd->irq_sp;
@ -131,3 +131,10 @@ void trap_restore(void)
clear_c0_status(ST0_BEV);
execution_hazard_barrier();
}
int arch_initr_trap(void)
{
trap_init(CONFIG_SYS_SDRAM_BASE);
return 0;
}

View File

@ -1028,7 +1028,7 @@ void arch_preboot_os(void)
mtmsr(msr);
}
void cpu_secondary_init_r(void)
int cpu_secondary_init_r(void)
{
#ifdef CONFIG_QE
#ifdef CONFIG_U_QE
@ -1040,6 +1040,8 @@ void cpu_secondary_init_r(void)
qe_init(qe_base);
qe_reset();
#endif
return 0;
}
#ifdef CONFIG_BOARD_LATE_INIT

View File

@ -40,6 +40,7 @@ obj-y += interrupts.o
obj-$(CONFIG_CMD_KGDB) += kgdb.o
obj-y += stack.o
obj-y += time.o
obj-y += traps.o
endif # not minimal
ifdef CONFIG_SPL_BUILD

19
arch/powerpc/lib/traps.c Normal file
View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
#include <common.h>
#include <init.h>
DECLARE_GLOBAL_DATA_PTR;
void trap_init(unsigned long reloc_addr);
int arch_initr_trap(void)
{
trap_init(gd->relocaddr);
return 0;
}

View File

@ -9,6 +9,7 @@
#include <efi_loader.h>
#include <errno.h>
#include <init.h>
#include <log.h>
#include <os.h>
#include <cli.h>
#include <sort.h>
@ -486,6 +487,10 @@ int main(int argc, char *argv[])
*/
gd->reloc_off = (ulong)gd->arch.text_base;
/* sandbox test: log functions called before log_init in board_init_f */
log_info("sandbox: starting...\n");
log_debug("debug: %s\n", __func__);
/* Do pre- and post-relocation init */
board_init_f(0);

View File

@ -1034,6 +1034,14 @@ config CMD_LSBLK
Print list of available block device drivers, and for each, the list
of known block devices.
config CMD_MBR
bool "MBR (Master Boot Record) command"
select DOS_PARTITION
select HAVE_BLOCK_DEVICE
help
Enable the 'mbr' command to ready and write MBR (Master Boot Record)
style partition tables.
config CMD_MISC
bool "misc"
depends on MISC

View File

@ -178,6 +178,7 @@ obj-$(CONFIG_CMD_ZFS) += zfs.o
obj-$(CONFIG_CMD_DFU) += dfu.o
obj-$(CONFIG_CMD_GPT) += gpt.o
obj-$(CONFIG_CMD_MBR) += mbr.o
obj-$(CONFIG_CMD_ETHSW) += ethsw.o
obj-$(CONFIG_CMD_AXI) += axi.o
obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o

314
cmd/mbr.c Normal file
View File

@ -0,0 +1,314 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* cmd_mbr.c -- MBR (Master Boot Record) handling command
*
* Copyright (C) 2020 Samsung Electronics
* author: Marek Szyprowski <m.szyprowski@samsung.com>
*
* based on the gpt command.
*/
#include <common.h>
#include <blk.h>
#include <command.h>
#include <malloc.h>
#include <part.h>
/**
* extract_val() - Extract a value from the key=value pair list
* @str: pointer to string with key=values pairs
* @key: pointer to the key to search for
*
* The list of parameters is come separated, only a value for
* the given key is returend.
*
* Function allocates memory for the value, remember to free!
*
* Return: Pointer to allocated string with the value.
*/
static char *extract_val(const char *str, const char *key)
{
char *v, *k;
char *s, *strcopy;
char *new = NULL;
strcopy = strdup(str);
if (strcopy == NULL)
return NULL;
s = strcopy;
while (s) {
v = strsep(&s, ",");
if (!v)
break;
k = strsep(&v, "=");
if (!k)
break;
if (strcmp(k, key) == 0) {
new = strdup(v);
break;
}
}
free(strcopy);
return new;
}
/**
* found_key() - Search for a key without a value in the parameter list
* @str: pointer to string with key
* @key: pointer to the key to search for
*
* The list of parameters is come separated.
*
* Return: True if key has been found.
*/
static bool found_key(const char *str, const char *key)
{
char *k;
char *s, *strcopy;
bool result = false;
strcopy = strdup(str);
if (!strcopy)
return NULL;
s = strcopy;
while (s) {
k = strsep(&s, ",");
if (!k)
break;
if (strcmp(k, key) == 0) {
result = true;
break;
}
}
free(strcopy);
return result;
}
static int str_to_partitions(const char *str_part, int blksz,
unsigned long *disk_uuid, struct disk_partition **partitions,
int *parts_count)
{
char *tok, *str, *s;
int i;
char *val, *p;
int p_count;
struct disk_partition *parts;
int errno = 0;
uint64_t size_ll, start_ll;
if (str_part == NULL)
return -1;
str = strdup(str_part);
if (str == NULL)
return -ENOMEM;
/* extract disk guid */
s = str;
val = extract_val(str, "uuid_disk");
if (val) {
val = strsep(&val, ";");
p = val;
*disk_uuid = ustrtoull(p, &p, 0);
free(val);
/* Move s to first partition */
strsep(&s, ";");
}
if (s == NULL) {
printf("Error: is the partitions string NULL-terminated?\n");
return -EINVAL;
}
/* remove the optional semicolon at the end of the string */
i = strlen(s) - 1;
if (s[i] == ';')
s[i] = '\0';
/* calculate expected number of partitions */
p_count = 1;
p = s;
while (*p) {
if (*p++ == ';')
p_count++;
}
/* allocate memory for partitions */
parts = calloc(sizeof(struct disk_partition), p_count);
if (parts == NULL)
return -ENOMEM;
/* retrieve partitions data from string */
for (i = 0; i < p_count; i++) {
tok = strsep(&s, ";");
if (tok == NULL)
break;
/* size */
val = extract_val(tok, "size");
if (!val) { /* 'size' is mandatory */
errno = -4;
goto err;
}
p = val;
if ((strcmp(p, "-") == 0)) {
/* auto extend the size */
parts[i].size = 0;
} else {
size_ll = ustrtoull(p, &p, 0);
parts[i].size = size_ll / blksz;
}
free(val);
/* start address */
val = extract_val(tok, "start");
if (val) { /* start address is optional */
p = val;
start_ll = ustrtoull(p, &p, 0);
parts[i].start = start_ll / blksz;
free(val);
}
/* system id */
val = extract_val(tok, "id");
if (!val) { /* '' is mandatory */
errno = -4;
goto err;
}
p = val;
parts[i].sys_ind = ustrtoul(p, &p, 0);
free(val);
/* bootable */
if (found_key(tok, "bootable"))
parts[i].bootable = PART_BOOTABLE;
}
*parts_count = p_count;
*partitions = parts;
free(str);
return 0;
err:
free(str);
free(parts);
return errno;
}
static int do_write_mbr(struct blk_desc *dev, const char *str)
{
unsigned long disk_uuid = 0;
struct disk_partition *partitions;
int blksz = dev->blksz;
int count;
if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
printf("MBR: failed to setup partitions from \"%s\"\n", str);
return -1;
}
if (layout_mbr_partitions(partitions, count, dev->lba)) {
printf("MBR: failed to layout partitions on the device\n");
free(partitions);
return -1;
}
if (write_mbr_partitions(dev, partitions, count, disk_uuid)) {
printf("MBR: failed to write partitions to the device\n");
free(partitions);
return -1;
}
return 0;
}
static int do_verify_mbr(struct blk_desc *dev, const char *str)
{
unsigned long disk_uuid = 0;
struct disk_partition *partitions;
int blksz = dev->blksz;
int count, i, ret = 1;
if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
printf("MBR: failed to setup partitions from \"%s\"\n", str);
return -1;
}
for (i = 0; i < count; i++) {
struct disk_partition p;
if (part_get_info(dev, i+1, &p))
goto fail;
if ((partitions[i].size && p.size < partitions[i].size) ||
(partitions[i].start && p.start < partitions[i].start) ||
(p.sys_ind != partitions[i].sys_ind))
goto fail;
}
ret = 0;
fail:
free(partitions);
return ret;
}
static int do_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
const char *parts = NULL;
int ret = CMD_RET_SUCCESS;
int dev = 0;
char *ep;
struct blk_desc *blk_dev_desc = NULL;
if (argc != 4 && argc != 5)
return CMD_RET_USAGE;
dev = (int)simple_strtoul(argv[3], &ep, 10);
if (!ep || ep[0] != '\0') {
printf("'%s' is not a number\n", argv[3]);
return CMD_RET_USAGE;
}
blk_dev_desc = blk_get_dev(argv[2], dev);
if (!blk_dev_desc) {
printf("%s: %s dev %d NOT available\n",
__func__, argv[2], dev);
return CMD_RET_FAILURE;
}
if ((strcmp(argv[1], "write") == 0)) {
parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
printf("MBR: write ");
ret = do_write_mbr(blk_dev_desc, parts);
} else if ((strcmp(argv[1], "verify") == 0)) {
printf("MBR: verify ");
parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
ret = do_verify_mbr(blk_dev_desc, parts);
} else {
return CMD_RET_USAGE;
}
if (ret) {
printf("error!\n");
return CMD_RET_FAILURE;
}
printf("success!\n");
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
"MBR (Master Boot Record)",
"<command> <interface> <dev> <partitions_list>\n"
" - MBR partition table restoration utility\n"
" Restore or check partition information on a device connected\n"
" to the given block interface\n"
" Example usage:\n"
" mbr write mmc 0 [\"${mbr_parts}\"]\n"
" mbr verify mmc 0 [\"${partitions}\"]\n"
);

View File

@ -17,6 +17,14 @@ config CONSOLE_RECORD
To enable console recording, call console_record_reset_enable()
from your code.
config CONSOLE_RECORD_INIT_F
bool "Enable console recording during pre-relocation init"
depends on CONSOLE_RECORD && SYS_MALLOC_F
default y
help
This option enables console recording during pre-relocation init.
CONFIG_SYS_MALLOC_F must be enabled to use this feature.
config CONSOLE_RECORD_OUT_SIZE
hex "Output buffer size"
depends on CONSOLE_RECORD

View File

@ -503,14 +503,6 @@ static int reserve_board(void)
return 0;
}
static int setup_machine(void)
{
#ifdef CONFIG_MACH_TYPE
gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
#endif
return 0;
}
static int reserve_global_data(void)
{
gd->start_addr_sp = reserve_stack_aligned(sizeof(gd_t));
@ -522,21 +514,21 @@ static int reserve_global_data(void)
static int reserve_fdt(void)
{
#ifndef CONFIG_OF_EMBED
/*
* If the device tree is sitting immediately above our image then we
* must relocate it. If it is embedded in the data section, then it
* will be relocated with other data.
*/
if (gd->fdt_blob) {
gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
if (!IS_ENABLED(CONFIG_OF_EMBED)) {
/*
* If the device tree is sitting immediately above our image
* then we must relocate it. If it is embedded in the data
* section, then it will be relocated with other data.
*/
if (gd->fdt_blob) {
gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
debug("Reserving %lu Bytes for FDT at: %08lx\n",
gd->fdt_size, gd->start_addr_sp);
gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
debug("Reserving %lu Bytes for FDT at: %08lx\n",
gd->fdt_size, gd->start_addr_sp);
}
}
#endif
return 0;
}
@ -605,6 +597,10 @@ int setup_bdinfo(void)
bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE; /* size of SRAM */
}
#ifdef CONFIG_MACH_TYPE
bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
#endif
return arch_setup_bdinfo();
}
@ -620,14 +616,15 @@ static int init_post(void)
static int reloc_fdt(void)
{
#ifndef CONFIG_OF_EMBED
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
if (gd->new_fdt) {
memcpy(gd->new_fdt, gd->fdt_blob, fdt_totalsize(gd->fdt_blob));
gd->fdt_blob = gd->new_fdt;
if (!IS_ENABLED(CONFIG_OF_EMBED)) {
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
if (gd->new_fdt) {
memcpy(gd->new_fdt, gd->fdt_blob,
fdt_totalsize(gd->fdt_blob));
gd->fdt_blob = gd->new_fdt;
}
}
#endif
return 0;
}
@ -765,15 +762,6 @@ static int initf_bootstage(void)
return 0;
}
static int initf_console_record(void)
{
#if defined(CONFIG_CONSOLE_RECORD) && CONFIG_VAL(SYS_MALLOC_F_LEN)
return console_record_init();
#else
return 0;
#endif
}
static int initf_dm(void)
{
#if defined(CONFIG_DM) && CONFIG_VAL(SYS_MALLOC_F_LEN)
@ -784,11 +772,12 @@ static int initf_dm(void)
bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
if (ret)
return ret;
#endif
#ifdef CONFIG_TIMER_EARLY
ret = dm_timer_init();
if (ret)
return ret;
if (IS_ENABLED(CONFIG_TIMER_EARLY)) {
ret = dm_timer_init();
if (ret)
return ret;
}
#endif
return 0;
@ -830,7 +819,9 @@ static const init_fnc_t init_sequence_f[] = {
bloblist_init,
#endif
setup_spl_handoff,
initf_console_record,
#if defined(CONFIG_CONSOLE_RECORD_INIT_F)
console_record_init,
#endif
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
#endif
@ -922,7 +913,6 @@ static const init_fnc_t init_sequence_f[] = {
reserve_uboot,
reserve_malloc,
reserve_board,
setup_machine,
reserve_global_data,
reserve_fdt,
reserve_bootstage,

View File

@ -91,21 +91,8 @@ __weak int board_flash_wp_on(void)
return 0;
}
__weak void cpu_secondary_init_r(void)
__weak int cpu_secondary_init_r(void)
{
}
static int initr_secondary_cpu(void)
{
/*
* after non-volatile devices & environment is setup and cpu code have
* another round to deal with any initialization that might require
* full access to the environment or loading of some image (firmware)
* from a non-volatile device
*/
/* TODO: maybe define this for all archs? */
cpu_secondary_init_r();
return 0;
}
@ -195,20 +182,10 @@ static int initr_reloc_global_data(void)
return 0;
}
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
static int initr_trap(void)
__weak int arch_initr_trap(void)
{
/*
* Setup trap handlers
*/
#if defined(CONFIG_PPC)
trap_init(gd->relocaddr);
#else
trap_init(CONFIG_SYS_SDRAM_BASE);
#endif
return 0;
}
#endif
#ifdef CONFIG_ADDR_MAP
static int initr_addr_map(void)
@ -219,14 +196,6 @@ static int initr_addr_map(void)
}
#endif
#ifdef CONFIG_POST
static int initr_post_backlog(void)
{
post_output_backlog();
return 0;
}
#endif
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
static int initr_unlock_ram_in_cache(void)
{
@ -235,25 +204,6 @@ static int initr_unlock_ram_in_cache(void)
}
#endif
#ifdef CONFIG_PCI_ENDPOINT
static int initr_pci_ep(void)
{
pci_ep_init();
return 0;
}
#endif
#ifdef CONFIG_PCI
static int initr_pci(void)
{
if (IS_ENABLED(CONFIG_PCI_INIT_R))
pci_init();
return 0;
}
#endif
static int initr_barrier(void)
{
#ifdef CONFIG_PPC
@ -282,23 +232,6 @@ static int initr_malloc(void)
return 0;
}
static int initr_console_record(void)
{
#if defined(CONFIG_CONSOLE_RECORD)
return console_record_init();
#else
return 0;
#endif
}
#ifdef CONFIG_SYS_NONCACHED_MEMORY
static int initr_noncached(void)
{
noncached_init();
return 0;
}
#endif
static int initr_of_live(void)
{
if (CONFIG_IS_ENABLED(OF_LIVE)) {
@ -485,14 +418,6 @@ static int initr_mmc(void)
}
#endif
#ifdef CONFIG_XEN
static int initr_xen(void)
{
xen_init();
return 0;
}
#endif
#ifdef CONFIG_PVBLOCK
static int initr_pvblock(void)
{
@ -555,21 +480,6 @@ static int initr_malloc_bootparams(void)
}
#endif
static int initr_jumptable(void)
{
jumptable_init();
return 0;
}
#if defined(CONFIG_API)
static int initr_api(void)
{
/* Initialize API */
api_init();
return 0;
}
#endif
#ifdef CONFIG_CMD_NET
static int initr_ethaddr(void)
{
@ -614,14 +524,6 @@ static int initr_scsi(void)
}
#endif
#ifdef CONFIG_BITBANGMII
static int initr_bbmii(void)
{
bb_miiphy_init();
return 0;
}
#endif
#ifdef CONFIG_CMD_NET
static int initr_net(void)
{
@ -713,9 +615,11 @@ static init_fnc_t init_sequence_r[] = {
initr_malloc,
log_init,
initr_bootstage, /* Needs malloc() but has its own timer */
initr_console_record,
#if defined(CONFIG_CONSOLE_RECORD)
console_record_init,
#endif
#ifdef CONFIG_SYS_NONCACHED_MEMORY
initr_noncached,
noncached_init,
#endif
initr_of_live,
#ifdef CONFIG_DM
@ -755,9 +659,7 @@ static init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_NEEDS_MANUAL_RELOC
initr_manual_reloc_cmdtable,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
initr_trap,
#endif
arch_initr_trap,
#ifdef CONFIG_ADDR_MAP
initr_addr_map,
#endif
@ -766,15 +668,15 @@ static init_fnc_t init_sequence_r[] = {
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_POST
initr_post_backlog,
post_output_backlog,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
#if defined(CONFIG_PCI_INIT_R) && defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do early PCI configuration _before_ the flash gets initialised,
* because PCU resources are crucial for flash access on some boards.
*/
initr_pci,
pci_init,
#endif
#ifdef CONFIG_ARCH_EARLY_INIT_R
arch_early_init_r,
@ -798,7 +700,7 @@ static init_fnc_t init_sequence_r[] = {
initr_mmc,
#endif
#ifdef CONFIG_XEN
initr_xen,
xen_init,
#endif
#ifdef CONFIG_PVBLOCK
initr_pvblock,
@ -808,21 +710,21 @@ static init_fnc_t init_sequence_r[] = {
initr_malloc_bootparams,
#endif
INIT_FUNC_WATCHDOG_RESET
initr_secondary_cpu,
cpu_secondary_init_r,
#if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
mac_read_from_eeprom,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
#if defined(CONFIG_PCI_INIT_R) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do pci configuration
*/
initr_pci,
pci_init,
#endif
stdio_add_devices,
initr_jumptable,
jumptable_init,
#ifdef CONFIG_API
initr_api,
api_init,
#endif
console_init_r, /* fully init console as a device */
#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
@ -861,10 +763,10 @@ static init_fnc_t init_sequence_r[] = {
initr_scsi,
#endif
#ifdef CONFIG_BITBANGMII
initr_bbmii,
bb_miiphy_init,
#endif
#ifdef CONFIG_PCI_ENDPOINT
initr_pci_ep,
pci_ep_init,
#endif
#ifdef CONFIG_CMD_NET
INIT_FUNC_WATCHDOG_RESET

View File

@ -44,14 +44,15 @@ static int on_console(const char *name, const char *value, enum env_op op,
case env_op_create:
case env_op_overwrite:
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
if (iomux_doenv(console, value))
return 1;
#else
/* Try assigning specified device */
if (console_assign(console, value) < 0)
return 1;
#endif
if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
if (iomux_doenv(console, value))
return 1;
} else {
/* Try assigning specified device */
if (console_assign(console, value) < 0)
return 1;
}
return 0;
case env_op_delete:
@ -69,14 +70,13 @@ U_BOOT_ENV_CALLBACK(console, on_console);
static int on_silent(const char *name, const char *value, enum env_op op,
int flags)
{
#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)
if (flags & H_INTERACTIVE)
return 0;
#endif
#if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)
if ((flags & H_INTERACTIVE) == 0)
return 0;
#endif
if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET))
if (flags & H_INTERACTIVE)
return 0;
if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC))
if ((flags & H_INTERACTIVE) == 0)
return 0;
if (value != NULL)
gd->flags |= GD_FLG_SILENT;
@ -88,6 +88,64 @@ static int on_silent(const char *name, const char *value, enum env_op op,
U_BOOT_ENV_CALLBACK(silent, on_silent);
#endif
#ifdef CONFIG_CONSOLE_RECORD
/* helper function: access to gd->console_out and gd->console_in */
static void console_record_putc(const char c)
{
if (!(gd->flags & GD_FLG_RECORD))
return;
if (gd->console_out.start)
membuff_putbyte((struct membuff *)&gd->console_out, c);
}
static void console_record_puts(const char *s)
{
if (!(gd->flags & GD_FLG_RECORD))
return;
if (gd->console_out.start)
membuff_put((struct membuff *)&gd->console_out, s, strlen(s));
}
static int console_record_getc(void)
{
if (!(gd->flags & GD_FLG_RECORD))
return -1;
if (!gd->console_in.start)
return -1;
return membuff_getbyte((struct membuff *)&gd->console_in);
}
static int console_record_tstc(void)
{
if (!(gd->flags & GD_FLG_RECORD))
return 0;
if (gd->console_in.start) {
if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
return 1;
}
return 0;
}
#else
static void console_record_putc(char c)
{
}
static void console_record_puts(const char *s)
{
}
static int console_record_getc(void)
{
return -1;
}
static int console_record_tstc(void)
{
return 0;
}
#endif
#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
/*
* if overwrite_console returns 1, the stdin, stderr and stdout
@ -114,13 +172,9 @@ static int console_setfile(int file, struct stdio_dev * dev)
case stdin:
case stdout:
case stderr:
/* Start new device */
if (dev->start) {
error = dev->start(dev);
/* If it's not started dont use it */
if (error < 0)
break;
}
error = console_start(file, dev);
if (error)
break;
/* Assign the new device (leaving the existing one started) */
stdio_devices[file] = dev;
@ -159,14 +213,13 @@ static bool console_dev_is_serial(struct stdio_dev *sdev)
{
bool is_serial;
#ifdef CONFIG_DM_SERIAL
if (sdev->flags & DEV_FLAGS_DM) {
if (IS_ENABLED(CONFIG_DM_SERIAL) && (sdev->flags & DEV_FLAGS_DM)) {
struct udevice *dev = sdev->priv;
is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
} else
#endif
is_serial = !strcmp(sdev->name, "serial");
} else {
is_serial = !strcmp(sdev->name, "serial");
}
return is_serial;
}
@ -174,10 +227,42 @@ static bool console_dev_is_serial(struct stdio_dev *sdev)
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
/** Console I/O multiplexing *******************************************/
/* tstcdev: save the last stdio device with pending characters, with tstc != 0 */
static struct stdio_dev *tstcdev;
struct stdio_dev **console_devices[MAX_FILES];
int cd_count[MAX_FILES];
static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
{
console_devices[file][0] = dev;
}
/**
* console_needs_start_stop() - check if we need to start or stop the STDIO device
* @file: STDIO file
* @sdev: STDIO device in question
*
* This function checks if we need to start or stop the stdio device used for
* a console. For IOMUX case it simply enforces one time start and one time
* stop of the device independently of how many STDIO files are using it. In
* other words, we start console once before first STDIO device wants it and
* stop after the last is gone.
*/
static bool console_needs_start_stop(int file, struct stdio_dev *sdev)
{
int i, j;
for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
if (i == file)
continue;
for (j = 0; j < cd_count[i]; j++)
if (console_devices[i][j] == sdev)
return false;
}
return true;
}
/*
* This depends on tstc() always being called before getchar().
* This is guaranteed to be true because this routine is called
@ -194,6 +279,12 @@ static int console_getc(int file)
return ret;
}
/* Upper layer may have already called tstc(): check the saved result */
static bool console_has_tstc(void)
{
return !!tstcdev;
}
static int console_tstc(int file)
{
int i, ret;
@ -276,11 +367,26 @@ static inline void console_doenv(int file, struct stdio_dev *dev)
}
#endif
#else
static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
{
}
static inline bool console_needs_start_stop(int file, struct stdio_dev *sdev)
{
return true;
}
static inline int console_getc(int file)
{
return stdio_devices[file]->getc(stdio_devices[file]);
}
static bool console_has_tstc(void)
{
return false;
}
static inline int console_tstc(int file)
{
return stdio_devices[file]->tstc(stdio_devices[file]);
@ -310,6 +416,32 @@ static inline void console_doenv(int file, struct stdio_dev *dev)
#endif
#endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
int console_start(int file, struct stdio_dev *sdev)
{
int error;
if (!console_needs_start_stop(file, sdev))
return 0;
/* Start new device */
if (sdev->start) {
error = sdev->start(sdev);
/* If it's not started don't use it */
if (error < 0)
return error;
}
return 0;
}
void console_stop(int file, struct stdio_dev *sdev)
{
if (!console_needs_start_stop(file, sdev))
return;
if (sdev->stop)
sdev->stop(sdev);
}
/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
int serial_printf(const char *fmt, ...)
@ -338,25 +470,25 @@ int fgetc(int file)
*/
for (;;) {
WATCHDOG_RESET();
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
/*
* Upper layer may have already called tstc() so
* check for that first.
*/
if (tstcdev != NULL)
return console_getc(file);
console_tstc(file);
#else
if (console_tstc(file))
return console_getc(file);
#endif
#ifdef CONFIG_WATCHDOG
if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
/*
* Upper layer may have already called tstc() so
* check for that first.
*/
if (console_has_tstc())
return console_getc(file);
console_tstc(file);
} else {
if (console_tstc(file))
return console_getc(file);
}
/*
* If the watchdog must be rate-limited then it should
* already be handled in board-specific code.
*/
udelay(1);
#endif
if (IS_ENABLED(CONFIG_WATCHDOG))
udelay(1);
}
}
@ -406,23 +538,18 @@ int fprintf(int file, const char *fmt, ...)
int getchar(void)
{
#ifdef CONFIG_DISABLE_CONSOLE
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
int ch;
if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
return 0;
#endif
if (!gd->have_console)
return 0;
#ifdef CONFIG_CONSOLE_RECORD
if (gd->console_in.start) {
int ch;
ch = console_record_getc();
if (ch != -1)
return ch;
ch = membuff_getbyte((struct membuff *)&gd->console_in);
if (ch != -1)
return 1;
}
#endif
if (gd->flags & GD_FLG_DEVINIT) {
/* Get from the standard input */
return fgetc(stdin);
@ -434,19 +561,15 @@ int getchar(void)
int tstc(void)
{
#ifdef CONFIG_DISABLE_CONSOLE
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
return 0;
#endif
if (!gd->have_console)
return 0;
#ifdef CONFIG_CONSOLE_RECORD
if (gd->console_in.start) {
if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
return 1;
}
#endif
if (console_record_tstc())
return 1;
if (gd->flags & GD_FLG_DEVINIT) {
/* Test the standard input */
return ftstc(stdin);
@ -485,10 +608,8 @@ static void print_pre_console_buffer(int flushpoint)
char buf_out[CONFIG_PRE_CON_BUF_SZ + 1];
char *buf_in;
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT)
if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
return;
#endif
buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
@ -517,38 +638,31 @@ static inline void print_pre_console_buffer(int flushpoint) {}
void putc(const char c)
{
#ifdef CONFIG_SANDBOX
if (!gd)
return;
console_record_putc(c);
/* sandbox can send characters to stdout before it has a console */
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
os_putc(c);
return;
}
#endif
#ifdef CONFIG_DEBUG_UART
/* if we don't have a console yet, use the debug UART */
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
printch(c);
return;
}
#endif
if (!gd)
return;
#ifdef CONFIG_CONSOLE_RECORD
if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
membuff_putbyte((struct membuff *)&gd->console_out, c);
#endif
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT) {
if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
if (!(gd->flags & GD_FLG_DEVINIT))
pre_console_putc(c);
return;
}
#endif
#ifdef CONFIG_DISABLE_CONSOLE
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
return;
#endif
if (!gd->have_console)
return pre_console_putc(c);
@ -565,15 +679,18 @@ void putc(const char c)
void puts(const char *s)
{
#ifdef CONFIG_SANDBOX
if (!gd)
return;
console_record_puts(s);
/* sandbox can send characters to stdout before it has a console */
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
os_puts(s);
return;
}
#endif
#ifdef CONFIG_DEBUG_UART
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
while (*s) {
int ch = *s++;
@ -581,25 +698,15 @@ void puts(const char *s)
}
return;
}
#endif
if (!gd)
return;
#ifdef CONFIG_CONSOLE_RECORD
if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
membuff_put((struct membuff *)&gd->console_out, s, strlen(s));
#endif
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT) {
if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
if (!(gd->flags & GD_FLG_DEVINIT))
pre_console_puts(s);
return;
}
#endif
#ifdef CONFIG_DISABLE_CONSOLE
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
return;
#endif
if (!gd->have_console)
return pre_console_puts(s);
@ -725,7 +832,7 @@ void clear_ctrlc(void)
/** U-Boot INIT FUNCTIONS *************************************************/
struct stdio_dev *search_device(int flags, const char *name)
struct stdio_dev *console_search_dev(int flags, const char *name)
{
struct stdio_dev *dev;
@ -761,7 +868,7 @@ int console_assign(int file, const char *devname)
/* Check for valid device name */
dev = search_device(flag, devname);
dev = console_search_dev(flag, devname);
if (dev)
return console_setfile(file, dev);
@ -772,19 +879,19 @@ int console_assign(int file, const char *devname)
/* return true if the 'silent' flag is removed */
static bool console_update_silent(void)
{
#ifdef CONFIG_SILENT_CONSOLE
unsigned long flags = gd->flags;
if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
return false;
if (env_get("silent")) {
gd->flags |= GD_FLG_SILENT;
} else {
unsigned long flags = gd->flags;
gd->flags &= ~GD_FLG_SILENT;
return !!(flags & GD_FLG_SILENT);
return false;
}
#endif
return false;
gd->flags &= ~GD_FLG_SILENT;
return !!(flags & GD_FLG_SILENT);
}
int console_announce_r(void)
@ -843,12 +950,8 @@ int console_init_r(void)
{
char *stdinname, *stdoutname, *stderrname;
struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
int i;
#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
int iomux_err = 0;
#endif
int flushpoint;
/* update silent for env loaded from flash (initr_env) */
@ -871,27 +974,27 @@ int console_init_r(void)
stderrname = env_get("stderr");
if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
inputdev = search_device(DEV_FLAGS_INPUT, stdinname);
outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
errdev = search_device(DEV_FLAGS_OUTPUT, stderrname);
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
iomux_err = iomux_doenv(stdin, stdinname);
iomux_err += iomux_doenv(stdout, stdoutname);
iomux_err += iomux_doenv(stderr, stderrname);
if (!iomux_err)
/* Successful, so skip all the code below. */
goto done;
#endif
inputdev = console_search_dev(DEV_FLAGS_INPUT, stdinname);
outputdev = console_search_dev(DEV_FLAGS_OUTPUT, stdoutname);
errdev = console_search_dev(DEV_FLAGS_OUTPUT, stderrname);
if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
iomux_err = iomux_doenv(stdin, stdinname);
iomux_err += iomux_doenv(stdout, stdoutname);
iomux_err += iomux_doenv(stderr, stderrname);
if (!iomux_err)
/* Successful, so skip all the code below. */
goto done;
}
}
/* if the devices are overwritten or not found, use default device */
if (inputdev == NULL) {
inputdev = search_device(DEV_FLAGS_INPUT, "serial");
inputdev = console_search_dev(DEV_FLAGS_INPUT, "serial");
}
if (outputdev == NULL) {
outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
}
if (errdev == NULL) {
errdev = search_device(DEV_FLAGS_OUTPUT, "serial");
errdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
}
/* Initializes output console first */
if (outputdev != NULL) {
@ -907,25 +1010,22 @@ int console_init_r(void)
console_doenv(stdin, inputdev);
}
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
done:
#endif
#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
stdio_print_current_devices();
#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
stdio_print_current_devices();
#ifdef CONFIG_VIDCONSOLE_AS_LCD
if (strstr(stdoutname, CONFIG_VIDCONSOLE_AS_NAME))
printf("Warning: Please change '%s' to 'vidconsole' in stdout/stderr environment vars\n",
CONFIG_VIDCONSOLE_AS_NAME);
#endif
#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
/* set the environment variables (will overwrite previous env settings) */
for (i = 0; i < MAX_FILES; i++) {
env_set(stdio_names[i], stdio_devices[i]->name);
if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
/* set the environment variables (will overwrite previous env settings) */
for (i = 0; i < MAX_FILES; i++)
env_set(stdio_names[i], stdio_devices[i]->name);
}
#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
@ -956,18 +1056,16 @@ int console_init_r(void)
else
flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
#ifdef CONFIG_SPLASH_SCREEN
/*
* suppress all output if splash screen is enabled and we have
* a bmp to display. We redirect the output from frame buffer
* console to serial console in this case or suppress it if
* "silent" mode was requested.
*/
if (env_get("splashimage") != NULL) {
if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
if (!(gd->flags & GD_FLG_SILENT))
outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
outputdev = console_search_dev (DEV_FLAGS_OUTPUT, "serial");
}
#endif
/* Scan devices looking for input and output devices */
list_for_each(pos, list) {
@ -987,23 +1085,18 @@ int console_init_r(void)
if (outputdev != NULL) {
console_setfile(stdout, outputdev);
console_setfile(stderr, outputdev);
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
console_devices[stdout][0] = outputdev;
console_devices[stderr][0] = outputdev;
#endif
console_devices_set(stdout, outputdev);
console_devices_set(stderr, outputdev);
}
/* Initializes input console */
if (inputdev != NULL) {
console_setfile(stdin, inputdev);
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
console_devices[stdin][0] = inputdev;
#endif
console_devices_set(stdin, inputdev);
}
#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
stdio_print_current_devices();
#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
stdio_print_current_devices();
/* Setting environment variables */
for (i = 0; i < MAX_FILES; i++) {

View File

@ -25,8 +25,10 @@ unsigned long get_version(void)
# define miiphy_set_current_dev dummy
#endif
void jumptable_init(void)
int jumptable_init(void)
{
gd->jt = malloc(sizeof(struct jt_funcs));
#include <_exports.h>
return 0;
}

View File

@ -27,8 +27,8 @@ int iomux_doenv(const int console, const char *arg)
{
char *console_args, *temp, **start;
int i, j, k, io_flag, cs_idx, repeat;
struct stdio_dev **cons_set, **old_set;
struct stdio_dev *dev;
struct stdio_dev **cons_set;
console_args = strdup(arg);
if (console_args == NULL)
@ -45,15 +45,14 @@ int iomux_doenv(const int console, const char *arg)
i = 0;
temp = console_args;
for (;;) {
temp = strchr(temp, ',');
if (temp != NULL) {
i++;
temp++;
continue;
}
/* There's always one entry more than the number of commas. */
i++;
break;
temp = strchr(temp, ',');
if (temp == NULL)
break;
temp++;
}
start = (char **)malloc(i * sizeof(char *));
if (start == NULL) {
@ -95,10 +94,10 @@ int iomux_doenv(const int console, const char *arg)
for (j = 0; j < i; j++) {
/*
* Check whether the device exists and is valid.
* console_assign() also calls search_device(),
* console_assign() also calls console_search_dev(),
* but I need the pointer to the device.
*/
dev = search_device(io_flag, start[j]);
dev = console_search_dev(io_flag, start[j]);
if (dev == NULL)
continue;
/*
@ -127,21 +126,25 @@ int iomux_doenv(const int console, const char *arg)
if (cs_idx == 0) {
free(cons_set);
return 1;
} else {
/* Works even if console_devices[console] is NULL. */
console_devices[console] =
(struct stdio_dev **)realloc(console_devices[console],
cs_idx * sizeof(struct stdio_dev *));
if (console_devices[console] == NULL) {
free(cons_set);
return 1;
}
memcpy(console_devices[console], cons_set, cs_idx *
sizeof(struct stdio_dev *));
cd_count[console] = cs_idx;
}
free(cons_set);
old_set = console_devices[console];
repeat = cd_count[console];
console_devices[console] = cons_set;
cd_count[console] = cs_idx;
/* Stop dropped consoles */
for (i = 0; i < repeat; i++) {
for (j = 0; j < cs_idx; j++) {
if (old_set[i] == cons_set[j])
break;
}
if (j == cs_idx)
console_stop(console, old_set[i]);
}
free(old_set);
return 0;
}
#endif /* CONSOLE_MUX */

View File

@ -198,9 +198,10 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
* @rec: log record to dispatch
* Return: 0 msg sent, 1 msg not sent while already dispatching another msg
*/
static int log_dispatch(struct log_rec *rec)
static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args)
{
struct log_device *ldev;
char buf[CONFIG_SYS_CBSIZE];
/*
* When a log driver writes messages (e.g. via the network stack) this
@ -214,8 +215,13 @@ static int log_dispatch(struct log_rec *rec)
gd->processing_msg = true;
list_for_each_entry(ldev, &gd->log_head, sibling_node) {
if ((ldev->flags & LOGDF_ENABLE) &&
log_passes_filters(ldev, rec))
log_passes_filters(ldev, rec)) {
if (!rec->msg) {
vsnprintf(buf, sizeof(buf), fmt, args);
rec->msg = buf;
}
ldev->drv->emit(ldev, rec);
}
}
gd->processing_msg = false;
return 0;
@ -224,10 +230,12 @@ static int log_dispatch(struct log_rec *rec)
int _log(enum log_category_t cat, enum log_level_t level, const char *file,
int line, const char *func, const char *fmt, ...)
{
char buf[CONFIG_SYS_CBSIZE];
struct log_rec rec;
va_list args;
if (!gd)
return -ENOSYS;
/* Check for message continuation */
if (cat == LOGC_CONT)
cat = gd->logc_prev;
@ -240,19 +248,29 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
rec.file = file;
rec.line = line;
rec.func = func;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
rec.msg = buf;
if (!gd || !(gd->flags & GD_FLG_LOG_READY)) {
if (gd)
gd->log_drop_count++;
rec.msg = NULL;
if (!(gd->flags & GD_FLG_LOG_READY)) {
gd->log_drop_count++;
/* display dropped traces with console puts and DEBUG_UART */
if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) {
char buf[CONFIG_SYS_CBSIZE];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
puts(buf);
va_end(args);
}
return -ENOSYS;
}
if (!log_dispatch(&rec)) {
va_start(args, fmt);
if (!log_dispatch(&rec, fmt, args)) {
gd->logc_prev = cat;
gd->logl_prev = level;
}
va_end(args);
return 0;
}

View File

@ -126,7 +126,7 @@ endmenu
config HANDOFF
bool "Pass hand-off information from SPL to U-Boot proper"
depends on BLOBLIST
depends on SPL && BLOBLIST
help
It is useful to be able to pass information from SPL to U-Boot
proper to preserve state that is known in SPL and is needed in U-Boot.

View File

@ -181,7 +181,7 @@ struct stdio_dev *stdio_get_by_name(const char *name)
* 'stdout', which may include a list of devices separate by
* commas. Obviously this is not going to work, so we ignore
* that case. The call path in that case is
* console_init_r() -> search_device() -> stdio_get_by_name()
* console_init_r() -> console_search_dev() -> stdio_get_by_name()
*/
if (!strncmp(name, "vidconsole", 10) && !strchr(name, ',') &&
!stdio_probe_device(name, UCLASS_VIDEO, &sdev))
@ -332,7 +332,7 @@ int stdio_add_devices(void)
/*
* If the console setting is not in environment variables then
* console_init_r() will not be calling iomux_doenv() (which
* calls search_device()). So we will not dynamically add
* calls console_search_dev()). So we will not dynamically add
* devices by calling stdio_probe_device().
*
* So just probe all video devices now so that whichever one is

View File

@ -18,6 +18,8 @@
#include <command.h>
#include <ide.h>
#include <memalign.h>
#include <asm/unaligned.h>
#include <linux/compiler.h>
#include "part_dos.h"
#include <part.h>
@ -29,22 +31,11 @@
* to use large numbers of partitions */
#define MAX_EXT_PARTS 256
/* Convert char[4] in little endian format to the host format integer
*/
static inline unsigned int le32_to_int(unsigned char *le32)
{
return ((le32[3] << 24) +
(le32[2] << 16) +
(le32[1] << 8) +
le32[0]
);
}
static inline int is_extended(int part_type)
{
return (part_type == 0x5 ||
part_type == 0xf ||
part_type == 0x85);
return (part_type == DOS_PART_TYPE_EXTENDED ||
part_type == DOS_PART_TYPE_EXTENDED_LBA ||
part_type == DOS_PART_TYPE_EXTENDED_LINUX);
}
static int get_bootable(dos_partition_t *p)
@ -61,8 +52,8 @@ static int get_bootable(dos_partition_t *p)
static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector,
int part_num, unsigned int disksig)
{
lbaint_t lba_start = ext_part_sector + le32_to_int (p->start4);
lbaint_t lba_size = le32_to_int (p->size4);
lbaint_t lba_start = ext_part_sector + get_unaligned_le32(p->start4);
lbaint_t lba_size = get_unaligned_le32(p->size4);
printf("%3d\t%-10" LBAFlength "u\t%-10" LBAFlength
"u\t%08x-%02x\t%02x%s%s\n",
@ -171,7 +162,7 @@ static void print_partition_extended(struct blk_desc *dev_desc,
}
if (!ext_part_sector)
disksig = le32_to_int(&buffer[DOS_PART_DISKSIG_OFFSET]);
disksig = get_unaligned_le32(&buffer[DOS_PART_DISKSIG_OFFSET]);
/* Print all primary/logical partitions */
pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
@ -198,7 +189,7 @@ static void print_partition_extended(struct blk_desc *dev_desc,
for (i = 0; i < 4; i++, pt++) {
if (is_extended (pt->sys_ind)) {
lbaint_t lba_start
= le32_to_int (pt->start4) + relative;
= get_unaligned_le32 (pt->start4) + relative;
print_partition_extended(dev_desc, lba_start,
ext_part_sector == 0 ? lba_start : relative,
@ -244,7 +235,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
if (!ext_part_sector)
disksig = le32_to_int(&buffer[DOS_PART_DISKSIG_OFFSET]);
disksig = get_unaligned_le32(&buffer[DOS_PART_DISKSIG_OFFSET]);
#endif
/* Print all primary/logical partitions */
@ -260,8 +251,8 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
(ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) {
info->blksz = DOS_PART_DEFAULT_SECTOR;
info->start = (lbaint_t)(ext_part_sector +
le32_to_int(pt->start4));
info->size = (lbaint_t)le32_to_int(pt->size4);
get_unaligned_le32(pt->start4));
info->size = (lbaint_t)get_unaligned_le32(pt->size4);
part_set_generic_name(dev_desc, part_num,
(char *)info->name);
/* sprintf(info->type, "%d, pt->sys_ind); */
@ -286,7 +277,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
for (i = 0; i < 4; i++, pt++) {
if (is_extended (pt->sys_ind)) {
lbaint_t lba_start
= le32_to_int (pt->start4) + relative;
= get_unaligned_le32 (pt->start4) + relative;
return part_get_info_extended(dev_desc, lba_start,
ext_part_sector == 0 ? lba_start : relative,
@ -312,13 +303,13 @@ static int part_get_info_extended(struct blk_desc *dev_desc,
return -1;
}
void part_print_dos(struct blk_desc *dev_desc)
static void __maybe_unused part_print_dos(struct blk_desc *dev_desc)
{
printf("Part\tStart Sector\tNum Sectors\tUUID\t\tType\n");
print_partition_extended(dev_desc, 0, 0, 1, 0);
}
int part_get_info_dos(struct blk_desc *dev_desc, int part,
static int __maybe_unused part_get_info_dos(struct blk_desc *dev_desc, int part,
struct disk_partition *info)
{
return part_get_info_extended(dev_desc, 0, 0, 1, part, info, 0);
@ -329,7 +320,174 @@ int is_valid_dos_buf(void *buf)
return test_block_type(buf) == DOS_MBR ? 0 : -1;
}
int write_mbr_partition(struct blk_desc *dev_desc, void *buf)
#if CONFIG_IS_ENABLED(CMD_MBR)
static void lba_to_chs(lbaint_t lba, unsigned char *rc, unsigned char *rh,
unsigned char *rs)
{
unsigned int c, h, s;
/* use fixed CHS geometry */
unsigned int sectpertrack = 63;
unsigned int heads = 255;
c = (lba + 1) / sectpertrack / heads;
h = (lba + 1) / sectpertrack - c * heads;
s = (lba + 1) - (c * heads + h) * sectpertrack;
if (c > 1023) {
c = 1023;
h = 254;
s = 63;
}
*rc = c & 0xff;
*rh = h;
*rs = s + ((c & 0x300) >> 2);
}
static void mbr_fill_pt_entry(dos_partition_t *pt, lbaint_t start,
lbaint_t relative, lbaint_t size, uchar sys_ind, bool bootable)
{
pt->boot_ind = bootable ? 0x80 : 0x00;
pt->sys_ind = sys_ind;
lba_to_chs(start, &pt->cyl, &pt->head, &pt->sector);
lba_to_chs(start + size - 1, &pt->end_cyl, &pt->end_head, &pt->end_sector);
put_unaligned_le32(relative, &pt->start4);
put_unaligned_le32(size, &pt->size4);
}
int write_mbr_partitions(struct blk_desc *dev,
struct disk_partition *p, int count, unsigned int disksig)
{
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev->blksz);
lbaint_t ext_part_start = 0, ext_part_size = 0, ext_part_sect = 0;
dos_partition_t *pt;
int i;
memset(buffer, 0, dev->blksz);
buffer[DOS_PART_MAGIC_OFFSET] = 0x55;
buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa;
put_unaligned_le32(disksig, &buffer[DOS_PART_DISKSIG_OFFSET]);
pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
/* create all primary partitions */
for (i = 0; i < 4 && i < count; i++, pt++) {
mbr_fill_pt_entry(pt, p[i].start, p[i].start, p[i].size,
p[i].sys_ind, p[i].bootable);
if (is_extended(p[i].sys_ind)) {
ext_part_start = p[i].start;
ext_part_size = p[i].size;
ext_part_sect = p[i].start;
}
}
if (i < count && !ext_part_start) {
printf("%s: extended partition is needed for more than 4 partitions\n",
__func__);
return -1;
}
/* write MBR */
if (blk_dwrite(dev, 0, 1, buffer) != 1) {
printf("%s: failed writing 'MBR' (1 blks at 0x0)\n",
__func__);
return -1;
}
/* create extended volumes */
for (; i < count; i++) {
lbaint_t next_ebr = 0;
memset(buffer, 0, dev->blksz);
buffer[DOS_PART_MAGIC_OFFSET] = 0x55;
buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa;
pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
mbr_fill_pt_entry(pt, p[i].start, p[i].start - ext_part_sect,
p[i].size, p[i].sys_ind, p[i].bootable);
if (i + 1 < count) {
pt++;
next_ebr = p[i].start + p[i].size;
mbr_fill_pt_entry(pt, next_ebr,
next_ebr - ext_part_start,
p[i+1].start + p[i+1].size - next_ebr,
DOS_PART_TYPE_EXTENDED, 0);
}
/* write EBR */
if (blk_dwrite(dev, ext_part_sect, 1, buffer) != 1) {
printf("%s: failed writing 'EBR' (1 blks at 0x%lx)\n",
__func__, ext_part_sect);
return -1;
}
ext_part_sect = next_ebr;
}
return 0;
}
int layout_mbr_partitions(struct disk_partition *p, int count,
lbaint_t total_sectors)
{
struct disk_partition *ext = NULL;
int i, j;
lbaint_t ext_vol_start;
/* calculate primary partitions start and size if needed */
if (!p[0].start)
p[0].start = DOS_PART_DEFAULT_GAP;
for (i = 0; i < 4 && i < count; i++) {
if (!p[i].start)
p[i].start = p[i - 1].start + p[i - 1].size;
if (!p[i].size) {
lbaint_t end = total_sectors;
lbaint_t allocated = 0;
for (j = i + 1; j < 4 && j < count; j++) {
if (p[j].start) {
end = p[j].start;
break;
}
allocated += p[j].size;
}
p[i].size = end - allocated - p[i].start;
}
if (p[i].sys_ind == 0x05)
ext = &p[i];
}
if (i >= 4 && !ext) {
printf("%s: extended partition is needed for more than 4 partitions\n",
__func__);
return -1;
}
/* calculate extended volumes start and size if needed */
ext_vol_start = ext->start;
for (i = 4; i < count; i++) {
if (!p[i].start)
p[i].start = ext_vol_start + DOS_PART_DEFAULT_GAP;
if (!p[i].size) {
lbaint_t end = ext->start + ext->size;
lbaint_t allocated = 0;
for (j = i + 1; j < count; j++) {
if (p[j].start) {
end = p[j].start - DOS_PART_DEFAULT_GAP;
break;
}
allocated += p[j].size + DOS_PART_DEFAULT_GAP;
}
p[i].size = end - allocated - p[i].start;
}
ext_vol_start = p[i].start + p[i].size;
}
return 0;
}
#endif
int write_mbr_sector(struct blk_desc *dev_desc, void *buf)
{
if (is_valid_dos_buf(buf))
return -1;

View File

@ -15,6 +15,11 @@
#define DOS_PBR_MEDIA_TYPE_OFFSET 0x15
#define DOS_MBR 0
#define DOS_PBR 1
#define DOS_PART_TYPE_EXTENDED 0x05
#define DOS_PART_TYPE_EXTENDED_LBA 0x0F
#define DOS_PART_TYPE_EXTENDED_LINUX 0x85
#define DOS_PART_DEFAULT_GAP 2048
typedef struct dos_partition {
unsigned char boot_ind; /* 0x80 - active */

View File

@ -14,4 +14,5 @@ Shell commands
bootefi
bootmenu
button
mbr
pstore

94
doc/usage/mbr.rst Normal file
View File

@ -0,0 +1,94 @@
.. SPDX-License-Identifier: GPL-2.0+
mbr command
===========
Synopsis
--------
::
mbr verify [interface] [device no] [partition list]
mbr write [interface] [device no] [partition list]
Description
-----------
The mbr command lets users create or verify the MBR (Master Boot Record)
partition layout based on the provided text description. The partition
layout is alternatively read from the 'mbr_parts' environment variable.
This can be used in scripts to help system image flashing tools to ensure
proper partition layout.
The syntax of the text description of the partition list is similar to
the one used by the 'gpt' command.
Supported partition parameters are:
* name (currently ignored)
* start (partition start offset in bytes)
* size (in bytes or '-' to expand it to the whole free area)
* bootable (boolean flag)
* id (MBR partition type)
If one wants to create more than 4 partitions, an 'Extended' primary
partition (with 0x05 ID) has to be explicitly provided as a one of the
first 4 entries.
Here is an example how to create a 6 partitions (3 on the 'extended
volume'), some of the predefined sizes:
::
=> setenv mbr_parts 'name=boot,start=4M,size=128M,bootable,id=0x0e;
name=rootfs,size=3072M,id=0x83;
name=system-data,size=512M,id=0x83;
name=[ext],size=-,id=0x05;
name=user,size=-,id=0x83;
name=modules,size=100M,id=0x83;
name=ramdisk,size=8M,id=0x83'
=> mbr write mmc 0
To check if the layout on the MMC #0 storage device matches the provided
text description one has to issue following command (assuming that
mbr_parts environment variable is set):
::
=> mbr verify mmc 0
The verify sub-command is especially useful in the system update scripts:
::
=> if mbr verify mmc 0; then
echo MBR layout needs to be updated
...
fi
The 'mbr write' command returns 0 on success write or 1 on failure.
The 'mbr verify' returns 0 if the layout matches the one on the storage
device or 1 if not.
Configuration
-------------
To use the mbr command you must specify CONFIG_CMD_MBR=y.
Return value
------------
The variable *$?* takes the following values
+---+------------------------------+
| 0 | mbr write was succesful |
+---+------------------------------+
| 1 | mbr write failed |
+---+------------------------------+
| 0 | mbr verify was succesful |
+---+------------------------------+
| 1 | mbr verify was not succesful |
+---+------------------------------+
|-1 | invalid arguments |
+---+------------------------------+

View File

@ -508,7 +508,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
fastboot_fail("invalid MBR partition", response);
return;
}
if (write_mbr_partition(dev_desc, download_buffer)) {
if (write_mbr_sector(dev_desc, download_buffer)) {
printf("%s: writing MBR partition failed\n", __func__);
fastboot_fail("writing MBR partition failed",
response);

View File

@ -105,7 +105,7 @@ int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /
sizeof(bb_miiphy_buses[0]);
#endif
void bb_miiphy_init(void)
int bb_miiphy_init(void)
{
int i;
@ -124,6 +124,8 @@ void bb_miiphy_init(void)
bb_miiphy_buses[i].init(&bb_miiphy_buses[i]);
}
}
return 0;
}
static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname)

View File

@ -1842,7 +1842,7 @@ U_BOOT_DRIVER(pci_generic_drv) = {
.of_match = pci_generic_ids,
};
void pci_init(void)
int pci_init(void)
{
struct udevice *bus;
@ -1855,4 +1855,6 @@ void pci_init(void)
uclass_next_device_check(&bus)) {
;
}
return 0;
}

View File

@ -454,16 +454,18 @@ int pci_hose_scan(struct pci_controller *hose)
return pci_hose_scan_bus(hose, hose->current_busno);
}
void pci_init(void)
int pci_init(void)
{
hose_head = NULL;
/* allow env to disable pci init/enum */
if (env_get("pcidisable") != NULL)
return;
return 0;
/* now call board specific pci_init()... */
pci_init_board();
return 0;
}
/* Returns the address of the requested capability structure within the

View File

@ -210,7 +210,7 @@ UCLASS_DRIVER(pci_ep) = {
.flags = DM_UC_FLAG_SEQ_ALIAS,
};
void pci_ep_init(void)
int pci_ep_init(void)
{
struct udevice *dev;
@ -219,4 +219,6 @@ void pci_ep_init(void)
uclass_next_device_check(&dev)) {
;
}
return 0;
}

View File

@ -232,7 +232,7 @@ void clear_evtchn(uint32_t port)
synch_clear_bit(port, &s->evtchn_pending[0]);
}
void xen_init(void)
int xen_init(void)
{
debug("%s\n", __func__);
@ -240,6 +240,8 @@ void xen_init(void)
init_events();
init_xenbus();
init_gnttab();
return 0;
}
void xen_fini(void)

View File

@ -7,6 +7,14 @@
#ifndef __API_H
#define __API_H
void api_init(void);
/**
* api_init() - Initialize API for external applications
*
* Initialize API for external (standalone) applications running on top of
* U-Boot. It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int api_init(void);
#endif

View File

@ -412,12 +412,12 @@ struct global_data {
* @new_bloblist: relocated blob list information
*/
struct bloblist_hdr *new_bloblist;
# ifdef CONFIG_SPL
#endif
#if CONFIG_IS_ENABLED(HANDOFF)
/**
* @spl_handoff: SPL hand-off information
*/
struct spl_handoff *spl_handoff;
# endif
#endif
#if defined(CONFIG_TRANSLATION_OFFSET)
/**

View File

@ -8,6 +8,7 @@
#define __CONSOLE_H
#include <stdbool.h>
#include <stdio_dev.h>
#include <linux/errno.h>
extern char console_buffer[];
@ -15,6 +16,8 @@ extern char console_buffer[];
/* common/console.c */
int console_init_f(void); /* Before relocation; uses the serial stuff */
int console_init_r(void); /* After relocation; uses the console stuff */
int console_start(int file, struct stdio_dev *sdev); /* Start a console device */
void console_stop(int file, struct stdio_dev *sdev); /* Stop a console device */
int console_assign(int file, const char *devname); /* Assign the console */
int ctrlc(void);
int had_ctrlc(void); /* have we had a Control-C since last clear? */
@ -22,6 +25,18 @@ void clear_ctrlc(void); /* clear the Control-C condition */
int disable_ctrlc(int); /* 1 to disable, 0 to enable Control-C detect */
int confirm_yesno(void); /* 1 if input is "y", "Y", "yes" or "YES" */
/**
* console_search_dev() - search for stdio device with given flags and name
* @flags: device flags as per input/output/system
* @name: device name
*
* Iterates over registered STDIO devices and match them with given @flags
* and @name.
*
* @return pointer to the &struct stdio_dev if found, or NULL otherwise
*/
struct stdio_dev *console_search_dev(int flags, const char *name);
#ifdef CONFIG_CONSOLE_RECORD
/**
* console_record_init() - set up the console recording buffers

View File

@ -15,8 +15,14 @@
struct cmd_tbl;
struct spi_slave;
/* Set up the jump table for use by the API */
void jumptable_init(void);
/**
* jumptable_init() - Set up the jump table for use by the API
*
* It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int jumptable_init(void);
/* These are declarations of exported functions available in C code */
unsigned long get_version(void);

View File

@ -163,6 +163,41 @@ int arch_setup_bdinfo(void);
*/
int setup_bdinfo(void);
/**
* cpu_secondary_init_r() - CPU-specific secondary initialization
*
* After non-volatile devices, environment and cpu code are setup, have
* another round to deal with any initialization that might require
* full access to the environment or loading of some image (firmware)
* from a non-volatile device.
*
* It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int cpu_secondary_init_r(void);
/**
* pci_ep_init() - Initialize pci endpoint devices
*
* It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int pci_ep_init(void);
/**
* pci_init() - Enumerate pci devices
*
* It is called during the generic post-relocation init sequence to enumerate
* pci buses. This is needed, for instance, in the case of DM PCI-based
* Ethernet devices, which will not be detected without having the enumeration
* performed earlier.
*
* Return: 0 if OK
*/
int pci_init(void);
/**
* init_cache_f_r() - Turn on the cache in preparation for relocation
*
@ -234,8 +269,6 @@ int mac_read_from_eeprom(void);
int set_cpu_clk_info(void);
int update_flash_size(int flash_size);
int arch_early_init_r(void);
void pci_init(void);
void pci_ep_init(void);
int misc_init_r(void);
#if defined(CONFIG_VID)
int init_func_vid(void);
@ -267,7 +300,15 @@ int board_early_init_r(void);
/* TODO(sjg@chromium.org): Drop this when DM_PCI migration is completed */
void pci_init_board(void);
void trap_init(unsigned long reloc_addr);
/**
* arch_initr_trap() - Init traps
*
* Arch specific routine for initializing traps. It is called during the
* generic board init sequence, after relocation.
*
* Return: 0 if OK
*/
int arch_initr_trap(void);
/**
* main_loop() - Enter the main loop of U-Boot

View File

@ -26,6 +26,5 @@ extern int cd_count[MAX_FILES];
int iomux_doenv(const int, const char *);
void iomux_printdevs(const int);
struct stdio_dev *search_device(int, const char *);
#endif /* _IO_MUX_H */

View File

@ -81,7 +81,15 @@ struct bb_miiphy_bus {
extern struct bb_miiphy_bus bb_miiphy_buses[];
extern int bb_miiphy_buses_num;
void bb_miiphy_init(void);
/**
* bb_miiphy_init() - Initialize bit-banged MII bus driver
*
* It is called during the generic post-relocation init sequence.
*
* Return: 0 if OK
*/
int bb_miiphy_init(void);
int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg);
int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
u16 value);

View File

@ -465,14 +465,19 @@ int get_disk_guid(struct blk_desc *dev_desc, char *guid);
int is_valid_dos_buf(void *buf);
/**
* write_mbr_partition() - write DOS MBR
* write_mbr_sector() - write DOS MBR
*
* @param dev_desc - block device descriptor
* @param buf - buffer which contains the MBR
*
* @return - '0' on success, otherwise error
*/
int write_mbr_partition(struct blk_desc *dev_desc, void *buf);
int write_mbr_sector(struct blk_desc *dev_desc, void *buf);
int write_mbr_partitions(struct blk_desc *dev,
struct disk_partition *p, int count, unsigned int disksig);
int layout_mbr_partitions(struct disk_partition *p, int count,
lbaint_t total_sectors);
#endif

View File

@ -107,7 +107,6 @@ int post_init_f (void);
void post_bootmode_init (void);
int post_bootmode_get (unsigned int * last_test);
void post_bootmode_clear (void);
void post_output_backlog ( void );
int post_run (char *name, int flags);
int post_info (char *name);
int post_log (char *format, ...);
@ -116,6 +115,16 @@ void post_reloc (void);
#endif
unsigned long post_time_ms (unsigned long base);
/**
* post_output_backlog() - Print POST results
*
* Print POST results during the generic board init sequence, after
* relocation.
*
* Return: 0 if OK
*/
int post_output_backlog(void);
extern struct post_test post_list[];
extern unsigned int post_list_size;
extern int post_hotkeys_pressed(void);

View File

@ -11,7 +11,7 @@
* Map Xen memory pages, initialize event handler and xenbus,
* setup the grant table.
*/
void xen_init(void);
int xen_init(void);
/**
* xen_fini() - Board cleanup before Linux kernel start

View File

@ -128,7 +128,7 @@ static void post_log_mark_succ(unsigned long testid)
}
/* ... and the messages are output once we are relocated */
void post_output_backlog(void)
int post_output_backlog(void)
{
int j;
@ -143,6 +143,8 @@ void post_output_backlog(void)
}
}
}
return 0;
}
static void post_bootmode_test_on(unsigned int last_test)

View File

@ -15,29 +15,44 @@
DECLARE_GLOBAL_DATA_PTR;
/* emit some sample log records in different ways, for testing */
static int do_log_run(int cat, const char *file)
static int do_log_run(struct unit_test_state *uts, int cat, const char *file)
{
int i;
int ret, expected_ret;
if (gd->flags & GD_FLG_LOG_READY)
expected_ret = 0;
else
expected_ret = -ENOSYS;
gd->log_fmt = LOGF_TEST;
debug("debug\n");
for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
log(cat, i, "log %d\n", i);
_log(log_uc_cat(cat), i, file, 100 + i, "func", "_log %d\n",
i);
ret = _log(log_uc_cat(cat), i, file, 100 + i,
"func", "_log %d\n", i);
ut_asserteq(ret, expected_ret);
}
/* test with LOGL_COUNT flag */
for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
ret = _log(log_uc_cat(cat), i | LOGL_FORCE_DEBUG, file, 100 + i,
"func", "_log force %d\n", i);
ut_asserteq(ret, expected_ret);
}
gd->log_fmt = log_get_default_format();
return 0;
}
#define log_run_cat(cat) do_log_run(cat, "file")
#define log_run_file(file) do_log_run(UCLASS_SPI, file)
#define log_run() do_log_run(UCLASS_SPI, "file")
#define log_run_cat(cat) do_log_run(uts, cat, "file")
#define log_run_file(file) do_log_run(uts, UCLASS_SPI, file)
#define log_run() do_log_run(uts, UCLASS_SPI, "file")
#define EXPECT_LOG BIT(0)
#define EXPECT_DIRECT BIT(1)
#define EXPECT_EXTRA BIT(2)
#define EXPECT_FORCE BIT(3)
#define EXPECT_DEBUG BIT(4)
static int do_check_log_entries(struct unit_test_state *uts, int flags, int min,
int max)
@ -49,11 +64,22 @@ static int do_check_log_entries(struct unit_test_state *uts, int flags, int min,
ut_assert_nextline("do_log_run() log %d", i);
if (flags & EXPECT_DIRECT)
ut_assert_nextline("func() _log %d", i);
if (flags & EXPECT_DEBUG) {
ut_assert_nextline("log %d", i);
ut_assert_nextline("_log %d", i);
}
}
if (flags & EXPECT_EXTRA)
for (; i <= LOGL_MAX ; i++)
ut_assert_nextline("func() _log %d", i);
for (i = LOGL_FIRST; i < LOGL_COUNT; i++) {
if (flags & EXPECT_FORCE)
ut_assert_nextline("func() _log force %d", i);
if (flags & EXPECT_DEBUG)
ut_assert_nextline("_log force %d", i);
}
ut_assert_console_end();
return 0;
}
@ -66,10 +92,10 @@ static int do_check_log_entries(struct unit_test_state *uts, int flags, int min,
#define check_log_entries_flags(flags) \
check_log_entries_flags_levels(flags, LOGL_FIRST, _LOG_MAX_LEVEL)
#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT)
#define check_log_entries() check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE)
#define check_log_entries_extra() \
check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA)
#define check_log_entries_none() check_log_entries_flags(0)
check_log_entries_flags(EXPECT_LOG | EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE)
#define check_log_entries_none() check_log_entries_flags(EXPECT_FORCE)
/* Check a category filter using the first category */
int log_test_cat_allow(struct unit_test_state *uts)
@ -126,7 +152,7 @@ int log_test_file(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
log_run_file("file");
check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE);
ut_assertok(console_record_reset_enable());
log_run_file("file2");
@ -147,7 +173,7 @@ int log_test_file_second(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
log_run_file("file2");
check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA);
check_log_entries_flags(EXPECT_DIRECT | EXPECT_EXTRA | EXPECT_FORCE);
ut_assertok(log_remove_filter("console", filt));
return 0;
@ -182,8 +208,8 @@ int log_test_level(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
log_run();
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT, LOGL_FIRST,
LOGL_WARNING);
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
LOGL_FIRST, LOGL_WARNING);
ut_assertok(log_remove_filter("console", filt));
return 0;
@ -351,7 +377,7 @@ int log_test_level_deny(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
log_run();
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
LOGL_WARNING + 1, _LOG_MAX_LEVEL);
ut_assertok(log_remove_filter("console", filt1));
@ -374,7 +400,7 @@ int log_test_min(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
log_run();
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT,
check_log_entries_flags_levels(EXPECT_LOG | EXPECT_DIRECT | EXPECT_FORCE,
LOGL_WARNING, LOGL_INFO - 1);
ut_assertok(log_remove_filter("console", filt1));
@ -382,3 +408,23 @@ int log_test_min(struct unit_test_state *uts)
return 0;
}
LOG_TEST_FLAGS(log_test_min, UT_TESTF_CONSOLE_REC);
/* Check dropped traces */
int log_test_dropped(struct unit_test_state *uts)
{
/* force LOG not ready */
gd->flags &= ~(GD_FLG_LOG_READY);
gd->log_drop_count = 0;
ut_assertok(console_record_reset_enable());
log_run();
ut_asserteq(gd->log_drop_count, 3 * (LOGL_COUNT - LOGL_FIRST - 1));
check_log_entries_flags_levels(EXPECT_DEBUG, LOGL_FIRST, CONFIG_LOG_DEFAULT_LEVEL);
gd->flags |= GD_FLG_LOG_READY;
gd->log_drop_count = 0;
return 0;
}
LOG_TEST_FLAGS(log_test_dropped, UT_TESTF_CONSOLE_REC);

View File

@ -36,3 +36,14 @@ def test_log_format(u_boot_console):
run_with_format('FLfm', 'file.c:123-func() msg')
run_with_format('lm', 'NOTICE. msg')
run_with_format('m', 'msg')
@pytest.mark.buildconfigspec('debug_uart')
@pytest.mark.boardspec('sandbox')
def test_log_dropped(u_boot_console):
"""Test dropped 'log' message when debug_uart is activated"""
cons = u_boot_console
cons.restart_uboot()
output = cons.get_spawn_output().replace('\r', '')
assert 'sandbox: starting...' in output
assert (not 'debug: main' in output)