Files
u-boot/arch/sandbox/include/asm/state.h
Simon Glass b4f6fdbcd2 sandbox: Add -M option to disable mcheck at runtime
Add a command-line option (-M or --no_mcheck) to disable mcheck heap
protection at runtime. When mcheck is disabled, the wrapper functions
pass through directly to the underlying allocator without adding
headers or checking for corruption.

This is useful for debugging when mcheck interferes with test results,
such as when memory-leak detection reports false positives due to
accumulated allocations from other tests.

Changes:
- Add disable_mcheck flag to sandbox_state
- Add mcheck_set_disabled() function to mcheck API
- Modify dlmalloc wrappers to bypass mcheck when disabled
- Add stub for when MCHECK_HEAP_PROTECTION is not enabled
- Document the new option in sandbox.rst

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-03 12:39:14 -07:00

418 lines
13 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2011-2012 The Chromium OS Authors.
*/
#ifndef __SANDBOX_STATE_H
#define __SANDBOX_STATE_H
#include <alist.h>
#include <sysreset.h>
#include <stdbool.h>
#include <linux/list.h>
#include <linux/stringify.h>
enum sandboxio_size_t;
enum {
SB_MAX_BINDS = 4,
};
/**
* Selects the behavior of the serial terminal.
*
* If Ctrl-C is processed by U-Boot, then the only way to quit sandbox is with
* the 'reset' command, or equivalent.
*
* If the terminal is cooked, then Ctrl-C will terminate U-Boot, and the
* command line will not be quite such a faithful emulation.
*
* Options are:
*
* raw-with-sigs - Raw, but allow signals (Ctrl-C will quit)
* raw - Terminal is always raw
* cooked - Terminal is always cooked
*/
enum state_terminal_raw {
STATE_TERM_RAW_WITH_SIGS, /* Default */
STATE_TERM_RAW,
STATE_TERM_COOKED,
STATE_TERM_COUNT,
};
struct sandbox_spi_info {
struct udevice *emul;
};
struct sandbox_wdt_info {
unsigned long long counter;
uint reset_count;
bool running;
};
/**
* struct sandbox_mapmem_entry - maps pointers to/from U-Boot addresses
*
* When map_to_sysmem() is called with an address outside sandbox's emulated
* RAM, a record is created with a tag that can be used to reference that
* pointer. When map_sysmem() is called later with that tag, the pointer will
* be returned, just as it would for a normal sandbox address.
*
* @tag: Address tag (a value which U-Boot uses to refer to the address)
* @refcnt: Number of references to this tag
* @ptr: Associated pointer for that tag
* @sibling_node: Next node
*/
struct sandbox_mapmem_entry {
ulong tag;
uint refcnt;
void *ptr;
struct list_head sibling_node;
};
/**
* sandbox_read() - Read function for sandbox_mmio
*
* @addr: Pointer to read from
* @size: Access size of read
* Return: Value obtained
*/
typedef long (*sandbox_mmio_read_func)(void *ctx, const void *addr,
enum sandboxio_size_t size);
/**
* sandbox_write() - Write function for sandbox_mmio
*
* @addr: Pointer to write to
* @val: Value to write
* @size: Access size of write
*/
typedef void (*sandbox_mmio_write_func)(void *ctx, void *addr, unsigned int val,
enum sandboxio_size_t size);
/**
* sandbox_mmio_add() - Add a new MMIO region
*
* Register a new set of read/write functions to be called for a particular
* memory region
*
* @base: Base pointer for region
* @size: Size of region
* @h_read: Read handler
* @h_write: Write handler
* @ctx: Context pointer to passed to read/write functions
*/
int sandbox_mmio_add(void *base, ulong size, sandbox_mmio_read_func h_read,
sandbox_mmio_write_func h_write, void *ctx);
/**
* sandbox_mmio_remove() - Remove an MMIO region
*
* All regions with the given @ctx are removed
*
* @ctx: Context to search for
*/
void sandbox_mmio_remove(void *ctx);
/**
* struct sandbox_mmio - defines a region of memory-mapped I/O
*
* This allows accesses to a region of memory to go through provided functions
*
* @base: Base pointer of region
* @size: Size of region
* @h_read: Read handler
* @h_write: Write handler
* @ctx: Context pointer provided when registering
*/
struct sandbox_mmio {
void *base;
ulong size;
sandbox_mmio_read_func h_read;
sandbox_mmio_write_func h_write;
void *ctx;
};
/* The complete state of the test system */
struct sandbox_state {
const char *cmd; /* Command to execute */
bool interactive; /* Enable cmdline after execute */
bool run_distro_boot; /* Automatically run distro bootcommands */
const char *fdt_fname; /* Filename of FDT binary */
const char *parse_err; /* Error to report from parsing */
int argc; /* Program arguments */
char **argv; /* Command line arguments */
const char *jumped_fname; /* Jumped from previous U-Boot */
const char *prog_fname; /* U-Boot executable filename */
uint8_t *ram_buf; /* Emulated RAM buffer */
unsigned long ram_size; /* Size of RAM buffer */
const char *ram_buf_fname; /* Filename to use for RAM buffer */
bool ram_buf_rm; /* Remove RAM buffer file after read */
bool write_ram_buf; /* Write RAM buffer on exit */
const char *state_fname; /* File containing sandbox state */
void *state_fdt; /* Holds saved state for sandbox */
bool read_state; /* Read sandbox state on startup */
bool write_state; /* Write sandbox state on exit */
bool ignore_missing_state_on_read; /* No error if state missing */
bool show_lcd; /* Show LCD on start-up */
bool double_lcd; /* Double display size for high-DPI */
bool serial_is_tty; /* Serial console is connected to a tty */
enum sysreset_t last_sysreset; /* Last system reset type */
bool sysreset_allowed[SYSRESET_COUNT]; /* Allowed system reset types */
enum state_terminal_raw term_raw; /* Terminal raw/cooked */
bool skip_delays; /* Ignore any time delays (for test) */
bool show_test_output; /* Don't suppress stdout in tests */
int default_log_level; /* Default log level for sandbox */
bool ram_buf_read; /* true if we read the RAM buffer */
bool run_unittests; /* Run unit tests */
const char *select_unittests; /* Unit test to run */
bool handle_signals; /* Handle signals within sandbox */
bool autoboot_keyed; /* Use keyed-autoboot feature */
bool disable_eth; /* Disable Ethernet devices */
bool disable_sf_bootdevs; /* Don't bind SPI flash bootdevs */
bool upl; /* Enable Universal Payload (UPL) */
bool native; /* Adjust to reflect host arch */
bool no_flattree_tests; /* Don't run second set of DM tests */
bool soft_fail; /* Continue on failure */
bool pager_bypass; /* Enable pager-bypass mode */
bool no_term_present; /* Assume no terminal present */
bool quiet_vidconsole; /* Don't use vidconsole for stdout */
bool disable_mcheck; /* Disable mcheck heap protection */
int video_test; /* ms to wait before next assert */
const char *video_frames_dir; /* Directory to write video frames */
int video_frame_count; /* Number of frames written */
/* Pointer to information for each SPI bus/cs */
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
[CONFIG_SANDBOX_SPI_MAX_CS];
/* Information about Watchdog */
struct sandbox_wdt_info wdt;
ulong next_tag; /* Next address tag to allocate */
struct list_head mapmem_head; /* struct sandbox_mapmem_entry */
bool hwspinlock; /* Hardware Spinlock status */
bool allow_memio; /* Allow readl() etc. to work */
/* Title to use for LCD window, NULL for default */
const char *window_title;
void *other_fdt_buf; /* 'other' FDT blob used by tests */
int other_size; /* size of other FDT blob */
const char *binds[SB_MAX_BINDS]; /* list of -B arguments */
int num_binds; /* number of -B arguments */
struct alist mmio; /* list of struct sandbox_mmio */
/*
* This struct is getting large.
*
* Consider putting test data in driver-private structs, like
* sandbox_pch.c.
*
* If you add new members, please put them above this comment.
*/
};
/* Minimum space we guarantee in the state FDT when calling read/write*/
#define SANDBOX_STATE_MIN_SPACE 0x1000
/**
* struct sandbox_state_io - methods to saved/restore sandbox state
* @name: Name of of the device tree node, also the name of the variable
* holding this data so it should be an identifier (use underscore
* instead of minus)
* @compat: Compatible string for the node containing this state
*
* @read: Function to read state from FDT
* If data is available, then blob and node will provide access to it. If
* not (blob == NULL and node == -1) this function should set up an empty
* data set for start-of-day.
* @param blob: Pointer to device tree blob, or NULL if no data to read
* @param node: Node offset to read from
* Return: 0 if OK, -ve on error
*
* @write: Function to write state to FDT
* The caller will ensure that there is a node ready for the state. The
* node may already contain the old state, in which case it should be
* overridden. There is guaranteed to be SANDBOX_STATE_MIN_SPACE bytes
* of free space, so error checking is not required for fdt_setprop...()
* calls which add up to less than this much space.
*
* For adding larger properties, use state_setprop().
*
* @param blob: Device tree blob holding state
* @param node: Node to write our state into
*
* Note that it is possible to save data as large blobs or as individual
* hierarchical properties. However, unless you intend to keep state files
* around for a long time and be able to run an old state file on a new
* sandbox, it might not be worth using individual properties for everything.
* This is certainly supported, it is just a matter of the effort you wish
* to put into the state read/write feature.
*/
struct sandbox_state_io {
const char *name;
const char *compat;
int (*write)(void *blob, int node);
int (*read)(const void *blob, int node);
};
/**
* SANDBOX_STATE_IO - Declare sandbox state to read/write
*
* Sandbox permits saving state from one run and restoring it in another. This
* allows the test system to retain state between runs and thus better
* emulate a real system. Examples of state that might be useful to save are
* the emulated GPIOs pin settings, flash memory contents and TPM private
* data. U-Boot memory contents is dealth with separately since it is large
* and it is not normally useful to save it (since a normal system does not
* preserve DRAM between runs). See the '-m' option for this.
*
* See struct sandbox_state_io above for member documentation.
*/
#define SANDBOX_STATE_IO(_name, _compat, _read, _write) \
ll_entry_declare(struct sandbox_state_io, _name, state_io) = { \
.name = __stringify(_name), \
.read = _read, \
.write = _write, \
.compat = _compat, \
}
/**
* Gets a pointer to the current state.
*
* Return: pointer to state
*/
struct sandbox_state *state_get_current(void);
/**
* Read the sandbox state from the supplied device tree file
*
* This calls all registered state handlers to read in the sandbox state
* from a previous test run.
*
* @param state Sandbox state to update
* @param fname Filename of device tree file to read from
* Return: 0 if OK, -ve on error
*/
int sandbox_read_state(struct sandbox_state *state, const char *fname);
/**
* Write the sandbox state to the supplied device tree file
*
* This calls all registered state handlers to write out the sandbox state
* so that it can be preserved for a future test run.
*
* If the file exists it is overwritten.
*
* @param state Sandbox state to update
* @param fname Filename of device tree file to write to
* Return: 0 if OK, -ve on error
*/
int sandbox_write_state(struct sandbox_state *state, const char *fname);
/**
* Add a property to a sandbox state node
*
* This is equivalent to fdt_setprop except that it automatically enlarges
* the device tree if necessary. That means it is safe to write any amount
* of data here.
*
* This function can only be called from within struct sandbox_state_io's
* ->write method, i.e. within state I/O drivers.
*
* @param node Device tree node to write to
* @param prop_name Property to write
* @param data Data to write into property
* @param size Size of data to write into property
*/
int state_setprop(int node, const char *prop_name, const void *data, int size);
/**
* Control skipping of time delays
*
* Some tests have unnecessay time delays (e.g. USB). Allow these to be
* skipped to speed up testing
*
* @param skip_delays true to skip delays from now on, false to honour delay
* requests
*/
void state_set_skip_delays(bool skip_delays);
/**
* See if delays should be skipped
*
* Return: true if delays should be skipped, false if they should be honoured
*/
bool state_get_skip_delays(void);
/**
* state_reset_for_test() - Reset ready to re-run tests
*
* This clears out any test state ready for another test run.
*/
void state_reset_for_test(struct sandbox_state *state);
/**
* state_show() - Show information about the sandbox state
*
* @param state Sandbox state to show
*/
void state_show(struct sandbox_state *state);
/**
* state_get_rel_filename() - Get a filename relative to the executable
*
* This uses argv[0] to obtain a filename path
*
* @rel_path: Relative path to build, e.g. "arch/sandbox/dts/test.dtb". Must not
* have a trailing /
* @buf: Buffer to use to return the filename
* @size: Size of buffer
* @return length of filename (including terminator), -ENOSPC if @size is too
* small
*/
int state_get_rel_filename(const char *rel_path, char *buf, int size);
/**
* state_load_other_fdt() - load the 'other' FDT into a buffer
*
* This loads the other.dtb file into a buffer. This is typically used in tests.
*
* @bufp: Place to put allocated buffer pointer. The buffer is read using
* os_read_file() which calls os_malloc(), so does affect U-Boot's own malloc()
* space
* @sizep: Returns the size of the buffer
* @return 0 if OK, -ve on error
*/
int state_load_other_fdt(const char **bufp, int *sizep);
/**
* sandbox_serial_is_tty() - check if serial console is connected to a tty
*
* Return: true if serial console is connected to a terminal, false if not
*/
bool sandbox_serial_is_tty(void);
/*
* sandbox_video_is_visible() - check if video display is showing
*
* Return: true if display is active, false if just using the serial console
*/
bool sandbox_video_is_visible(void);
/**
* Initialize the test system state
*/
int state_init(void);
/**
* Uninitialize the test system state, writing out state if configured to
* do so.
*
* Return: 0 if OK, -ve on error
*/
int state_uninit(void);
#endif