Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
88c5c68ffa
105
README
105
README
@ -815,6 +815,8 @@ The following options need to be configured:
|
||||
CONFIG_CMD_EDITENV edit env variable
|
||||
CONFIG_CMD_EEPROM * EEPROM read/write support
|
||||
CONFIG_CMD_ELF * bootelf, bootvx
|
||||
CONFIG_CMD_ENV_CALLBACK * display details about env callbacks
|
||||
CONFIG_CMD_ENV_FLAGS * display details about env flags
|
||||
CONFIG_CMD_EXPORTENV * export the environment
|
||||
CONFIG_CMD_EXT2 * ext2 command support
|
||||
CONFIG_CMD_EXT4 * ext4 command support
|
||||
@ -824,8 +826,10 @@ The following options need to be configured:
|
||||
CONFIG_CMD_FDOS * Dos diskette Support
|
||||
CONFIG_CMD_FLASH flinfo, erase, protect
|
||||
CONFIG_CMD_FPGA FPGA device initialization support
|
||||
CONFIG_CMD_GETTIME * Get time since boot
|
||||
CONFIG_CMD_GO * the 'go' command (exec code)
|
||||
CONFIG_CMD_GREPENV * search environment
|
||||
CONFIG_CMD_HASH * calculate hash / digest
|
||||
CONFIG_CMD_HWFLOW * RTS/CTS hw flow control
|
||||
CONFIG_CMD_I2C * I2C serial bus support
|
||||
CONFIG_CMD_IDE * IDE harddisk support
|
||||
@ -860,6 +864,7 @@ The following options need to be configured:
|
||||
CONFIG_CMD_PING * send ICMP ECHO_REQUEST to network
|
||||
host
|
||||
CONFIG_CMD_PORTIO * Port I/O
|
||||
CONFIG_CMD_READ * Read raw data from partition
|
||||
CONFIG_CMD_REGINFO * Register dump
|
||||
CONFIG_CMD_RUN run command in env variable
|
||||
CONFIG_CMD_SAVES * save S record dump
|
||||
@ -1485,6 +1490,11 @@ CBFS (Coreboot Filesystem) support
|
||||
|
||||
Support drawing of RLE8-compressed bitmaps on the LCD.
|
||||
|
||||
CONFIG_I2C_EDID
|
||||
|
||||
Enables an 'i2c edid' command which can read EDID
|
||||
information over I2C from an attached LCD display.
|
||||
|
||||
|
||||
- Splash Screen Support: CONFIG_SPLASH_SCREEN
|
||||
|
||||
@ -2179,6 +2189,11 @@ CBFS (Coreboot Filesystem) support
|
||||
serial# is unaffected by this, i. e. it remains
|
||||
read-only.]
|
||||
|
||||
The same can be accomplished in a more flexible way
|
||||
for any variable by configuring the type of access
|
||||
to allow for those variables in the ".flags" variable
|
||||
or define CONFIG_ENV_FLAGS_LIST_STATIC.
|
||||
|
||||
- Protected RAM:
|
||||
CONFIG_PRAM
|
||||
|
||||
@ -2409,6 +2424,23 @@ CBFS (Coreboot Filesystem) support
|
||||
A better solution is to properly configure the firewall,
|
||||
but sometimes that is not allowed.
|
||||
|
||||
- Hashing support:
|
||||
CONFIG_CMD_HASH
|
||||
|
||||
This enables a generic 'hash' command which can produce
|
||||
hashes / digests from a few algorithms (e.g. SHA1, SHA256).
|
||||
|
||||
CONFIG_HASH_VERIFY
|
||||
|
||||
Enable the hash verify command (hash -v). This adds to code
|
||||
size a little.
|
||||
|
||||
CONFIG_SHA1 - support SHA1 hashing
|
||||
CONFIG_SHA256 - support SHA256 hashing
|
||||
|
||||
Note: There is also a sha1sum command, which should perhaps
|
||||
be deprecated in favour of 'hash sha1'.
|
||||
|
||||
- Show boot progress:
|
||||
CONFIG_SHOW_BOOT_PROGRESS
|
||||
|
||||
@ -3087,6 +3119,49 @@ Configuration Settings:
|
||||
cases. This setting can be used to tune behaviour; see
|
||||
lib/hashtable.c for details.
|
||||
|
||||
- CONFIG_ENV_FLAGS_LIST_DEFAULT
|
||||
- CONFIG_ENV_FLAGS_LIST_STATIC
|
||||
Enable validation of the values given to enviroment variables when
|
||||
calling env set. Variables can be restricted to only decimal,
|
||||
hexadecimal, or boolean. If CONFIG_CMD_NET is also defined,
|
||||
the variables can also be restricted to IP address or MAC address.
|
||||
|
||||
The format of the list is:
|
||||
type_attribute = [s|d|x|b|i|m]
|
||||
access_atribute = [a|r|o|c]
|
||||
attributes = type_attribute[access_atribute]
|
||||
entry = variable_name[:attributes]
|
||||
list = entry[,list]
|
||||
|
||||
The type attributes are:
|
||||
s - String (default)
|
||||
d - Decimal
|
||||
x - Hexadecimal
|
||||
b - Boolean ([1yYtT|0nNfF])
|
||||
i - IP address
|
||||
m - MAC address
|
||||
|
||||
The access attributes are:
|
||||
a - Any (default)
|
||||
r - Read-only
|
||||
o - Write-once
|
||||
c - Change-default
|
||||
|
||||
- CONFIG_ENV_FLAGS_LIST_DEFAULT
|
||||
Define this to a list (string) to define the ".flags"
|
||||
envirnoment variable in the default or embedded environment.
|
||||
|
||||
- CONFIG_ENV_FLAGS_LIST_STATIC
|
||||
Define this to a list (string) to define validation that
|
||||
should be done if an entry is not found in the ".flags"
|
||||
environment variable. To override a setting in the static
|
||||
list, simply add an entry for the same variable name to the
|
||||
".flags" variable.
|
||||
|
||||
- CONFIG_ENV_ACCESS_IGNORE_FORCE
|
||||
If defined, don't allow the -f switch to env set override variable
|
||||
access flags.
|
||||
|
||||
The following definitions that deal with the placement and management
|
||||
of environment data (variable area); in general, we support the
|
||||
following configurations:
|
||||
@ -4188,6 +4263,36 @@ Please note that changes to some configuration parameters may take
|
||||
only effect after the next boot (yes, that's just like Windoze :-).
|
||||
|
||||
|
||||
Callback functions for environment variables:
|
||||
---------------------------------------------
|
||||
|
||||
For some environment variables, the behavior of u-boot needs to change
|
||||
when their values are changed. This functionailty allows functions to
|
||||
be associated with arbitrary variables. On creation, overwrite, or
|
||||
deletion, the callback will provide the opportunity for some side
|
||||
effect to happen or for the change to be rejected.
|
||||
|
||||
The callbacks are named and associated with a function using the
|
||||
U_BOOT_ENV_CALLBACK macro in your board or driver code.
|
||||
|
||||
These callbacks are associated with variables in one of two ways. The
|
||||
static list can be added to by defining CONFIG_ENV_CALLBACK_LIST_STATIC
|
||||
in the board configuration to a string that defines a list of
|
||||
associations. The list must be in the following format:
|
||||
|
||||
entry = variable_name[:callback_name]
|
||||
list = entry[,list]
|
||||
|
||||
If the callback name is not specified, then the callback is deleted.
|
||||
Spaces are also allowed anywhere in the list.
|
||||
|
||||
Callbacks can also be associated by defining the ".callbacks" variable
|
||||
with the same list format above. Any association in ".callbacks" will
|
||||
override any association in the static list. You can define
|
||||
CONFIG_ENV_CALLBACK_LIST_DEFAULT to a list (string) to define the
|
||||
".callbacks" envirnoment variable in the default or embedded environment.
|
||||
|
||||
|
||||
Command Line Parsing:
|
||||
=====================
|
||||
|
||||
|
@ -333,6 +333,8 @@ uint32_t mxc_get_clock(enum mxc_clock clk)
|
||||
return mx28_get_sspclk(MXC_SSPCLK2);
|
||||
case MXC_SSP3_CLK:
|
||||
return mx28_get_sspclk(MXC_SSPCLK3);
|
||||
case MXC_XTAL_CLK:
|
||||
return XTAL_FREQ_KHZ * 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -732,6 +732,21 @@ static unsigned long exynos5_get_i2c_clk(void)
|
||||
return aclk_66;
|
||||
}
|
||||
|
||||
static unsigned long exynos4_get_i2c_clk(void)
|
||||
{
|
||||
struct exynos4_clock *clk =
|
||||
(struct exynos4_clock *)samsung_get_base_clock();
|
||||
unsigned long sclk, aclk_100;
|
||||
unsigned int ratio;
|
||||
|
||||
sclk = get_pll_clk(APLL);
|
||||
|
||||
ratio = (readl(&clk->div_top)) >> 4;
|
||||
ratio &= 0xf;
|
||||
aclk_100 = sclk / (ratio + 1);
|
||||
return aclk_100;
|
||||
}
|
||||
|
||||
unsigned long get_pll_clk(int pllreg)
|
||||
{
|
||||
if (cpu_is_exynos5())
|
||||
@ -752,6 +767,8 @@ unsigned long get_i2c_clk(void)
|
||||
{
|
||||
if (cpu_is_exynos5()) {
|
||||
return exynos5_get_i2c_clk();
|
||||
} else if (cpu_is_exynos4()) {
|
||||
return exynos4_get_i2c_clk();
|
||||
} else {
|
||||
debug("I2C clock is not set for this CPU\n");
|
||||
return 0;
|
||||
|
@ -265,10 +265,74 @@ static int exynos5_pinmux_config(int peripheral, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos4_i2c_config(int peripheral, int flags)
|
||||
{
|
||||
struct exynos4_gpio_part1 *gpio1 =
|
||||
(struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1();
|
||||
|
||||
switch (peripheral) {
|
||||
case PERIPH_ID_I2C0:
|
||||
s5p_gpio_cfg_pin(&gpio1->d1, 0, GPIO_FUNC(0x2));
|
||||
s5p_gpio_cfg_pin(&gpio1->d1, 1, GPIO_FUNC(0x2));
|
||||
break;
|
||||
case PERIPH_ID_I2C1:
|
||||
s5p_gpio_cfg_pin(&gpio1->d1, 2, GPIO_FUNC(0x2));
|
||||
s5p_gpio_cfg_pin(&gpio1->d1, 3, GPIO_FUNC(0x2));
|
||||
break;
|
||||
case PERIPH_ID_I2C2:
|
||||
s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3));
|
||||
s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3));
|
||||
break;
|
||||
case PERIPH_ID_I2C3:
|
||||
s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3));
|
||||
s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3));
|
||||
break;
|
||||
case PERIPH_ID_I2C4:
|
||||
s5p_gpio_cfg_pin(&gpio1->b, 2, GPIO_FUNC(0x3));
|
||||
s5p_gpio_cfg_pin(&gpio1->b, 3, GPIO_FUNC(0x3));
|
||||
break;
|
||||
case PERIPH_ID_I2C5:
|
||||
s5p_gpio_cfg_pin(&gpio1->b, 6, GPIO_FUNC(0x3));
|
||||
s5p_gpio_cfg_pin(&gpio1->b, 7, GPIO_FUNC(0x3));
|
||||
break;
|
||||
case PERIPH_ID_I2C6:
|
||||
s5p_gpio_cfg_pin(&gpio1->c1, 3, GPIO_FUNC(0x4));
|
||||
s5p_gpio_cfg_pin(&gpio1->c1, 4, GPIO_FUNC(0x4));
|
||||
break;
|
||||
case PERIPH_ID_I2C7:
|
||||
s5p_gpio_cfg_pin(&gpio1->d0, 2, GPIO_FUNC(0x3));
|
||||
s5p_gpio_cfg_pin(&gpio1->d0, 3, GPIO_FUNC(0x3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int exynos4_pinmux_config(int peripheral, int flags)
|
||||
{
|
||||
switch (peripheral) {
|
||||
case PERIPH_ID_I2C0:
|
||||
case PERIPH_ID_I2C1:
|
||||
case PERIPH_ID_I2C2:
|
||||
case PERIPH_ID_I2C3:
|
||||
case PERIPH_ID_I2C4:
|
||||
case PERIPH_ID_I2C5:
|
||||
case PERIPH_ID_I2C6:
|
||||
case PERIPH_ID_I2C7:
|
||||
exynos4_i2c_config(peripheral, flags);
|
||||
break;
|
||||
default:
|
||||
debug("%s: invalid peripheral %d", __func__, peripheral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_pinmux_config(int peripheral, int flags)
|
||||
{
|
||||
if (cpu_is_exynos5())
|
||||
return exynos5_pinmux_config(peripheral, flags);
|
||||
else if (cpu_is_exynos4())
|
||||
return exynos4_pinmux_config(peripheral, flags);
|
||||
else {
|
||||
debug("pinmux functionality not supported\n");
|
||||
return -1;
|
||||
|
@ -28,6 +28,8 @@
|
||||
#define EXYNOS4_ADDR_BASE 0x10000000
|
||||
|
||||
/* EXYNOS4 */
|
||||
#define EXYNOS4_I2C_SPACING 0x10000
|
||||
|
||||
#define EXYNOS4_GPIO_PART3_BASE 0x03860000
|
||||
#define EXYNOS4_PRO_ID 0x10000000
|
||||
#define EXYNOS4_SYSREG_BASE 0x10010000
|
||||
|
@ -35,6 +35,7 @@ enum mxc_clock {
|
||||
MXC_SSP1_CLK,
|
||||
MXC_SSP2_CLK,
|
||||
MXC_SSP3_CLK,
|
||||
MXC_XTAL_CLK,
|
||||
};
|
||||
|
||||
enum mxs_ioclock {
|
||||
|
@ -540,15 +540,13 @@ void board_init_r(gd_t *id, ulong dest_addr)
|
||||
flash_size = flash_init();
|
||||
if (flash_size > 0) {
|
||||
# ifdef CONFIG_SYS_FLASH_CHECKSUM
|
||||
char *s = getenv("flashchecksum");
|
||||
|
||||
print_size(flash_size, "");
|
||||
/*
|
||||
* Compute and print flash CRC if flashchecksum is set to 'y'
|
||||
*
|
||||
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
||||
*/
|
||||
if (s && (*s == 'y')) {
|
||||
if (getenv_yesno("flashchecksum") == 1) {
|
||||
printf(" CRC: %08X", crc32(0,
|
||||
(const unsigned char *) CONFIG_SYS_FLASH_BASE,
|
||||
flash_size));
|
||||
|
@ -16,7 +16,7 @@
|
||||
#endif
|
||||
|
||||
extern int strcasecmp(const char *, const char *);
|
||||
extern int strncasecmp(const char *, const char *, int);
|
||||
extern int strncasecmp(const char *, const char *, __kernel_size_t);
|
||||
extern char * strcpy(char *,const char *);
|
||||
extern char * strncpy(char *,const char *, __kernel_size_t);
|
||||
extern __kernel_size_t strlen(const char *);
|
||||
|
@ -462,8 +462,7 @@ void board_init_r (gd_t *id, ulong dest_addr)
|
||||
*
|
||||
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
||||
*/
|
||||
s = getenv ("flashchecksum");
|
||||
if (s && (*s == 'y')) {
|
||||
if (getenv_yesno("flashchecksum") == 1) {
|
||||
printf (" CRC: %08X",
|
||||
crc32 (0,
|
||||
(const unsigned char *) CONFIG_SYS_FLASH_BASE,
|
||||
|
@ -74,7 +74,6 @@ void board_init_f(ulong not_used)
|
||||
gd = (gd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
|
||||
bd = (bd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
|
||||
- GENERATED_BD_INFO_SIZE);
|
||||
__maybe_unused char *s;
|
||||
#if defined(CONFIG_CMD_FLASH)
|
||||
ulong flash_size = 0;
|
||||
#endif
|
||||
@ -143,8 +142,7 @@ void board_init_f(ulong not_used)
|
||||
*
|
||||
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
||||
*/
|
||||
s = getenv ("flashchecksum");
|
||||
if (s && (*s == 'y')) {
|
||||
if (getenv_yesno("flashchecksum") == 1) {
|
||||
printf (" CRC: %08X",
|
||||
crc32(0, (const u8 *)bd->bi_flashstart,
|
||||
flash_size)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <serial.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <version.h>
|
||||
#include <net.h>
|
||||
@ -46,7 +47,7 @@ static char *failed = "*** failed ***\n";
|
||||
* mips_io_port_base is the begin of the address space to which x86 style
|
||||
* I/O ports are mapped.
|
||||
*/
|
||||
unsigned long mips_io_port_base = -1;
|
||||
const unsigned long mips_io_port_base = -1;
|
||||
|
||||
int __board_early_init_f(void)
|
||||
{
|
||||
@ -262,6 +263,8 @@ void board_init_r(gd_t *id, ulong dest_addr)
|
||||
|
||||
monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
|
||||
|
||||
serial_initialize();
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
/*
|
||||
* We have to relocate the command table manually
|
||||
|
@ -46,10 +46,8 @@ u32 get_my_id()
|
||||
*/
|
||||
int hold_cores_in_reset(int verbose)
|
||||
{
|
||||
const char *s = getenv("mp_holdoff");
|
||||
|
||||
/* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */
|
||||
if (s && (*s == 'y' || *s == 'Y' || *s == '1')) {
|
||||
if (getenv_yesno("mp_holdoff") == 1) {
|
||||
if (verbose) {
|
||||
puts("Secondary cores are being held in reset.\n");
|
||||
puts("See 'mp_holdoff' environment variable\n");
|
||||
|
@ -14,7 +14,7 @@
|
||||
#define __HAVE_ARCH_MEMCHR
|
||||
|
||||
extern int strcasecmp(const char *, const char *);
|
||||
extern int strncasecmp(const char *, const char *, int);
|
||||
extern int strncasecmp(const char *, const char *, __kernel_size_t);
|
||||
extern char * strcpy(char *,const char *);
|
||||
extern char * strncpy(char *,const char *, __kernel_size_t);
|
||||
extern __kernel_size_t strlen(const char *);
|
||||
|
@ -739,16 +739,13 @@ void board_init_r(gd_t *id, ulong dest_addr)
|
||||
flash_size = 0;
|
||||
} else if ((flash_size = flash_init()) > 0) {
|
||||
#ifdef CONFIG_SYS_FLASH_CHECKSUM
|
||||
char *s;
|
||||
|
||||
print_size(flash_size, "");
|
||||
/*
|
||||
* Compute and print flash CRC if flashchecksum is set to 'y'
|
||||
*
|
||||
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
||||
*/
|
||||
s = getenv("flashchecksum");
|
||||
if (s && (*s == 'y')) {
|
||||
if (getenv_yesno("flashchecksum") == 1) {
|
||||
printf(" CRC: %08X",
|
||||
crc32(0,
|
||||
(const unsigned char *)
|
||||
@ -841,9 +838,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
|
||||
* "i2cfast" into account
|
||||
*/
|
||||
{
|
||||
char *s = getenv("i2cfast");
|
||||
|
||||
if (s && ((*s == 'y') || (*s == 'Y'))) {
|
||||
if (getenv_yesno("i2cfast") == 1) {
|
||||
bd->bi_iic_fast[0] = 1;
|
||||
bd->bi_iic_fast[1] = 1;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
*/
|
||||
|
||||
extern int strcasecmp(const char *, const char *);
|
||||
extern int strncasecmp(const char *, const char *, int);
|
||||
extern int strncasecmp(const char *, const char *, __kernel_size_t);
|
||||
extern char *strcpy(char *, const char *);
|
||||
extern char *strncpy(char *, const char *, __kernel_size_t);
|
||||
extern __kernel_size_t strlen(const char *);
|
||||
|
@ -284,8 +284,7 @@ void board_init_f(ulong bootflag)
|
||||
*
|
||||
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
|
||||
*/
|
||||
s = getenv("flashchecksum");
|
||||
if (s && (*s == 'y')) {
|
||||
if (getenv_yesno("flashchecksum") == 1) {
|
||||
printf(" CRC: %08lX",
|
||||
crc32(0, (const unsigned char *)CONFIG_SYS_FLASH_BASE,
|
||||
flash_size)
|
||||
|
@ -834,15 +834,11 @@ int mem_test_walk (void)
|
||||
/*********************************************************************/
|
||||
int testdram (void)
|
||||
{
|
||||
char *s;
|
||||
int rundata, runaddress, runwalk;
|
||||
|
||||
s = getenv ("testdramdata");
|
||||
rundata = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramaddress");
|
||||
runaddress = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramwalk");
|
||||
runwalk = (s && (*s == 'y')) ? 1 : 0;
|
||||
rundata = getenv_yesno("testdramdata") == 1;
|
||||
runaddress = getenv_yesno("testdramaddress") == 1;
|
||||
runwalk = getenv_yesno("testdramwalk") == 1;
|
||||
|
||||
/* rundata = 1; */
|
||||
/* runaddress = 0; */
|
||||
|
@ -834,15 +834,11 @@ int mem_test_walk (void)
|
||||
/*********************************************************************/
|
||||
int testdram (void)
|
||||
{
|
||||
char *s;
|
||||
int rundata, runaddress, runwalk;
|
||||
|
||||
s = getenv ("testdramdata");
|
||||
rundata = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramaddress");
|
||||
runaddress = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramwalk");
|
||||
runwalk = (s && (*s == 'y')) ? 1 : 0;
|
||||
rundata = getenv_yesno("testdramdata") == 1;
|
||||
runaddress = getenv_yesno("testdramaddress") == 1;
|
||||
runwalk = getenv_yesno("testdramwalk") == 1;
|
||||
|
||||
/* rundata = 1; */
|
||||
/* runaddress = 0; */
|
||||
|
@ -953,22 +953,18 @@ int mem_test_walk (void)
|
||||
/*********************************************************************/
|
||||
int testdram (void)
|
||||
{
|
||||
char *s;
|
||||
int rundata = 0;
|
||||
int runaddress = 0;
|
||||
int runwalk = 0;
|
||||
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_DATA
|
||||
s = getenv ("testdramdata");
|
||||
rundata = (s && (*s == 'y')) ? 1 : 0;
|
||||
rundata = getenv_yesno("testdramdata") == 1;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_ADDRESS
|
||||
s = getenv ("testdramaddress");
|
||||
runaddress = (s && (*s == 'y')) ? 1 : 0;
|
||||
runaddress = getenv_yesno("testdramaddress") == 1;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_WALK
|
||||
s = getenv ("testdramwalk");
|
||||
runwalk = (s && (*s == 'y')) ? 1 : 0;
|
||||
runwalk = getenv_yesno("testdramwalk") == 1;
|
||||
#endif
|
||||
|
||||
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
|
||||
|
@ -391,7 +391,7 @@ int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
nextbase -= ((CONFIG_ENV_SIZE + 4096 - 1) & ~(4096 - 1));
|
||||
envp = (env_t *)nextbase;
|
||||
res = (char *)envp->data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -544,15 +544,11 @@ int mem_test_walk (void)
|
||||
/*********************************************************************/
|
||||
int testdram (void)
|
||||
{
|
||||
char *s;
|
||||
int rundata, runaddress, runwalk;
|
||||
|
||||
s = getenv ("testdramdata");
|
||||
rundata = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramaddress");
|
||||
runaddress = (s && (*s == 'y')) ? 1 : 0;
|
||||
s = getenv ("testdramwalk");
|
||||
runwalk = (s && (*s == 'y')) ? 1 : 0;
|
||||
rundata = getenv_yesno("testdramdata") == 1;
|
||||
runaddress = getenv_yesno("testdramaddress") == 1;
|
||||
runwalk = getenv_yesno("testdramwalk") == 1;
|
||||
|
||||
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
|
||||
printf ("Testing RAM ... ");
|
||||
|
@ -768,22 +768,18 @@ int mem_test_walk (void)
|
||||
/*********************************************************************/
|
||||
int testdram (void)
|
||||
{
|
||||
char *s;
|
||||
int rundata = 0;
|
||||
int runaddress = 0;
|
||||
int runwalk = 0;
|
||||
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_DATA
|
||||
s = getenv ("testdramdata");
|
||||
rundata = (s && (*s == 'y')) ? 1 : 0;
|
||||
rundata = getenv_yesno("testdramdata") == 1;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_ADDRESS
|
||||
s = getenv ("testdramaddress");
|
||||
runaddress = (s && (*s == 'y')) ? 1 : 0;
|
||||
runaddress = getenv_yesno("testdramaddress") == 1;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DRAM_TEST_WALK
|
||||
s = getenv ("testdramwalk");
|
||||
runwalk = (s && (*s == 'y')) ? 1 : 0;
|
||||
runwalk = getenv_yesno("testdramwalk") == 1;
|
||||
#endif
|
||||
|
||||
if ((rundata == 1) || (runaddress == 1) || (runwalk == 1))
|
||||
|
@ -30,6 +30,7 @@ ifndef CONFIG_SPL_BUILD
|
||||
COBJS-y += main.o
|
||||
COBJS-y += command.o
|
||||
COBJS-y += exports.o
|
||||
COBJS-y += hash.o
|
||||
COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o
|
||||
COBJS-y += s_record.o
|
||||
COBJS-y += xyzModem.o
|
||||
@ -43,7 +44,10 @@ COBJS-y += cmd_nvedit.o
|
||||
COBJS-y += cmd_version.o
|
||||
|
||||
# environment
|
||||
COBJS-y += env_attr.o
|
||||
COBJS-y += env_callback.o
|
||||
COBJS-y += env_common.o
|
||||
COBJS-y += env_flags.o
|
||||
COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
|
||||
COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
|
||||
XCOBJS-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o
|
||||
@ -100,8 +104,10 @@ ifdef CONFIG_FPGA
|
||||
COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
|
||||
endif
|
||||
COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
|
||||
COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
|
||||
COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
|
||||
COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
|
||||
COBJS-$(CONFIG_CMD_HASH) += cmd_hash.o
|
||||
COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o
|
||||
COBJS-$(CONFIG_CMD_IMMAP) += cmd_immap.o
|
||||
COBJS-$(CONFIG_CMD_INI) += cmd_ini.o
|
||||
@ -117,6 +123,7 @@ COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o
|
||||
COBJS-$(CONFIG_ID_EEPROM) += cmd_mac.o
|
||||
COBJS-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o
|
||||
COBJS-$(CONFIG_CMD_MEMORY) += cmd_mem.o
|
||||
COBJS-$(CONFIG_CMD_IO) += cmd_io.o
|
||||
COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
|
||||
COBJS-$(CONFIG_MII) += miiphyutil.o
|
||||
COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
|
||||
@ -141,6 +148,7 @@ endif
|
||||
COBJS-y += cmd_pcmcia.o
|
||||
COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
|
||||
COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o
|
||||
COBJS-$(CONFIG_CMD_READ) += cmd_read.o
|
||||
COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
|
||||
COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
|
||||
COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o
|
||||
@ -184,6 +192,7 @@ COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
|
||||
COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
|
||||
COBJS-y += flash.o
|
||||
COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
|
||||
COBJS-$(CONFIG_I2C_EDID) += edid.o
|
||||
COBJS-$(CONFIG_KALLSYMS) += kallsyms.o
|
||||
COBJS-$(CONFIG_LCD) += lcd.o
|
||||
COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
|
||||
@ -192,6 +201,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
|
||||
COBJS-$(CONFIG_UPDATE_TFTP) += update.o
|
||||
COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
|
||||
COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
|
||||
COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
@ -200,7 +210,10 @@ COBJS-y += env_common.o
|
||||
COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
|
||||
COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += cmd_nvedit.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_attr.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_callback.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_flags.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_nowhere.o
|
||||
COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
|
||||
endif
|
||||
|
@ -537,7 +537,7 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_OF_LIBFDT)
|
||||
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
|
||||
case BOOTM_STATE_FDT:
|
||||
{
|
||||
boot_fdt_add_mem_rsv_regions(&images.lmb,
|
||||
|
56
common/cmd_gettime.c
Normal file
56
common/cmd_gettime.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* (C) Copyright 2001
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
static int do_gettime(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
unsigned long int val = get_timer(0);
|
||||
|
||||
#ifdef CONFIG_SYS_HZ
|
||||
printf("Timer val: %lu\n", val);
|
||||
printf("Seconds : %lu\n", val / CONFIG_SYS_HZ);
|
||||
printf("Remainder : %lu\n", val % CONFIG_SYS_HZ);
|
||||
printf("sys_hz = %lu\n", (unsigned long int)CONFIG_SYS_HZ);
|
||||
#else
|
||||
printf("CONFIG_SYS_HZ not defined");
|
||||
printf("Timer Val %lu", val);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
gettime, 1, 1, do_gettime,
|
||||
"get timer val elapsed,\n",
|
||||
"get time elapsed from uboot start\n"
|
||||
);
|
333
common/cmd_gpt.c
Normal file
333
common/cmd_gpt.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* cmd_gpt.c -- GPT (GUID Partition Table) handling command
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* author: Lukasz Majewski <l.majewski@samsung.com>
|
||||
* author: Piotr Wilczek <p.wilczek@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <command.h>
|
||||
#include <mmc.h>
|
||||
#include <part_efi.h>
|
||||
#include <exports.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#ifndef CONFIG_PARTITION_UUIDS
|
||||
#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled
|
||||
#endif
|
||||
|
||||
/**
|
||||
* extract_env(): Expand env name from string format '&{env_name}'
|
||||
* and return pointer to the env (if the env is set)
|
||||
*
|
||||
* @param str - pointer to string
|
||||
* @param env - pointer to pointer to extracted env
|
||||
*
|
||||
* @return - zero on successful expand and env is set
|
||||
*/
|
||||
static char extract_env(const char *str, char **env)
|
||||
{
|
||||
char *e, *s;
|
||||
|
||||
if (!str || strlen(str) < 4)
|
||||
return -1;
|
||||
|
||||
if ((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')) {
|
||||
s = strdup(str);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
memset(s + strlen(s) - 1, '\0', 1);
|
||||
memmove(s, s + 2, strlen(s) - 1);
|
||||
e = getenv(s);
|
||||
free(s);
|
||||
if (e == NULL) {
|
||||
printf("Environmental '%s' not set\n", str);
|
||||
return -1; /* env not set */
|
||||
}
|
||||
*env = e;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract_val(): Extract value from a key=value pair list (comma separated).
|
||||
* Only value for the given key is returend.
|
||||
* Function allocates memory for the value, remember to free!
|
||||
*
|
||||
* @param str - pointer to string with key=values pairs
|
||||
* @param key - pointer to the key to search for
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_gpt_info(): Fill partition information from string
|
||||
* function allocates memory, remember to free!
|
||||
*
|
||||
* @param dev_desc - pointer block device descriptor
|
||||
* @param str_part - pointer to string with partition information
|
||||
* @param str_disk_guid - pointer to pointer to allocated string with disk guid
|
||||
* @param partitions - pointer to pointer to allocated partitions array
|
||||
* @param parts_count - number of partitions
|
||||
*
|
||||
* @return - zero on success, otherwise error
|
||||
*
|
||||
*/
|
||||
static int set_gpt_info(block_dev_desc_t *dev_desc,
|
||||
const char *str_part,
|
||||
char **str_disk_guid,
|
||||
disk_partition_t **partitions,
|
||||
u8 *parts_count)
|
||||
{
|
||||
char *tok, *str, *s;
|
||||
int i;
|
||||
char *val, *p;
|
||||
int p_count;
|
||||
disk_partition_t *parts;
|
||||
int errno = 0;
|
||||
|
||||
debug("%s: MMC lba num: 0x%x %d\n", __func__,
|
||||
(unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
|
||||
|
||||
if (str_part == NULL)
|
||||
return -1;
|
||||
|
||||
str = strdup(str_part);
|
||||
|
||||
/* extract disk guid */
|
||||
s = str;
|
||||
tok = strsep(&s, ";");
|
||||
val = extract_val(tok, "uuid_disk");
|
||||
if (!val) {
|
||||
free(str);
|
||||
return -2;
|
||||
}
|
||||
if (extract_env(val, &p))
|
||||
p = val;
|
||||
*str_disk_guid = strdup(p);
|
||||
free(val);
|
||||
|
||||
if (strlen(s) == 0)
|
||||
return -3;
|
||||
|
||||
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(disk_partition_t), p_count);
|
||||
|
||||
/* retrive partions data from string */
|
||||
for (i = 0; i < p_count; i++) {
|
||||
tok = strsep(&s, ";");
|
||||
|
||||
if (tok == NULL)
|
||||
break;
|
||||
|
||||
/* uuid */
|
||||
val = extract_val(tok, "uuid");
|
||||
if (!val) { /* 'uuid' is mandatory */
|
||||
errno = -4;
|
||||
goto err;
|
||||
}
|
||||
if (extract_env(val, &p))
|
||||
p = val;
|
||||
if (strlen(p) >= sizeof(parts[i].uuid)) {
|
||||
printf("Wrong uuid format for partition %d\n", i);
|
||||
errno = -4;
|
||||
goto err;
|
||||
}
|
||||
strcpy((char *)parts[i].uuid, p);
|
||||
free(val);
|
||||
|
||||
/* name */
|
||||
val = extract_val(tok, "name");
|
||||
if (!val) { /* name is mandatory */
|
||||
errno = -4;
|
||||
goto err;
|
||||
}
|
||||
if (extract_env(val, &p))
|
||||
p = val;
|
||||
if (strlen(p) >= sizeof(parts[i].name)) {
|
||||
errno = -4;
|
||||
goto err;
|
||||
}
|
||||
strcpy((char *)parts[i].name, p);
|
||||
free(val);
|
||||
|
||||
/* size */
|
||||
val = extract_val(tok, "size");
|
||||
if (!val) { /* 'size' is mandatory */
|
||||
errno = -4;
|
||||
goto err;
|
||||
}
|
||||
if (extract_env(val, &p))
|
||||
p = val;
|
||||
parts[i].size = ustrtoul(p, &p, 0);
|
||||
parts[i].size /= dev_desc->blksz;
|
||||
free(val);
|
||||
|
||||
/* start address */
|
||||
val = extract_val(tok, "start");
|
||||
if (val) { /* start address is optional */
|
||||
if (extract_env(val, &p))
|
||||
p = val;
|
||||
parts[i].start = ustrtoul(p, &p, 0);
|
||||
parts[i].start /= dev_desc->blksz;
|
||||
free(val);
|
||||
}
|
||||
}
|
||||
|
||||
*parts_count = p_count;
|
||||
*partitions = parts;
|
||||
free(str);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free(str);
|
||||
free(*str_disk_guid);
|
||||
free(parts);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
static int gpt_mmc_default(int dev, const char *str_part)
|
||||
{
|
||||
int ret;
|
||||
char *str_disk_guid;
|
||||
u8 part_count = 0;
|
||||
disk_partition_t *partitions = NULL;
|
||||
|
||||
struct mmc *mmc = find_mmc_device(dev);
|
||||
|
||||
if (mmc == NULL) {
|
||||
printf("%s: mmc dev %d NOT available\n", __func__, dev);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (!str_part)
|
||||
return -1;
|
||||
|
||||
/* fill partitions */
|
||||
ret = set_gpt_info(&mmc->block_dev, str_part,
|
||||
&str_disk_guid, &partitions, &part_count);
|
||||
if (ret) {
|
||||
if (ret == -1)
|
||||
printf("No partition list provided\n");
|
||||
if (ret == -2)
|
||||
printf("Missing disk guid\n");
|
||||
if ((ret == -3) || (ret == -4))
|
||||
printf("Partition list incomplete\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* save partitions layout to disk */
|
||||
gpt_restore(&mmc->block_dev, str_disk_guid, partitions, part_count);
|
||||
free(str_disk_guid);
|
||||
free(partitions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* do_gpt(): Perform GPT operations
|
||||
*
|
||||
* @param cmdtp - command name
|
||||
* @param flag
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return zero on success; otherwise error
|
||||
*/
|
||||
static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int ret = CMD_RET_SUCCESS;
|
||||
int dev = 0;
|
||||
char *pstr;
|
||||
|
||||
if (argc < 5)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
/* command: 'write' */
|
||||
if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
|
||||
/* device: 'mmc' */
|
||||
if (strcmp(argv[2], "mmc") == 0) {
|
||||
/* check if 'dev' is a number */
|
||||
for (pstr = argv[3]; *pstr != '\0'; pstr++)
|
||||
if (!isdigit(*pstr)) {
|
||||
printf("'%s' is not a number\n",
|
||||
argv[3]);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
dev = (int)simple_strtoul(argv[3], NULL, 10);
|
||||
/* write to mmc */
|
||||
if (gpt_mmc_default(dev, argv[4]))
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
|
||||
"GUID Partition Table",
|
||||
"<command> <interface> <dev> <partions_list>\n"
|
||||
" - GUID partition table restoration\n"
|
||||
" Restore GPT information on a device connected\n"
|
||||
" to interface\n"
|
||||
);
|
63
common/cmd_hash.c
Normal file
63
common/cmd_hash.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
*
|
||||
* (C) Copyright 2011
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <hash.h>
|
||||
|
||||
static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
#ifdef CONFIG_HASH_VERIFY
|
||||
int verify = 0;
|
||||
|
||||
if (!strcmp(argv[1], "-v")) {
|
||||
verify = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
#endif
|
||||
/* Move forward to 'algorithm' parameter */
|
||||
argc--;
|
||||
argv++;
|
||||
return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HASH_VERIFY
|
||||
U_BOOT_CMD(
|
||||
hash, 6, 1, do_hash,
|
||||
"compute hash message digest",
|
||||
"algorithm address count [[*]sum_dest]\n"
|
||||
" - compute message digest [save to env var / *address]\n"
|
||||
"hash -v algorithm address count [*]sum\n"
|
||||
" - verify hash of memory area with env var / *address"
|
||||
);
|
||||
#else
|
||||
U_BOOT_CMD(
|
||||
hash, 5, 1, do_hash,
|
||||
"compute message digest",
|
||||
"algorithm address count [[*]sum_dest]\n"
|
||||
" - compute message digest [save to env var / *address]"
|
||||
);
|
||||
#endif
|
249
common/cmd_i2c.c
249
common/cmd_i2c.c
@ -78,10 +78,12 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <edid.h>
|
||||
#include <environment.h>
|
||||
#include <i2c.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
/* Display values from last command.
|
||||
* Memory modify remembered values are different from display memory.
|
||||
@ -132,35 +134,65 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define DISP_LINE_LEN 16
|
||||
|
||||
/* implement possible board specific board init */
|
||||
static void __def_i2c_init_board(void)
|
||||
/**
|
||||
* i2c_init_board() - Board-specific I2C bus init
|
||||
*
|
||||
* This function is the default no-op implementation of I2C bus
|
||||
* initialization. This function can be overriden by board-specific
|
||||
* implementation if needed.
|
||||
*/
|
||||
__weak
|
||||
void i2c_init_board(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void i2c_init_board(void)
|
||||
__attribute__((weak, alias("__def_i2c_init_board")));
|
||||
|
||||
/* TODO: Implement architecture-specific get/set functions */
|
||||
static unsigned int __def_i2c_get_bus_speed(void)
|
||||
|
||||
/**
|
||||
* i2c_get_bus_speed() - Return I2C bus speed
|
||||
*
|
||||
* This function is the default implementation of function for retrieveing
|
||||
* the current I2C bus speed in Hz.
|
||||
*
|
||||
* A driver implementing runtime switching of I2C bus speed must override
|
||||
* this function to report the speed correctly. Simple or legacy drivers
|
||||
* can use this fallback.
|
||||
*
|
||||
* Returns I2C bus speed in Hz.
|
||||
*/
|
||||
__weak
|
||||
unsigned int i2c_get_bus_speed(void)
|
||||
{
|
||||
return CONFIG_SYS_I2C_SPEED;
|
||||
}
|
||||
unsigned int i2c_get_bus_speed(void)
|
||||
__attribute__((weak, alias("__def_i2c_get_bus_speed")));
|
||||
|
||||
static int __def_i2c_set_bus_speed(unsigned int speed)
|
||||
/**
|
||||
* i2c_set_bus_speed() - Configure I2C bus speed
|
||||
* @speed: Newly set speed of the I2C bus in Hz
|
||||
*
|
||||
* This function is the default implementation of function for setting
|
||||
* the I2C bus speed in Hz.
|
||||
*
|
||||
* A driver implementing runtime switching of I2C bus speed must override
|
||||
* this function to report the speed correctly. Simple or legacy drivers
|
||||
* can use this fallback.
|
||||
*
|
||||
* Returns zero on success, negative value on error.
|
||||
*/
|
||||
__weak
|
||||
int i2c_set_bus_speed(unsigned int speed)
|
||||
{
|
||||
if (speed != CONFIG_SYS_I2C_SPEED)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int i2c_set_bus_speed(unsigned int)
|
||||
__attribute__((weak, alias("__def_i2c_set_bus_speed")));
|
||||
|
||||
/*
|
||||
* get_alen: small parser helper function to get address length
|
||||
* returns the address length
|
||||
/**
|
||||
* get_alen() - Small parser helper function to get address length
|
||||
*
|
||||
* Returns the address length.
|
||||
*/
|
||||
static uint get_alen(char *arg)
|
||||
{
|
||||
@ -178,11 +210,19 @@ static uint get_alen(char *arg)
|
||||
return alen;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* do_i2c_read() - Handle the "i2c read" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
|
||||
*/
|
||||
|
||||
static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
u_char chip;
|
||||
@ -271,7 +311,16 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* do_i2c_md() - Handle the "i2c md" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c md {i2c_chip} {addr}{.0, .1, .2} {len}
|
||||
*/
|
||||
@ -363,8 +412,15 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Write (fill) memory
|
||||
/**
|
||||
* do_i2c_mw() - Handle the "i2c mw" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
|
||||
@ -421,10 +477,20 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate a CRC on memory
|
||||
/**
|
||||
* do_i2c_crc() - Handle the "i2c crc32" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Calculate a CRC on memory
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count}
|
||||
@ -481,13 +547,22 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Modify memory.
|
||||
/**
|
||||
* mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Modify memory.
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
|
||||
* i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
|
||||
*/
|
||||
|
||||
static int
|
||||
mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
|
||||
{
|
||||
@ -603,7 +678,16 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* do_i2c_probe() - Handle the "i2c probe" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c probe {addr}
|
||||
*
|
||||
@ -657,7 +741,16 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
|
||||
return (0 == found);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* do_i2c_loop() - Handle the "i2c loop" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*
|
||||
* Syntax:
|
||||
* i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}]
|
||||
* {length} - Number of bytes to read
|
||||
@ -718,6 +811,8 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
|
||||
/*
|
||||
* The SDRAM command is separately configured because many
|
||||
* (most?) embedded boards don't use SDRAM DIMMs.
|
||||
*
|
||||
* FIXME: Document and probably move elsewhere!
|
||||
*/
|
||||
#if defined(CONFIG_CMD_SDRAM)
|
||||
static void print_ddr2_tcyc (u_char const b)
|
||||
@ -1246,7 +1341,48 @@ static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Syntax:
|
||||
* i2c edid {i2c_chip}
|
||||
*/
|
||||
#if defined(CONFIG_I2C_EDID)
|
||||
int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
u_char chip;
|
||||
struct edid1_info edid;
|
||||
|
||||
if (argc < 2) {
|
||||
cmd_usage(cmdtp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
|
||||
puts("Error reading EDID content.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (edid_check_info(&edid)) {
|
||||
puts("Content isn't valid EDID.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
edid_print_info(&edid);
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif /* CONFIG_I2C_EDID */
|
||||
|
||||
#if defined(CONFIG_I2C_MUX)
|
||||
/**
|
||||
* do_i2c_add_bus() - Handle the "i2c bus" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero always.
|
||||
*/
|
||||
static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int ret=0;
|
||||
@ -1276,6 +1412,16 @@ static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
|
||||
#endif /* CONFIG_I2C_MUX */
|
||||
|
||||
#if defined(CONFIG_I2C_MULTI_BUS)
|
||||
/**
|
||||
* do_i2c_bus_num() - Handle the "i2c dev" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int bus_idx, ret=0;
|
||||
@ -1294,6 +1440,16 @@ static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
|
||||
}
|
||||
#endif /* CONFIG_I2C_MULTI_BUS */
|
||||
|
||||
/**
|
||||
* do_i2c_bus_speed() - Handle the "i2c speed" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int speed, ret=0;
|
||||
@ -1311,16 +1467,45 @@ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* do_i2c_mm() - Handle the "i2c mm" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_i2c_mm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return mod_i2c_mem (cmdtp, 1, flag, argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_i2c_nm() - Handle the "i2c nm" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return mod_i2c_mem (cmdtp, 0, flag, argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_i2c_reset() - Handle the "i2c reset" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero always.
|
||||
*/
|
||||
static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
||||
@ -1335,6 +1520,9 @@ static cmd_tbl_t cmd_i2c_sub[] = {
|
||||
#if defined(CONFIG_I2C_MULTI_BUS)
|
||||
U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""),
|
||||
#endif /* CONFIG_I2C_MULTI_BUS */
|
||||
#if defined(CONFIG_I2C_EDID)
|
||||
U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""),
|
||||
#endif /* CONFIG_I2C_EDID */
|
||||
U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""),
|
||||
U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""),
|
||||
U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""),
|
||||
@ -1356,6 +1544,16 @@ void i2c_reloc(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* do_i2c() - Handle the "i2c" command-line command
|
||||
* @cmdtp: Command data struct pointer
|
||||
* @flag: Command flag
|
||||
* @argc: Command-line argument count
|
||||
* @argv: Array of command-line arguments
|
||||
*
|
||||
* Returns zero on success, CMD_RET_USAGE in case of misuse and negative
|
||||
* on error.
|
||||
*/
|
||||
static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
cmd_tbl_t *c;
|
||||
@ -1385,6 +1583,9 @@ static char i2c_help_text[] =
|
||||
#if defined(CONFIG_I2C_MULTI_BUS)
|
||||
"i2c dev [dev] - show or set current I2C bus\n"
|
||||
#endif /* CONFIG_I2C_MULTI_BUS */
|
||||
#if defined(CONFIG_I2C_EDID)
|
||||
"i2c edid chip - print EDID configuration information\n"
|
||||
#endif /* CONFIG_I2C_EDID */
|
||||
"i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n"
|
||||
"i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n"
|
||||
"i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n"
|
||||
|
93
common/cmd_io.c
Normal file
93
common/cmd_io.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* IO space access commands.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* IO Display
|
||||
*
|
||||
* Syntax:
|
||||
* iod{.b, .w, .l} {addr}
|
||||
*/
|
||||
int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
ulong addr;
|
||||
int size;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
size = cmd_get_data_size(argv[0], 4);
|
||||
if (size < 0)
|
||||
return 1;
|
||||
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
printf("%04x: ", (u16) addr);
|
||||
|
||||
if (size == 4)
|
||||
printf("%08x\n", inl(addr));
|
||||
else if (size == 2)
|
||||
printf("%04x\n", inw(addr));
|
||||
else
|
||||
printf("%02x\n", inb(addr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
ulong addr, size, val;
|
||||
|
||||
if (argc != 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
size = cmd_get_data_size(argv[0], 4);
|
||||
if (size < 0)
|
||||
return 1;
|
||||
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
val = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
if (size == 4)
|
||||
outl((u32) val, addr);
|
||||
else if (size == 2)
|
||||
outw((u16) val, addr);
|
||||
else
|
||||
outb((u8) val, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
U_BOOT_CMD(iod, 2, 0, do_io_iod,
|
||||
"IO space display", "[.b, .w, .l] address [# of objects]");
|
||||
|
||||
U_BOOT_CMD(iow, 3, 0, do_io_iow,
|
||||
"IO space modify (auto-incrementing address)",
|
||||
"[.b, .w, .l] address");
|
@ -47,12 +47,8 @@
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <watchdog.h>
|
||||
#include <serial.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <asm/byteorder.h>
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
#include <net.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@ -76,16 +72,6 @@ SPI_FLASH|NVRAM|MMC|FAT|REMOTE} or CONFIG_ENV_IS_NOWHERE
|
||||
*/
|
||||
#define MAX_ENV_SIZE (1 << 20) /* 1 MiB */
|
||||
|
||||
ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */
|
||||
ulong save_addr; /* Default Save Address */
|
||||
ulong save_size; /* Default Save Size (in bytes) */
|
||||
|
||||
/*
|
||||
* Table with supported baudrates (defined in config_xyz.h)
|
||||
*/
|
||||
static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
|
||||
#define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
|
||||
|
||||
/*
|
||||
* This variable is incremented on each do_env_set(), so it can
|
||||
* be used via get_env_id() as an indication, if the environment
|
||||
@ -106,7 +92,7 @@ int get_env_id(void)
|
||||
*
|
||||
* Returns 0 in case of error, or length of printed string
|
||||
*/
|
||||
static int env_print(char *name)
|
||||
static int env_print(char *name, int flag)
|
||||
{
|
||||
char *res = NULL;
|
||||
size_t len;
|
||||
@ -116,7 +102,7 @@ static int env_print(char *name)
|
||||
|
||||
e.key = name;
|
||||
e.data = NULL;
|
||||
hsearch_r(e, FIND, &ep, &env_htab);
|
||||
hsearch_r(e, FIND, &ep, &env_htab, flag);
|
||||
if (ep == NULL)
|
||||
return 0;
|
||||
len = printf("%s=%s\n", ep->key, ep->data);
|
||||
@ -124,7 +110,7 @@ static int env_print(char *name)
|
||||
}
|
||||
|
||||
/* print whole list */
|
||||
len = hexport_r(&env_htab, '\n', &res, 0, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\n', flag, &res, 0, 0, NULL);
|
||||
|
||||
if (len > 0) {
|
||||
puts(res);
|
||||
@ -141,10 +127,17 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
{
|
||||
int i;
|
||||
int rcode = 0;
|
||||
int env_flag = H_HIDE_DOT;
|
||||
|
||||
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
|
||||
argc--;
|
||||
argv++;
|
||||
env_flag &= ~H_HIDE_DOT;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
/* print all env vars */
|
||||
rcode = env_print(NULL);
|
||||
rcode = env_print(NULL, env_flag);
|
||||
if (!rcode)
|
||||
return 1;
|
||||
printf("\nEnvironment size: %d/%ld bytes\n",
|
||||
@ -153,8 +146,9 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
}
|
||||
|
||||
/* print selected env vars */
|
||||
env_flag &= ~H_HIDE_DOT;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
int rc = env_print(argv[i]);
|
||||
int rc = env_print(argv[i], env_flag);
|
||||
if (!rc) {
|
||||
printf("## Error: \"%s\" not defined\n", argv[i]);
|
||||
++rcode;
|
||||
@ -197,138 +191,33 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
|
||||
#endif
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
/*
|
||||
* Perform consistency checking before setting, replacing, or deleting an
|
||||
* environment variable, then (if successful) apply the changes to internals so
|
||||
* to make them effective. Code for this function was taken out of
|
||||
* _do_env_set(), which now calls it instead.
|
||||
* Also called as a callback function by himport_r().
|
||||
* Returns 0 in case of success, 1 in case of failure.
|
||||
* When (flag & H_FORCE) is set, do not print out any error message and force
|
||||
* overwriting of write-once variables.
|
||||
*/
|
||||
|
||||
int env_check_apply(const char *name, const char *oldval,
|
||||
const char *newval, int flag)
|
||||
{
|
||||
int console = -1;
|
||||
|
||||
/* Default value for NULL to protect string-manipulating functions */
|
||||
newval = newval ? : "";
|
||||
|
||||
/* Check for console redirection */
|
||||
if (strcmp(name, "stdin") == 0)
|
||||
console = stdin;
|
||||
else if (strcmp(name, "stdout") == 0)
|
||||
console = stdout;
|
||||
else if (strcmp(name, "stderr") == 0)
|
||||
console = stderr;
|
||||
|
||||
if (console != -1) {
|
||||
if ((newval == NULL) || (*newval == '\0')) {
|
||||
/* We cannot delete stdin/stdout/stderr */
|
||||
if ((flag & H_FORCE) == 0)
|
||||
printf("Can't delete \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_MUX
|
||||
if (iomux_doenv(console, newval))
|
||||
return 1;
|
||||
#else
|
||||
/* Try assigning specified device */
|
||||
if (console_assign(console, newval) < 0)
|
||||
return 1;
|
||||
#endif /* CONFIG_CONSOLE_MUX */
|
||||
}
|
||||
|
||||
/*
|
||||
* Some variables like "ethaddr" and "serial#" can be set only once and
|
||||
* cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
|
||||
*/
|
||||
#ifndef CONFIG_ENV_OVERWRITE
|
||||
if (oldval != NULL && /* variable exists */
|
||||
(flag & H_FORCE) == 0) { /* and we are not forced */
|
||||
if (strcmp(name, "serial#") == 0 ||
|
||||
(strcmp(name, "ethaddr") == 0
|
||||
#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
|
||||
&& strcmp(oldval, __stringify(CONFIG_ETHADDR)) != 0
|
||||
#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
|
||||
)) {
|
||||
printf("Can't overwrite \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* When we change baudrate, or we are doing an env default -a
|
||||
* (which will erase all variables prior to calling this),
|
||||
* we want the baudrate to actually change - for real.
|
||||
*/
|
||||
if (oldval != NULL || /* variable exists */
|
||||
(flag & H_NOCLEAR) == 0) { /* or env is clear */
|
||||
/*
|
||||
* Switch to new baudrate if new baudrate is supported
|
||||
*/
|
||||
if (strcmp(name, "baudrate") == 0) {
|
||||
int baudrate = simple_strtoul(newval, NULL, 10);
|
||||
int i;
|
||||
for (i = 0; i < N_BAUDRATES; ++i) {
|
||||
if (baudrate == baudrate_table[i])
|
||||
break;
|
||||
}
|
||||
if (i == N_BAUDRATES) {
|
||||
if ((flag & H_FORCE) == 0)
|
||||
printf("## Baudrate %d bps not "
|
||||
"supported\n", baudrate);
|
||||
return 1;
|
||||
}
|
||||
if (gd->baudrate == baudrate) {
|
||||
/* If unchanged, we just say it's OK */
|
||||
return 0;
|
||||
}
|
||||
printf("## Switch baudrate to %d bps and"
|
||||
"press ENTER ...\n", baudrate);
|
||||
udelay(50000);
|
||||
gd->baudrate = baudrate;
|
||||
#if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
|
||||
gd->bd->bi_baudrate = baudrate;
|
||||
#endif
|
||||
|
||||
serial_setbrg();
|
||||
udelay(50000);
|
||||
while (getc() != '\r')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some variables should be updated when the corresponding
|
||||
* entry in the environment is changed
|
||||
*/
|
||||
if (strcmp(name, "loadaddr") == 0) {
|
||||
load_addr = simple_strtoul(newval, NULL, 16);
|
||||
return 0;
|
||||
}
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
else if (strcmp(name, "bootfile") == 0) {
|
||||
copy_filename(BootFile, newval, sizeof(BootFile));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a new environment variable,
|
||||
* or replace or delete an existing one.
|
||||
*/
|
||||
*/
|
||||
static int _do_env_set(int flag, int argc, char * const argv[])
|
||||
{
|
||||
int i, len;
|
||||
char *name, *value, *s;
|
||||
ENTRY e, *ep;
|
||||
int env_flag = H_INTERACTIVE;
|
||||
|
||||
debug("Initial value for argc=%d\n", argc);
|
||||
while (argc > 1 && **(argv + 1) == '-') {
|
||||
char *arg = *++argv;
|
||||
|
||||
--argc;
|
||||
while (*++arg) {
|
||||
switch (*arg) {
|
||||
case 'f': /* force */
|
||||
env_flag |= H_FORCE;
|
||||
break;
|
||||
default:
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("Final value for argc=%d\n", argc);
|
||||
name = argv[1];
|
||||
value = argv[2];
|
||||
|
||||
@ -339,25 +228,10 @@ static int _do_env_set(int flag, int argc, char * const argv[])
|
||||
}
|
||||
|
||||
env_id++;
|
||||
/*
|
||||
* search if variable with this name already exists
|
||||
*/
|
||||
e.key = name;
|
||||
e.data = NULL;
|
||||
hsearch_r(e, FIND, &ep, &env_htab);
|
||||
|
||||
/*
|
||||
* Perform requested checks. Notice how since we are overwriting
|
||||
* a single variable, we need to set H_NOCLEAR
|
||||
*/
|
||||
if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
|
||||
debug("check function did not approve, refusing\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Delete only ? */
|
||||
if (argc < 3 || argv[2] == NULL) {
|
||||
int rc = hdelete_r(name, &env_htab, 0);
|
||||
int rc = hdelete_r(name, &env_htab, env_flag);
|
||||
return !rc;
|
||||
}
|
||||
|
||||
@ -384,7 +258,7 @@ static int _do_env_set(int flag, int argc, char * const argv[])
|
||||
|
||||
e.key = name;
|
||||
e.data = value;
|
||||
hsearch_r(e, ENTER, &ep, &env_htab);
|
||||
hsearch_r(e, ENTER, &ep, &env_htab, env_flag);
|
||||
free(value);
|
||||
if (!ep) {
|
||||
printf("## Error inserting \"%s\" variable, errno=%d\n",
|
||||
@ -511,6 +385,153 @@ int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_ENV_CALLBACK)
|
||||
static int print_static_binding(const char *var_name, const char *callback_name)
|
||||
{
|
||||
printf("\t%-20s %-20s\n", var_name, callback_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_active_callback(ENTRY *entry)
|
||||
{
|
||||
struct env_clbk_tbl *clbkp;
|
||||
int i;
|
||||
int num_callbacks;
|
||||
|
||||
if (entry->callback == NULL)
|
||||
return 0;
|
||||
|
||||
/* look up the callback in the linker-list */
|
||||
num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
|
||||
for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
|
||||
i < num_callbacks;
|
||||
i++, clbkp++) {
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
if (entry->callback == clbkp->callback + gd->reloc_off)
|
||||
#else
|
||||
if (entry->callback == clbkp->callback)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num_callbacks)
|
||||
/* this should probably never happen, but just in case... */
|
||||
printf("\t%-20s %p\n", entry->key, entry->callback);
|
||||
else
|
||||
printf("\t%-20s %-20s\n", entry->key, clbkp->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the callbacks available and what they are bound to
|
||||
*/
|
||||
int do_env_callback(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct env_clbk_tbl *clbkp;
|
||||
int i;
|
||||
int num_callbacks;
|
||||
|
||||
/* Print the available callbacks */
|
||||
puts("Available callbacks:\n");
|
||||
puts("\tCallback Name\n");
|
||||
puts("\t-------------\n");
|
||||
num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
|
||||
for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
|
||||
i < num_callbacks;
|
||||
i++, clbkp++)
|
||||
printf("\t%s\n", clbkp->name);
|
||||
puts("\n");
|
||||
|
||||
/* Print the static bindings that may exist */
|
||||
puts("Static callback bindings:\n");
|
||||
printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
|
||||
printf("\t%-20s %-20s\n", "-------------", "-------------");
|
||||
env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding);
|
||||
puts("\n");
|
||||
|
||||
/* walk through each variable and print the callback if it has one */
|
||||
puts("Active callback bindings:\n");
|
||||
printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
|
||||
printf("\t%-20s %-20s\n", "-------------", "-------------");
|
||||
hwalk_r(&env_htab, print_active_callback);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_ENV_FLAGS)
|
||||
static int print_static_flags(const char *var_name, const char *flags)
|
||||
{
|
||||
enum env_flags_vartype type = env_flags_parse_vartype(flags);
|
||||
enum env_flags_varaccess access = env_flags_parse_varaccess(flags);
|
||||
|
||||
printf("\t%-20s %-20s %-20s\n", var_name,
|
||||
env_flags_get_vartype_name(type),
|
||||
env_flags_get_varaccess_name(access));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_active_flags(ENTRY *entry)
|
||||
{
|
||||
enum env_flags_vartype type;
|
||||
enum env_flags_varaccess access;
|
||||
|
||||
if (entry->flags == 0)
|
||||
return 0;
|
||||
|
||||
type = (enum env_flags_vartype)
|
||||
(entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK);
|
||||
access = env_flags_parse_varaccess_from_binflags(entry->flags);
|
||||
printf("\t%-20s %-20s %-20s\n", entry->key,
|
||||
env_flags_get_vartype_name(type),
|
||||
env_flags_get_varaccess_name(access));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the flags available and what variables have flags
|
||||
*/
|
||||
int do_env_flags(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
/* Print the available variable types */
|
||||
printf("Available variable type flags (position %d):\n",
|
||||
ENV_FLAGS_VARTYPE_LOC);
|
||||
puts("\tFlag\tVariable Type Name\n");
|
||||
puts("\t----\t------------------\n");
|
||||
env_flags_print_vartypes();
|
||||
puts("\n");
|
||||
|
||||
/* Print the available variable access types */
|
||||
printf("Available variable access flags (position %d):\n",
|
||||
ENV_FLAGS_VARACCESS_LOC);
|
||||
puts("\tFlag\tVariable Access Name\n");
|
||||
puts("\t----\t--------------------\n");
|
||||
env_flags_print_varaccess();
|
||||
puts("\n");
|
||||
|
||||
/* Print the static flags that may exist */
|
||||
puts("Static flags:\n");
|
||||
printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
|
||||
"Variable Access");
|
||||
printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
|
||||
"---------------");
|
||||
env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags);
|
||||
puts("\n");
|
||||
|
||||
/* walk through each variable and print the flags if non-default */
|
||||
puts("Active flags:\n");
|
||||
printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
|
||||
"Variable Access");
|
||||
printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
|
||||
"---------------");
|
||||
hwalk_r(&env_htab, print_active_flags);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interactively edit an environment variable
|
||||
*/
|
||||
@ -552,7 +573,7 @@ char *getenv(const char *name)
|
||||
|
||||
e.key = name;
|
||||
e.data = NULL;
|
||||
hsearch_r(e, FIND, &ep, &env_htab);
|
||||
hsearch_r(e, FIND, &ep, &env_htab, 0);
|
||||
|
||||
return ep ? ep->data : NULL;
|
||||
}
|
||||
@ -704,8 +725,36 @@ static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
|
||||
static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
printf("Not implemented yet\n");
|
||||
return 0;
|
||||
int env_flag = H_INTERACTIVE;
|
||||
int ret = 0;
|
||||
|
||||
debug("Initial value for argc=%d\n", argc);
|
||||
while (argc > 1 && **(argv + 1) == '-') {
|
||||
char *arg = *++argv;
|
||||
|
||||
--argc;
|
||||
while (*++arg) {
|
||||
switch (*arg) {
|
||||
case 'f': /* force */
|
||||
env_flag |= H_FORCE;
|
||||
break;
|
||||
default:
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("Final value for argc=%d\n", argc);
|
||||
|
||||
env_id++;
|
||||
|
||||
while (--argc > 0) {
|
||||
char *name = *++argv;
|
||||
|
||||
if (!hdelete_r(name, &env_htab, env_flag))
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_EXPORTENV
|
||||
@ -812,7 +861,7 @@ NXTARG: ;
|
||||
argv++;
|
||||
|
||||
if (sep) { /* export as text file */
|
||||
len = hexport_r(&env_htab, sep, &addr, size, argc, argv);
|
||||
len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
@ -830,7 +879,7 @@ NXTARG: ;
|
||||
else /* export as raw binary data */
|
||||
res = addr;
|
||||
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, argc, argv);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
@ -951,7 +1000,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
|
||||
}
|
||||
|
||||
if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
|
||||
0, NULL, 0 /* do_apply */) == 0) {
|
||||
0, NULL) == 0) {
|
||||
error("Environment import failed: errno = %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
@ -974,10 +1023,16 @@ static cmd_tbl_t cmd_env_sub[] = {
|
||||
U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
|
||||
#endif
|
||||
U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
|
||||
U_BOOT_CMD_MKENT(delete, 2, 0, do_env_delete, "", ""),
|
||||
U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""),
|
||||
#if defined(CONFIG_CMD_EDITENV)
|
||||
U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_ENV_CALLBACK)
|
||||
U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""),
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_ENV_FLAGS)
|
||||
U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_EXPORTENV)
|
||||
U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
|
||||
#endif
|
||||
@ -1027,22 +1082,29 @@ static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
static char env_help_text[] =
|
||||
#if defined(CONFIG_CMD_ASKENV)
|
||||
"ask name [message] [size] - ask for environment variable\nenv "
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_ENV_CALLBACK)
|
||||
"callbacks - print callbacks and their associated variables\nenv "
|
||||
#endif
|
||||
"default [-f] -a - [forcibly] reset default environment\n"
|
||||
"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
|
||||
"env delete [-f] var [...] - [forcibly] delete variable(s)\n"
|
||||
#if defined(CONFIG_CMD_EDITENV)
|
||||
"env edit name - edit environment variable\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_EXPORTENV)
|
||||
"env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_ENV_FLAGS)
|
||||
"env flags - print variables that have non-default flags\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_GREPENV)
|
||||
"env grep string [...] - search environment\n"
|
||||
#endif
|
||||
#if defined(CONFIG_CMD_IMPORTENV)
|
||||
"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
|
||||
#endif
|
||||
"env print [name ...] - print environment\n"
|
||||
"env print [-a | name ...] - print environment\n"
|
||||
#if defined(CONFIG_CMD_RUN)
|
||||
"env run var [...] - run commands in an environment variable\n"
|
||||
#endif
|
||||
@ -1074,7 +1136,7 @@ U_BOOT_CMD_COMPLETE(
|
||||
U_BOOT_CMD_COMPLETE(
|
||||
printenv, CONFIG_SYS_MAXARGS, 1, do_env_print,
|
||||
"print environment variables",
|
||||
"\n - print values of all environment variables\n"
|
||||
"[-a]\n - print [all] values of all environment variables\n"
|
||||
"printenv name ...\n"
|
||||
" - print value of environment variable 'name'",
|
||||
var_complete
|
||||
@ -1093,10 +1155,10 @@ U_BOOT_CMD_COMPLETE(
|
||||
U_BOOT_CMD_COMPLETE(
|
||||
setenv, CONFIG_SYS_MAXARGS, 0, do_env_set,
|
||||
"set environment variables",
|
||||
"name value ...\n"
|
||||
" - set environment variable 'name' to 'value ...'\n"
|
||||
"setenv name\n"
|
||||
" - delete environment variable 'name'",
|
||||
"[-f] name value ...\n"
|
||||
" - [forcibly] set environment variable 'name' to 'value ...'\n"
|
||||
"setenv [-f] name\n"
|
||||
" - [forcibly] delete environment variable 'name'",
|
||||
var_complete
|
||||
);
|
||||
|
||||
|
81
common/cmd_read.c
Normal file
81
common/cmd_read.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <part.h>
|
||||
|
||||
int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
char *ep;
|
||||
block_dev_desc_t *dev_desc = NULL;
|
||||
int dev;
|
||||
int part = 0;
|
||||
disk_partition_t part_info;
|
||||
ulong offset = 0u;
|
||||
ulong limit = 0u;
|
||||
void *addr;
|
||||
uint blk;
|
||||
uint cnt;
|
||||
|
||||
if (argc != 6) {
|
||||
cmd_usage(cmdtp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = (int)simple_strtoul(argv[2], &ep, 16);
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
printf("Invalid block device %s\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
part = (int)simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
dev_desc = get_dev(argv[1], dev);
|
||||
if (dev_desc == NULL) {
|
||||
printf("Block device %s %d not supported\n", argv[1], dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr = (void *)simple_strtoul(argv[3], NULL, 16);
|
||||
blk = simple_strtoul(argv[4], NULL, 16);
|
||||
cnt = simple_strtoul(argv[5], NULL, 16);
|
||||
|
||||
if (part != 0) {
|
||||
if (get_partition_info(dev_desc, part, &part_info)) {
|
||||
printf("Cannot find partition %d\n", part);
|
||||
return 1;
|
||||
}
|
||||
offset = part_info.start;
|
||||
limit = part_info.size;
|
||||
} else {
|
||||
/* Largest address not available in block_dev_desc_t. */
|
||||
limit = ~0;
|
||||
}
|
||||
|
||||
if (cnt + blk > limit) {
|
||||
printf("Read out of range\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dev_desc->block_read(dev, offset + blk, cnt, addr) < 0) {
|
||||
printf("Error reading blocks\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
read, 6, 0, do_read,
|
||||
"Load binary data from a partition",
|
||||
"<interface> <dev[:part]> addr blk# cnt"
|
||||
);
|
@ -26,73 +26,11 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <hash.h>
|
||||
#include <sha1.h>
|
||||
|
||||
/*
|
||||
* Store the resulting sum to an address or variable
|
||||
*/
|
||||
static void store_result(const u8 *sum, const char *dest)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (*dest == '*') {
|
||||
u8 *ptr;
|
||||
|
||||
ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
|
||||
for (i = 0; i < 20; i++)
|
||||
*ptr++ = sum[i];
|
||||
} else {
|
||||
char str_output[41];
|
||||
char *str_ptr = str_output;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
sprintf(str_ptr, "%02x", sum[i]);
|
||||
str_ptr += 2;
|
||||
}
|
||||
str_ptr = '\0';
|
||||
setenv(dest, str_output);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SHA1SUM_VERIFY
|
||||
static int parse_verify_sum(char *verify_str, u8 *vsum)
|
||||
{
|
||||
if (*verify_str == '*') {
|
||||
u8 *ptr;
|
||||
|
||||
ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
|
||||
memcpy(vsum, ptr, 20);
|
||||
} else {
|
||||
unsigned int i;
|
||||
char *vsum_str;
|
||||
|
||||
if (strlen(verify_str) == 40)
|
||||
vsum_str = verify_str;
|
||||
else {
|
||||
vsum_str = getenv(verify_str);
|
||||
if (vsum_str == NULL || strlen(vsum_str) != 40)
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
char *nullp = vsum_str + (i + 1) * 2;
|
||||
char end = *nullp;
|
||||
|
||||
*nullp = '\0';
|
||||
*(u8 *)(vsum + i) =
|
||||
simple_strtoul(vsum_str + (i * 2), NULL, 16);
|
||||
*nullp = end;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
ulong addr, len;
|
||||
unsigned int i;
|
||||
u8 output[20];
|
||||
u8 vsum[20];
|
||||
int verify = 0;
|
||||
int ac;
|
||||
char * const *av;
|
||||
@ -102,76 +40,17 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
|
||||
av = argv + 1;
|
||||
ac = argc - 1;
|
||||
#ifdef CONFIG_SHA1SUM_VERIFY
|
||||
if (strcmp(*av, "-v") == 0) {
|
||||
verify = 1;
|
||||
av++;
|
||||
ac--;
|
||||
if (ac < 3)
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
addr = simple_strtoul(*av++, NULL, 16);
|
||||
len = simple_strtoul(*av++, NULL, 16);
|
||||
|
||||
sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1);
|
||||
|
||||
if (!verify) {
|
||||
printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
|
||||
for (i = 0; i < 20; i++)
|
||||
printf("%02x", output[i]);
|
||||
printf("\n");
|
||||
|
||||
if (ac > 2)
|
||||
store_result(output, *av);
|
||||
} else {
|
||||
char *verify_str = *av++;
|
||||
|
||||
if (parse_verify_sum(verify_str, vsum)) {
|
||||
printf("ERROR: %s does not contain a valid SHA1 sum\n",
|
||||
verify_str);
|
||||
return 1;
|
||||
}
|
||||
if (memcmp(output, vsum, 20) != 0) {
|
||||
printf("SHA1 for %08lx ... %08lx ==> ", addr,
|
||||
addr + len - 1);
|
||||
for (i = 0; i < 20; i++)
|
||||
printf("%02x", output[i]);
|
||||
printf(" != ");
|
||||
for (i = 0; i < 20; i++)
|
||||
printf("%02x", vsum[i]);
|
||||
printf(" ** ERROR **\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
unsigned long addr, len;
|
||||
unsigned int i;
|
||||
u8 output[20];
|
||||
|
||||
if (argc < 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
len = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1);
|
||||
printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
|
||||
for (i = 0; i < 20; i++)
|
||||
printf("%02x", output[i]);
|
||||
printf("\n");
|
||||
|
||||
if (argc > 3)
|
||||
store_result(output, argv[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return hash_command("sha1", verify, cmdtp, flag, ac, av);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SHA1SUM_VERIFY
|
||||
U_BOOT_CMD(
|
||||
sha1sum, 5, 1, do_sha1sum,
|
||||
|
@ -130,10 +130,12 @@ static int spl_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
if (call_bootm(argc, argv, subcmd_list[(int)c->cmd]))
|
||||
return -1;
|
||||
switch ((int)c->cmd) {
|
||||
#ifdef CONFIG_OF_LIBFDT
|
||||
case SPL_EXPORT_FDT:
|
||||
printf("Argument image is now in RAM: 0x%p\n",
|
||||
(void *)images.ft_addr);
|
||||
break;
|
||||
#endif
|
||||
case SPL_EXPORT_ATAGS:
|
||||
printf("Argument image is now in RAM at: 0x%p\n",
|
||||
(void *)gd->bd->bi_boot_params);
|
||||
|
@ -63,19 +63,68 @@ static int tpm_process(int argc, char * const argv[], cmd_tbl_t *cmdtp)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
#define CHECK(exp) do { \
|
||||
int _rv = exp; \
|
||||
if (_rv) { \
|
||||
printf("CHECK: %s %d %x\n", #exp, __LINE__, _rv);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int tpm_process_stress(int repeat_count)
|
||||
{
|
||||
int i;
|
||||
int rv = 0;
|
||||
u8 request[] = {0x0, 0xc1,
|
||||
0x0, 0x0, 0x0, 0x16,
|
||||
0x0, 0x0, 0x0, 0x65,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x0, 0x4,
|
||||
0x0, 0x0, 0x1, 0x9};
|
||||
u8 response[MAX_TRANSACTION_SIZE];
|
||||
u32 rlength = MAX_TRANSACTION_SIZE;
|
||||
|
||||
CHECK(tis_init());
|
||||
|
||||
for (i = 0; i < repeat_count; i++) {
|
||||
CHECK(tis_open());
|
||||
rv = tis_sendrecv(request, sizeof(request), response, &rlength);
|
||||
if (rv) {
|
||||
printf("tpm test failed at step %d with 0x%x\n", i, rv);
|
||||
CHECK(tis_close());
|
||||
break;
|
||||
}
|
||||
CHECK(tis_close());
|
||||
if ((response[6] || response[7] || response[8] || response[9])
|
||||
&& response[9] != 0x26) {
|
||||
/* Ignore postinit errors */
|
||||
printf("tpm command failed at step %d\n"
|
||||
"tpm error code: %02x%02x%02x%02x\n", i,
|
||||
response[6], response[7],
|
||||
response[8], response[9]);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int do_tpm_many(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[], int repeat_count)
|
||||
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
/*
|
||||
* Verify that in case it is present, the first argument, it is
|
||||
* exactly one character in size.
|
||||
*/
|
||||
if (argc < 7) {
|
||||
if (argc < 7 && repeat_count == 0) {
|
||||
puts("command should be at least six bytes in size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (repeat_count > 0) {
|
||||
rv = tpm_process_stress(repeat_count);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (tis_init()) {
|
||||
puts("tis_init() failed!\n");
|
||||
return -1;
|
||||
@ -96,8 +145,40 @@ static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return do_tpm_many(cmdtp, flag, argc, argv, 0);
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(tpm, MAX_TRANSACTION_SIZE, 1, do_tpm,
|
||||
"<byte> [<byte> ...] - write data and read response",
|
||||
"send arbitrary data (at least 6 bytes) to the TPM "
|
||||
"device and read the response"
|
||||
);
|
||||
|
||||
static int do_tpm_stress(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
long unsigned int n;
|
||||
int rv;
|
||||
|
||||
if (argc != 2) {
|
||||
puts("usage: tpm_stress <count>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = strict_strtoul(argv[1], 10, &n);
|
||||
if (rv) {
|
||||
puts("tpm_stress: bad count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return do_tpm_many(cmdtp, flag, argc, argv, n);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(tpm_stress, 2, 1, do_tpm_stress,
|
||||
"<n> - stress-test communication with TPM",
|
||||
"Repeat a TPM transaction (request-response) N times"
|
||||
);
|
||||
|
@ -24,11 +24,78 @@
|
||||
#include <common.h>
|
||||
#include <stdarg.h>
|
||||
#include <malloc.h>
|
||||
#include <serial.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <exports.h>
|
||||
#include <environment.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int on_console(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
int console = -1;
|
||||
|
||||
/* Check for console redirection */
|
||||
if (strcmp(name, "stdin") == 0)
|
||||
console = stdin;
|
||||
else if (strcmp(name, "stdout") == 0)
|
||||
console = stdout;
|
||||
else if (strcmp(name, "stderr") == 0)
|
||||
console = stderr;
|
||||
|
||||
/* if not actually setting a console variable, we don't care */
|
||||
if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0)
|
||||
return 0;
|
||||
|
||||
switch (op) {
|
||||
case env_op_create:
|
||||
case env_op_overwrite:
|
||||
|
||||
#ifdef CONFIG_CONSOLE_MUX
|
||||
if (iomux_doenv(console, value))
|
||||
return 1;
|
||||
#else
|
||||
/* Try assigning specified device */
|
||||
if (console_assign(console, value) < 0)
|
||||
return 1;
|
||||
#endif /* CONFIG_CONSOLE_MUX */
|
||||
return 0;
|
||||
|
||||
case env_op_delete:
|
||||
if ((flags & H_FORCE) == 0)
|
||||
printf("Can't delete \"%s\"\n", name);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(console, on_console);
|
||||
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
static int on_silent(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
|
||||
if (flags & H_INTERACTIVE)
|
||||
return 0;
|
||||
#endif
|
||||
#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC
|
||||
if ((flags & H_INTERACTIVE) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (value != NULL)
|
||||
gd->flags |= GD_FLG_SILENT;
|
||||
else
|
||||
gd->flags &= ~GD_FLG_SILENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(silent, on_silent);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
|
||||
/*
|
||||
* if overwrite_console returns 1, the stdin, stderr and stdout
|
||||
@ -591,7 +658,6 @@ int console_init_f(void)
|
||||
|
||||
void stdio_print_current_devices(void)
|
||||
{
|
||||
#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
|
||||
/* Print information */
|
||||
puts("In: ");
|
||||
if (stdio_devices[stdin] == NULL) {
|
||||
@ -613,7 +679,6 @@ void stdio_print_current_devices(void)
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stderr]->name);
|
||||
}
|
||||
#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
|
||||
@ -683,9 +748,9 @@ int console_init_r(void)
|
||||
done:
|
||||
#endif
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
|
||||
stdio_print_current_devices();
|
||||
#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
|
||||
|
||||
#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
|
||||
/* set the environment variables (will overwrite previous env settings) */
|
||||
@ -694,6 +759,8 @@ done:
|
||||
}
|
||||
#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
@ -758,15 +825,17 @@ int console_init_r(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
|
||||
stdio_print_current_devices();
|
||||
#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
|
||||
|
||||
/* Setting environment variables */
|
||||
for (i = 0; i < 3; i++) {
|
||||
setenv(stdio_names[i], stdio_devices[i]->name);
|
||||
}
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
|
307
common/edid.c
Normal file
307
common/edid.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
*
|
||||
* (C) Copyright 2010
|
||||
* Petr Stetiar <ynezz@true.cz>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Contains stolen code from ddcprobe project which is:
|
||||
* Copyright (C) Nalin Dahyabhai <bigfun@pobox.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <edid.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
int edid_check_info(struct edid1_info *edid_info)
|
||||
{
|
||||
if ((edid_info == NULL) || (edid_info->version == 0))
|
||||
return -1;
|
||||
|
||||
if (memcmp(edid_info->header, "\x0\xff\xff\xff\xff\xff\xff\x0", 8))
|
||||
return -1;
|
||||
|
||||
if (edid_info->version == 0xff && edid_info->revision == 0xff)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
|
||||
unsigned int *hmax, unsigned int *vmin,
|
||||
unsigned int *vmax)
|
||||
{
|
||||
int i;
|
||||
struct edid_monitor_descriptor *monitor;
|
||||
|
||||
*hmin = *hmax = *vmin = *vmax = 0;
|
||||
if (edid_check_info(edid))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(edid->monitor_details.descriptor); i++) {
|
||||
monitor = &edid->monitor_details.descriptor[i];
|
||||
if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE) {
|
||||
*hmin = monitor->data.range_data.horizontal_min;
|
||||
*hmax = monitor->data.range_data.horizontal_max;
|
||||
*vmin = monitor->data.range_data.vertical_min;
|
||||
*vmax = monitor->data.range_data.vertical_max;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Snip the tailing whitespace/return of a string.
|
||||
*
|
||||
* @param string The string to be snipped
|
||||
* @return the snipped string
|
||||
*/
|
||||
static char *snip(char *string)
|
||||
{
|
||||
char *s;
|
||||
|
||||
/*
|
||||
* This is always a 13 character buffer
|
||||
* and it's not always terminated.
|
||||
*/
|
||||
string[12] = '\0';
|
||||
s = &string[strlen(string) - 1];
|
||||
|
||||
while (s >= string && (isspace(*s) || *s == '\n' || *s == '\r' ||
|
||||
*s == '\0'))
|
||||
*(s--) = '\0';
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an EDID monitor descriptor block
|
||||
*
|
||||
* @param monitor The EDID monitor descriptor block
|
||||
* @have_timing Modifies to 1 if the desciptor contains timing info
|
||||
*/
|
||||
static void edid_print_dtd(struct edid_monitor_descriptor *monitor,
|
||||
unsigned int *have_timing)
|
||||
{
|
||||
unsigned char *bytes = (unsigned char *)monitor;
|
||||
struct edid_detailed_timing *timing =
|
||||
(struct edid_detailed_timing *)monitor;
|
||||
|
||||
if (bytes[0] == 0 && bytes[1] == 0) {
|
||||
if (monitor->type == EDID_MONITOR_DESCRIPTOR_SERIAL)
|
||||
printf("Monitor serial number: %s\n",
|
||||
snip(monitor->data.string));
|
||||
else if (monitor->type == EDID_MONITOR_DESCRIPTOR_ASCII)
|
||||
printf("Monitor ID: %s\n",
|
||||
snip(monitor->data.string));
|
||||
else if (monitor->type == EDID_MONITOR_DESCRIPTOR_NAME)
|
||||
printf("Monitor name: %s\n",
|
||||
snip(monitor->data.string));
|
||||
else if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE)
|
||||
printf("Monitor range limits, horizontal sync: "
|
||||
"%d-%d kHz, vertical refresh: "
|
||||
"%d-%d Hz, max pixel clock: "
|
||||
"%d MHz\n",
|
||||
monitor->data.range_data.horizontal_min,
|
||||
monitor->data.range_data.horizontal_max,
|
||||
monitor->data.range_data.vertical_min,
|
||||
monitor->data.range_data.vertical_max,
|
||||
monitor->data.range_data.pixel_clock_max * 10);
|
||||
} else {
|
||||
uint32_t pixclock, h_active, h_blanking, v_active, v_blanking;
|
||||
uint32_t h_total, v_total, vfreq;
|
||||
|
||||
pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
|
||||
h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
|
||||
h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
|
||||
v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
|
||||
v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
|
||||
|
||||
h_total = h_active + h_blanking;
|
||||
v_total = v_active + v_blanking;
|
||||
if (v_total * h_total)
|
||||
vfreq = pixclock / (v_total * h_total);
|
||||
else
|
||||
vfreq = 1; /* Error case */
|
||||
printf("\t%dx%d\%c\t%d Hz (detailed)\n", h_active,
|
||||
v_active, h_active > 1000 ? ' ' : '\t', vfreq);
|
||||
*have_timing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the manufacturer name from an EDID info.
|
||||
*
|
||||
* @param edid_info The EDID info to be printed
|
||||
* @param name Returns the string of the manufacturer name
|
||||
*/
|
||||
static void edid_get_manufacturer_name(struct edid1_info *edid, char *name)
|
||||
{
|
||||
name[0] = EDID1_INFO_MANUFACTURER_NAME_CHAR1(*edid) + 'A' - 1;
|
||||
name[1] = EDID1_INFO_MANUFACTURER_NAME_CHAR2(*edid) + 'A' - 1;
|
||||
name[2] = EDID1_INFO_MANUFACTURER_NAME_CHAR3(*edid) + 'A' - 1;
|
||||
name[3] = '\0';
|
||||
}
|
||||
|
||||
void edid_print_info(struct edid1_info *edid_info)
|
||||
{
|
||||
int i;
|
||||
char manufacturer[4];
|
||||
unsigned int have_timing = 0;
|
||||
uint32_t serial_number;
|
||||
|
||||
if (edid_check_info(edid_info)) {
|
||||
printf("Not a valid EDID\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("EDID version: %d.%d\n",
|
||||
edid_info->version, edid_info->revision);
|
||||
|
||||
printf("Product ID code: %04x\n", EDID1_INFO_PRODUCT_CODE(*edid_info));
|
||||
|
||||
edid_get_manufacturer_name(edid_info, manufacturer);
|
||||
printf("Manufacturer: %s\n", manufacturer);
|
||||
|
||||
serial_number = EDID1_INFO_SERIAL_NUMBER(*edid_info);
|
||||
if (serial_number != 0xffffffff) {
|
||||
if (strcmp(manufacturer, "MAG") == 0)
|
||||
serial_number -= 0x7000000;
|
||||
if (strcmp(manufacturer, "OQI") == 0)
|
||||
serial_number -= 456150000;
|
||||
if (strcmp(manufacturer, "VSC") == 0)
|
||||
serial_number -= 640000000;
|
||||
}
|
||||
printf("Serial number: %08x\n", serial_number);
|
||||
printf("Manufactured in week: %d year: %d\n",
|
||||
edid_info->week, edid_info->year + 1990);
|
||||
|
||||
printf("Video input definition: %svoltage level %d%s%s%s%s%s\n",
|
||||
EDID1_INFO_VIDEO_INPUT_DIGITAL(*edid_info) ?
|
||||
"digital signal, " : "analog signal, ",
|
||||
EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(*edid_info),
|
||||
EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(*edid_info) ?
|
||||
", blank to black" : "",
|
||||
EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(*edid_info) ?
|
||||
", separate sync" : "",
|
||||
EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(*edid_info) ?
|
||||
", composite sync" : "",
|
||||
EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(*edid_info) ?
|
||||
", sync on green" : "",
|
||||
EDID1_INFO_VIDEO_INPUT_SERRATION_V(*edid_info) ?
|
||||
", serration v" : "");
|
||||
|
||||
printf("Monitor is %s\n",
|
||||
EDID1_INFO_FEATURE_RGB(*edid_info) ? "RGB" : "non-RGB");
|
||||
|
||||
printf("Maximum visible display size: %d cm x %d cm\n",
|
||||
edid_info->max_size_horizontal,
|
||||
edid_info->max_size_vertical);
|
||||
|
||||
printf("Power management features: %s%s, %s%s, %s%s\n",
|
||||
EDID1_INFO_FEATURE_ACTIVE_OFF(*edid_info) ?
|
||||
"" : "no ", "active off",
|
||||
EDID1_INFO_FEATURE_SUSPEND(*edid_info) ? "" : "no ", "suspend",
|
||||
EDID1_INFO_FEATURE_STANDBY(*edid_info) ? "" : "no ", "standby");
|
||||
|
||||
printf("Estabilished timings:\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_720X400_70(*edid_info))
|
||||
printf("\t720x400\t\t70 Hz (VGA 640x400, IBM)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_720X400_88(*edid_info))
|
||||
printf("\t720x400\t\t88 Hz (XGA2)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_640X480_60(*edid_info))
|
||||
printf("\t640x480\t\t60 Hz (VGA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_640X480_67(*edid_info))
|
||||
printf("\t640x480\t\t67 Hz (Mac II, Apple)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_640X480_72(*edid_info))
|
||||
printf("\t640x480\t\t72 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_640X480_75(*edid_info))
|
||||
printf("\t640x480\t\t75 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_800X600_56(*edid_info))
|
||||
printf("\t800x600\t\t56 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_800X600_60(*edid_info))
|
||||
printf("\t800x600\t\t60 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_800X600_72(*edid_info))
|
||||
printf("\t800x600\t\t72 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_800X600_75(*edid_info))
|
||||
printf("\t800x600\t\t75 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_832X624_75(*edid_info))
|
||||
printf("\t832x624\t\t75 Hz (Mac II)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(*edid_info))
|
||||
printf("\t1024x768\t87 Hz Interlaced (8514A)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(*edid_info))
|
||||
printf("\t1024x768\t60 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(*edid_info))
|
||||
printf("\t1024x768\t70 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(*edid_info))
|
||||
printf("\t1024x768\t75 Hz (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(*edid_info))
|
||||
printf("\t1280x1024\t75 (VESA)\n");
|
||||
if (EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(*edid_info))
|
||||
printf("\t1152x870\t75 (Mac II)\n");
|
||||
|
||||
/* Standard timings. */
|
||||
printf("Standard timings:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(edid_info->standard_timings); i++) {
|
||||
unsigned int aspect = 10000;
|
||||
unsigned int x, y;
|
||||
unsigned char xres, vfreq;
|
||||
|
||||
xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid_info, i);
|
||||
vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid_info, i);
|
||||
if ((xres != vfreq) ||
|
||||
((xres != 0) && (xres != 1)) ||
|
||||
((vfreq != 0) && (vfreq != 1))) {
|
||||
switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid_info,
|
||||
i)) {
|
||||
case ASPECT_625:
|
||||
aspect = 6250;
|
||||
break;
|
||||
case ASPECT_75:
|
||||
aspect = 7500;
|
||||
break;
|
||||
case ASPECT_8:
|
||||
aspect = 8000;
|
||||
break;
|
||||
case ASPECT_5625:
|
||||
aspect = 5625;
|
||||
break;
|
||||
}
|
||||
x = (xres + 31) * 8;
|
||||
y = x * aspect / 10000;
|
||||
printf("\t%dx%d%c\t%d Hz\n", x, y,
|
||||
x > 1000 ? ' ' : '\t', (vfreq & 0x3f) + 60);
|
||||
have_timing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Detailed timing information. */
|
||||
for (i = 0; i < ARRAY_SIZE(edid_info->monitor_details.descriptor);
|
||||
i++) {
|
||||
edid_print_dtd(&edid_info->monitor_details.descriptor[i],
|
||||
&have_timing);
|
||||
}
|
||||
|
||||
if (!have_timing)
|
||||
printf("\tNone\n");
|
||||
}
|
229
common/env_attr.c
Normal file
229
common/env_attr.c
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/linux_string.h>
|
||||
#else
|
||||
#include <common.h>
|
||||
#endif
|
||||
|
||||
#include <env_attr.h>
|
||||
#include <errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/*
|
||||
* Iterate through the whole list calling the callback for each found element.
|
||||
* "attr_list" takes the form:
|
||||
* attributes = [^,:\s]*
|
||||
* entry = name[:attributes]
|
||||
* list = entry[,list]
|
||||
*/
|
||||
int env_attr_walk(const char *attr_list,
|
||||
int (*callback)(const char *name, const char *attributes))
|
||||
{
|
||||
const char *entry, *entry_end;
|
||||
char *name, *attributes;
|
||||
|
||||
if (!attr_list)
|
||||
/* list not found */
|
||||
return 1;
|
||||
|
||||
entry = attr_list;
|
||||
do {
|
||||
char *entry_cpy = NULL;
|
||||
|
||||
entry_end = strchr(entry, ENV_ATTR_LIST_DELIM);
|
||||
/* check if this is the last entry in the list */
|
||||
if (entry_end == NULL) {
|
||||
int entry_len = strlen(entry);
|
||||
|
||||
if (entry_len) {
|
||||
/*
|
||||
* allocate memory to copy the entry into since
|
||||
* we will need to inject '\0' chars and squash
|
||||
* white-space before calling the callback
|
||||
*/
|
||||
entry_cpy = malloc(entry_len + 1);
|
||||
if (entry_cpy)
|
||||
/* copy the rest of the list */
|
||||
strcpy(entry_cpy, entry);
|
||||
else
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
int entry_len = entry_end - entry;
|
||||
|
||||
if (entry_len) {
|
||||
/*
|
||||
* allocate memory to copy the entry into since
|
||||
* we will need to inject '\0' chars and squash
|
||||
* white-space before calling the callback
|
||||
*/
|
||||
entry_cpy = malloc(entry_len + 1);
|
||||
if (entry_cpy) {
|
||||
/* copy just this entry and null term */
|
||||
strncpy(entry_cpy, entry, entry_len);
|
||||
entry_cpy[entry_len] = '\0';
|
||||
} else
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if there is anything to process (e.g. not ",,,") */
|
||||
if (entry_cpy != NULL) {
|
||||
attributes = strchr(entry_cpy, ENV_ATTR_SEP);
|
||||
/* check if there is a ':' */
|
||||
if (attributes != NULL) {
|
||||
/* replace the ':' with '\0' to term name */
|
||||
*attributes++ = '\0';
|
||||
/* remove white-space from attributes */
|
||||
attributes = strim(attributes);
|
||||
}
|
||||
/* remove white-space from name */
|
||||
name = strim(entry_cpy);
|
||||
|
||||
/* only call the callback if there is a name */
|
||||
if (strlen(name) != 0) {
|
||||
int retval = 0;
|
||||
|
||||
retval = callback(name, attributes);
|
||||
if (retval) {
|
||||
free(entry_cpy);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(entry_cpy);
|
||||
entry = entry_end + 1;
|
||||
} while (entry_end != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for the last matching string in another string with the option to
|
||||
* start looking at a certain point (i.e. ignore anything beyond that point).
|
||||
*/
|
||||
static char *reverse_strstr(const char *searched, const char *search_for,
|
||||
const char *searched_start)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
if (*search_for == '\0')
|
||||
return (char *)searched;
|
||||
|
||||
for (;;) {
|
||||
char *match = strstr(searched, search_for);
|
||||
|
||||
/*
|
||||
* Stop looking if no new match is found or looking past the
|
||||
* searched_start pointer
|
||||
*/
|
||||
if (match == NULL || (searched_start != NULL &&
|
||||
match + strlen(search_for) > searched_start))
|
||||
break;
|
||||
|
||||
result = match;
|
||||
searched = match + 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the attributes string associated with a single name in the list
|
||||
* There is no protection on attributes being too small for the value
|
||||
*/
|
||||
int env_attr_lookup(const char *attr_list, const char *name, char *attributes)
|
||||
{
|
||||
const char *entry = NULL;
|
||||
|
||||
if (!attributes)
|
||||
/* bad parameter */
|
||||
return -1;
|
||||
if (!attr_list)
|
||||
/* list not found */
|
||||
return 1;
|
||||
|
||||
entry = reverse_strstr(attr_list, name, NULL);
|
||||
while (entry != NULL) {
|
||||
const char *prevch = entry - 1;
|
||||
const char *nextch = entry + strlen(name);
|
||||
|
||||
/* Skip spaces */
|
||||
while (*prevch == ' ')
|
||||
prevch--;
|
||||
while (*nextch == ' ')
|
||||
nextch++;
|
||||
|
||||
/* check for an exact match */
|
||||
if ((entry == attr_list ||
|
||||
*prevch == ENV_ATTR_LIST_DELIM) &&
|
||||
(*nextch == ENV_ATTR_SEP ||
|
||||
*nextch == ENV_ATTR_LIST_DELIM ||
|
||||
*nextch == '\0'))
|
||||
break;
|
||||
|
||||
entry = reverse_strstr(attr_list, name, entry);
|
||||
}
|
||||
if (entry != NULL) {
|
||||
int len;
|
||||
|
||||
/* skip the name */
|
||||
entry += strlen(name);
|
||||
/* skip spaces */
|
||||
while (*entry == ' ')
|
||||
entry++;
|
||||
if (*entry != ENV_ATTR_SEP)
|
||||
len = 0;
|
||||
else {
|
||||
const char *delim;
|
||||
static const char delims[] = {
|
||||
ENV_ATTR_LIST_DELIM, ' ', '\0'};
|
||||
|
||||
/* skip the attr sep */
|
||||
entry += 1;
|
||||
/* skip spaces */
|
||||
while (*entry == ' ')
|
||||
entry++;
|
||||
|
||||
delim = strpbrk(entry, delims);
|
||||
if (delim == NULL)
|
||||
len = strlen(entry);
|
||||
else
|
||||
len = delim - entry;
|
||||
memcpy(attributes, entry, len);
|
||||
}
|
||||
attributes[len] = '\0';
|
||||
|
||||
/* success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not found in list */
|
||||
return 2;
|
||||
}
|
144
common/env_callback.c
Normal file
144
common/env_callback.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <environment.h>
|
||||
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Look up a callback function pointer by name
|
||||
*/
|
||||
struct env_clbk_tbl *find_env_callback(const char *name)
|
||||
{
|
||||
struct env_clbk_tbl *clbkp;
|
||||
int i;
|
||||
int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
/* look up the callback in the linker-list */
|
||||
for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
|
||||
i < num_callbacks;
|
||||
i++, clbkp++) {
|
||||
if (strcmp(name, clbkp->name) == 0)
|
||||
return clbkp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for a possible callback for a newly added variable
|
||||
* This is called specifically when the variable did not exist in the hash
|
||||
* previously, so the blanket update did not find this variable.
|
||||
*/
|
||||
void env_callback_init(ENTRY *var_entry)
|
||||
{
|
||||
const char *var_name = var_entry->key;
|
||||
const char *callback_list = getenv(ENV_CALLBACK_VAR);
|
||||
char callback_name[256] = "";
|
||||
struct env_clbk_tbl *clbkp;
|
||||
int ret = 1;
|
||||
|
||||
/* look in the ".callbacks" var for a reference to this variable */
|
||||
if (callback_list != NULL)
|
||||
ret = env_attr_lookup(callback_list, var_name, callback_name);
|
||||
|
||||
/* only if not found there, look in the static list */
|
||||
if (ret)
|
||||
ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name,
|
||||
callback_name);
|
||||
|
||||
/* if an association was found, set the callback pointer */
|
||||
if (!ret && strlen(callback_name)) {
|
||||
clbkp = find_env_callback(callback_name);
|
||||
if (clbkp != NULL)
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
var_entry->callback = clbkp->callback + gd->reloc_off;
|
||||
#else
|
||||
var_entry->callback = clbkp->callback;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on each existing env var prior to the blanket update since removing
|
||||
* a callback association should remove its callback.
|
||||
*/
|
||||
static int clear_callback(ENTRY *entry)
|
||||
{
|
||||
entry->callback = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call for each element in the list that associates variables to callbacks
|
||||
*/
|
||||
static int set_callback(const char *name, const char *value)
|
||||
{
|
||||
ENTRY e, *ep;
|
||||
struct env_clbk_tbl *clbkp;
|
||||
|
||||
e.key = name;
|
||||
e.data = NULL;
|
||||
hsearch_r(e, FIND, &ep, &env_htab, 0);
|
||||
|
||||
/* does the env variable actually exist? */
|
||||
if (ep != NULL) {
|
||||
/* the assocaition delares no callback, so remove the pointer */
|
||||
if (value == NULL || strlen(value) == 0)
|
||||
ep->callback = NULL;
|
||||
else {
|
||||
/* assign the requested callback */
|
||||
clbkp = find_env_callback(value);
|
||||
if (clbkp != NULL)
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
ep->callback = clbkp->callback + gd->reloc_off;
|
||||
#else
|
||||
ep->callback = clbkp->callback;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_callbacks(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
/* remove all callbacks */
|
||||
hwalk_r(&env_htab, clear_callback);
|
||||
|
||||
/* configure any static callback bindings */
|
||||
env_attr_walk(ENV_CALLBACK_LIST_STATIC, set_callback);
|
||||
/* configure any dynamic callback bindings */
|
||||
env_attr_walk(value, set_callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(callbacks, on_callbacks);
|
@ -40,7 +40,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
#include <env_default.h>
|
||||
|
||||
struct hsearch_data env_htab = {
|
||||
.apply = env_check_apply,
|
||||
.change_ok = env_flags_validate,
|
||||
};
|
||||
|
||||
static uchar __env_get_char_spec(int index)
|
||||
@ -81,13 +81,42 @@ const uchar *env_get_addr(int index)
|
||||
return &default_environment[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an environment variable as a boolean
|
||||
* Return -1 if variable does not exist (default to true)
|
||||
*/
|
||||
int getenv_yesno(const char *var)
|
||||
{
|
||||
char *s = getenv(var);
|
||||
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ?
|
||||
1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the variable from the default environment
|
||||
*/
|
||||
char *getenv_default(const char *name)
|
||||
{
|
||||
char *ret_val;
|
||||
unsigned long really_valid = gd->env_valid;
|
||||
unsigned long real_gd_flags = gd->flags;
|
||||
|
||||
/* Pretend that the image is bad. */
|
||||
gd->flags &= ~GD_FLG_ENV_READY;
|
||||
gd->env_valid = 0;
|
||||
ret_val = getenv(name);
|
||||
gd->env_valid = really_valid;
|
||||
gd->flags = real_gd_flags;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void set_default_env(const char *s)
|
||||
{
|
||||
/*
|
||||
* By default, do not apply changes as they will eventually
|
||||
* be applied by someone else
|
||||
*/
|
||||
int do_apply = 0;
|
||||
int flags = 0;
|
||||
|
||||
if (sizeof(default_environment) > ENV_SIZE) {
|
||||
puts("*** Error - default environment is too large\n\n");
|
||||
return;
|
||||
@ -99,14 +128,7 @@ void set_default_env(const char *s)
|
||||
"using default environment\n\n",
|
||||
s + 1);
|
||||
} else {
|
||||
/*
|
||||
* This set_to_default was explicitly asked for
|
||||
* by the user, as opposed to being a recovery
|
||||
* mechanism. Therefore we check every single
|
||||
* variable and apply changes to the system
|
||||
* right away (e.g. baudrate, console).
|
||||
*/
|
||||
do_apply = 1;
|
||||
flags = H_INTERACTIVE;
|
||||
puts(s);
|
||||
}
|
||||
} else {
|
||||
@ -114,8 +136,8 @@ void set_default_env(const char *s)
|
||||
}
|
||||
|
||||
if (himport_r(&env_htab, (char *)default_environment,
|
||||
sizeof(default_environment), '\0', 0,
|
||||
0, NULL, do_apply) == 0)
|
||||
sizeof(default_environment), '\0', flags,
|
||||
0, NULL) == 0)
|
||||
error("Environment import failed: errno = %d\n", errno);
|
||||
|
||||
gd->flags |= GD_FLG_ENV_READY;
|
||||
@ -130,8 +152,8 @@ int set_default_vars(int nvars, char * const vars[])
|
||||
* (and use \0 as a separator)
|
||||
*/
|
||||
return himport_r(&env_htab, (const char *)default_environment,
|
||||
sizeof(default_environment), '\0', H_NOCLEAR,
|
||||
nvars, vars, 1 /* do_apply */);
|
||||
sizeof(default_environment), '\0',
|
||||
H_NOCLEAR | H_INTERACTIVE, nvars, vars);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
@ -155,7 +177,7 @@ int env_import(const char *buf, int check)
|
||||
}
|
||||
|
||||
if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
|
||||
0, NULL, 0 /* do_apply */)) {
|
||||
0, NULL)) {
|
||||
gd->flags |= GD_FLG_ENV_READY;
|
||||
return 1;
|
||||
}
|
||||
@ -172,6 +194,7 @@ void env_relocate(void)
|
||||
{
|
||||
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
||||
env_reloc();
|
||||
env_htab.change_ok += gd->reloc_off;
|
||||
#endif
|
||||
if (gd->env_valid == 0) {
|
||||
#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
|
||||
|
@ -60,7 +60,7 @@ int saveenv(void)
|
||||
char *res;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -139,7 +139,7 @@ int saveenv(void)
|
||||
BUG_ON(env_ptr != NULL);
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -61,7 +61,7 @@ int saveenv(void)
|
||||
int err;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
560
common/env_flags.c
Normal file
560
common/env_flags.c
Normal file
@ -0,0 +1,560 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "fw_env.h"
|
||||
#include <env_attr.h>
|
||||
#include <env_flags.h>
|
||||
#define getenv fw_getenv
|
||||
#else
|
||||
#include <common.h>
|
||||
#include <environment.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#define ENV_FLAGS_NET_VARTYPE_REPS "im"
|
||||
#else
|
||||
#define ENV_FLAGS_NET_VARTYPE_REPS ""
|
||||
#endif
|
||||
|
||||
static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS;
|
||||
static const char env_flags_varaccess_rep[] = "aroc";
|
||||
static const int env_flags_varaccess_mask[] = {
|
||||
0,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
|
||||
ENV_FLAGS_VARACCESS_PREVENT_CREATE |
|
||||
ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
|
||||
ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_DELETE |
|
||||
ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR};
|
||||
|
||||
#ifdef CONFIG_CMD_ENV_FLAGS
|
||||
static const char * const env_flags_vartype_names[] = {
|
||||
"string",
|
||||
"decimal",
|
||||
"hexadecimal",
|
||||
"boolean",
|
||||
#ifdef CONFIG_CMD_NET
|
||||
"IP address",
|
||||
"MAC address",
|
||||
#endif
|
||||
};
|
||||
static const char * const env_flags_varaccess_names[] = {
|
||||
"any",
|
||||
"read-only",
|
||||
"write-once",
|
||||
"change-default",
|
||||
};
|
||||
|
||||
/*
|
||||
* Print the whole list of available type flags.
|
||||
*/
|
||||
void env_flags_print_vartypes(void)
|
||||
{
|
||||
enum env_flags_vartype curtype = (enum env_flags_vartype)0;
|
||||
|
||||
while (curtype != env_flags_vartype_end) {
|
||||
printf("\t%c -\t%s\n", env_flags_vartype_rep[curtype],
|
||||
env_flags_vartype_names[curtype]);
|
||||
curtype++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the whole list of available access flags.
|
||||
*/
|
||||
void env_flags_print_varaccess(void)
|
||||
{
|
||||
enum env_flags_varaccess curaccess = (enum env_flags_varaccess)0;
|
||||
|
||||
while (curaccess != env_flags_varaccess_end) {
|
||||
printf("\t%c -\t%s\n", env_flags_varaccess_rep[curaccess],
|
||||
env_flags_varaccess_names[curaccess]);
|
||||
curaccess++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the type.
|
||||
*/
|
||||
const char *env_flags_get_vartype_name(enum env_flags_vartype type)
|
||||
{
|
||||
return env_flags_vartype_names[type];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the access.
|
||||
*/
|
||||
const char *env_flags_get_varaccess_name(enum env_flags_varaccess access)
|
||||
{
|
||||
return env_flags_varaccess_names[access];
|
||||
}
|
||||
#endif /* CONFIG_CMD_ENV_FLAGS */
|
||||
|
||||
/*
|
||||
* Parse the flags string from a .flags attribute list into the vartype enum.
|
||||
*/
|
||||
enum env_flags_vartype env_flags_parse_vartype(const char *flags)
|
||||
{
|
||||
char *type;
|
||||
|
||||
if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC)
|
||||
return env_flags_vartype_string;
|
||||
|
||||
type = strchr(env_flags_vartype_rep,
|
||||
flags[ENV_FLAGS_VARTYPE_LOC]);
|
||||
|
||||
if (type != NULL)
|
||||
return (enum env_flags_vartype)
|
||||
(type - &env_flags_vartype_rep[0]);
|
||||
|
||||
printf("## Warning: Unknown environment variable type '%c'\n",
|
||||
flags[ENV_FLAGS_VARTYPE_LOC]);
|
||||
return env_flags_vartype_string;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the flags string from a .flags attribute list into the varaccess enum.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
|
||||
{
|
||||
char *access;
|
||||
|
||||
if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
|
||||
return env_flags_varaccess_any;
|
||||
|
||||
access = strchr(env_flags_varaccess_rep,
|
||||
flags[ENV_FLAGS_VARACCESS_LOC]);
|
||||
|
||||
if (access != NULL)
|
||||
return (enum env_flags_varaccess)
|
||||
(access - &env_flags_varaccess_rep[0]);
|
||||
|
||||
printf("## Warning: Unknown environment variable access method '%c'\n",
|
||||
flags[ENV_FLAGS_VARACCESS_LOC]);
|
||||
return env_flags_varaccess_any;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the binary flags from a hash table entry into the varaccess enum.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(env_flags_varaccess_mask); i++)
|
||||
if (env_flags_varaccess_mask[i] ==
|
||||
(binflags & ENV_FLAGS_VARACCESS_BIN_MASK))
|
||||
return (enum env_flags_varaccess)i;
|
||||
|
||||
printf("Warning: Non-standard access flags. (0x%x)\n",
|
||||
binflags & ENV_FLAGS_VARACCESS_BIN_MASK);
|
||||
|
||||
return env_flags_varaccess_any;
|
||||
}
|
||||
|
||||
static inline int is_hex_prefix(const char *value)
|
||||
{
|
||||
return value[0] == '0' && (value[1] == 'x' || value[1] == 'X');
|
||||
}
|
||||
|
||||
static void skip_num(int hex, const char *value, const char **end,
|
||||
int max_digits)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (hex && is_hex_prefix(value))
|
||||
value += 2;
|
||||
|
||||
for (i = max_digits; i != 0; i--) {
|
||||
if (hex && !isxdigit(*value))
|
||||
break;
|
||||
if (!hex && !isdigit(*value))
|
||||
break;
|
||||
value++;
|
||||
}
|
||||
if (end != NULL)
|
||||
*end = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on the declared type enum, validate that the value string complies
|
||||
* with that format
|
||||
*/
|
||||
static int _env_flags_validate_type(const char *value,
|
||||
enum env_flags_vartype type)
|
||||
{
|
||||
const char *end;
|
||||
#ifdef CONFIG_CMD_NET
|
||||
const char *cur;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case env_flags_vartype_string:
|
||||
break;
|
||||
case env_flags_vartype_decimal:
|
||||
skip_num(0, value, &end, -1);
|
||||
if (*end != '\0')
|
||||
return -1;
|
||||
break;
|
||||
case env_flags_vartype_hex:
|
||||
skip_num(1, value, &end, -1);
|
||||
if (*end != '\0')
|
||||
return -1;
|
||||
if (value + 2 == end && is_hex_prefix(value))
|
||||
return -1;
|
||||
break;
|
||||
case env_flags_vartype_bool:
|
||||
if (value[0] != '1' && value[0] != 'y' && value[0] != 't' &&
|
||||
value[0] != 'Y' && value[0] != 'T' &&
|
||||
value[0] != '0' && value[0] != 'n' && value[0] != 'f' &&
|
||||
value[0] != 'N' && value[0] != 'F')
|
||||
return -1;
|
||||
if (value[1] != '\0')
|
||||
return -1;
|
||||
break;
|
||||
#ifdef CONFIG_CMD_NET
|
||||
case env_flags_vartype_ipaddr:
|
||||
cur = value;
|
||||
for (i = 0; i < 4; i++) {
|
||||
skip_num(0, cur, &end, 3);
|
||||
if (cur == end)
|
||||
return -1;
|
||||
if (i != 3 && *end != '.')
|
||||
return -1;
|
||||
if (i == 3 && *end != '\0')
|
||||
return -1;
|
||||
cur = end + 1;
|
||||
}
|
||||
break;
|
||||
case env_flags_vartype_macaddr:
|
||||
cur = value;
|
||||
for (i = 0; i < 6; i++) {
|
||||
skip_num(1, cur, &end, 2);
|
||||
if (cur == end)
|
||||
return -1;
|
||||
if (cur + 2 == end && is_hex_prefix(cur))
|
||||
return -1;
|
||||
if (i != 5 && *end != ':')
|
||||
return -1;
|
||||
if (i == 5 && *end != '\0')
|
||||
return -1;
|
||||
cur = end + 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case env_flags_vartype_end:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* OK */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for flags in a provided list and failing that the static list
|
||||
*/
|
||||
static inline int env_flags_lookup(const char *flags_list, const char *name,
|
||||
char *flags)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (!flags)
|
||||
/* bad parameter */
|
||||
return -1;
|
||||
|
||||
/* try the env first */
|
||||
if (flags_list)
|
||||
ret = env_attr_lookup(flags_list, name, flags);
|
||||
|
||||
if (ret != 0)
|
||||
/* if not found in the env, look in the static list */
|
||||
ret = env_attr_lookup(ENV_FLAGS_LIST_STATIC, name, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef USE_HOSTCC /* Functions only used from tools/env */
|
||||
/*
|
||||
* Look up any flags directly from the .flags variable and the static list
|
||||
* and convert them to the vartype enum.
|
||||
*/
|
||||
enum env_flags_vartype env_flags_get_type(const char *name)
|
||||
{
|
||||
const char *flags_list = getenv(ENV_FLAGS_VAR);
|
||||
char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
|
||||
|
||||
if (env_flags_lookup(flags_list, name, flags))
|
||||
return env_flags_vartype_string;
|
||||
|
||||
if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC)
|
||||
return env_flags_vartype_string;
|
||||
|
||||
return env_flags_parse_vartype(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the access of a variable directly from the .flags var.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_get_varaccess(const char *name)
|
||||
{
|
||||
const char *flags_list = getenv(ENV_FLAGS_VAR);
|
||||
char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
|
||||
|
||||
if (env_flags_lookup(flags_list, name, flags))
|
||||
return env_flags_varaccess_any;
|
||||
|
||||
if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
|
||||
return env_flags_varaccess_any;
|
||||
|
||||
return env_flags_parse_varaccess(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that the proposed new value for "name" is valid according to the
|
||||
* defined flags for that variable, if any.
|
||||
*/
|
||||
int env_flags_validate_type(const char *name, const char *value)
|
||||
{
|
||||
enum env_flags_vartype type;
|
||||
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
type = env_flags_get_type(name);
|
||||
if (_env_flags_validate_type(value, type) < 0) {
|
||||
printf("## Error: flags type check failure for "
|
||||
"\"%s\" <= \"%s\" (type: %c)\n",
|
||||
name, value, env_flags_vartype_rep[type]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that the proposed access to variable "name" is valid according to
|
||||
* the defined flags for that variable, if any.
|
||||
*/
|
||||
int env_flags_validate_varaccess(const char *name, int check_mask)
|
||||
{
|
||||
enum env_flags_varaccess access;
|
||||
int access_mask;
|
||||
|
||||
access = env_flags_get_varaccess(name);
|
||||
access_mask = env_flags_varaccess_mask[access];
|
||||
|
||||
return (check_mask & access_mask) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the parameters to "env set" directly
|
||||
*/
|
||||
int env_flags_validate_env_set_params(int argc, char * const argv[])
|
||||
{
|
||||
if ((argc >= 3) && argv[2] != NULL) {
|
||||
enum env_flags_vartype type = env_flags_get_type(argv[1]);
|
||||
|
||||
/*
|
||||
* we don't currently check types that need more than
|
||||
* one argument
|
||||
*/
|
||||
if (type != env_flags_vartype_string && argc > 3) {
|
||||
printf("## Error: too many parameters for setting "
|
||||
"\"%s\"\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
return env_flags_validate_type(argv[1], argv[2]);
|
||||
}
|
||||
/* ok */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !USE_HOSTCC - Functions only used from lib/hashtable.c */
|
||||
|
||||
/*
|
||||
* Parse the flag charachters from the .flags attribute list into the binary
|
||||
* form to be stored in the environment entry->flags field.
|
||||
*/
|
||||
static int env_parse_flags_to_bin(const char *flags)
|
||||
{
|
||||
int binflags;
|
||||
|
||||
binflags = env_flags_parse_vartype(flags) & ENV_FLAGS_VARTYPE_BIN_MASK;
|
||||
binflags |= env_flags_varaccess_mask[env_flags_parse_varaccess(flags)];
|
||||
|
||||
return binflags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for possible flags for a newly added variable
|
||||
* This is called specifically when the variable did not exist in the hash
|
||||
* previously, so the blanket update did not find this variable.
|
||||
*/
|
||||
void env_flags_init(ENTRY *var_entry)
|
||||
{
|
||||
const char *var_name = var_entry->key;
|
||||
const char *flags_list = getenv(ENV_FLAGS_VAR);
|
||||
char flags[ENV_FLAGS_ATTR_MAX_LEN + 1] = "";
|
||||
int ret = 1;
|
||||
|
||||
/* look in the ".flags" and static for a reference to this variable */
|
||||
ret = env_flags_lookup(flags_list, var_name, flags);
|
||||
|
||||
/* if any flags were found, set the binary form to the entry */
|
||||
if (!ret && strlen(flags))
|
||||
var_entry->flags = env_parse_flags_to_bin(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on each existing env var prior to the blanket update since removing
|
||||
* a flag in the flag list should remove its flags.
|
||||
*/
|
||||
static int clear_flags(ENTRY *entry)
|
||||
{
|
||||
entry->flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call for each element in the list that defines flags for a variable
|
||||
*/
|
||||
static int set_flags(const char *name, const char *value)
|
||||
{
|
||||
ENTRY e, *ep;
|
||||
|
||||
e.key = name;
|
||||
e.data = NULL;
|
||||
hsearch_r(e, FIND, &ep, &env_htab, 0);
|
||||
|
||||
/* does the env variable actually exist? */
|
||||
if (ep != NULL) {
|
||||
/* the flag list is empty, so clear the flags */
|
||||
if (value == NULL || strlen(value) == 0)
|
||||
ep->flags = 0;
|
||||
else
|
||||
/* assign the requested flags */
|
||||
ep->flags = env_parse_flags_to_bin(value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_flags(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
/* remove all flags */
|
||||
hwalk_r(&env_htab, clear_flags);
|
||||
|
||||
/* configure any static flags */
|
||||
env_attr_walk(ENV_FLAGS_LIST_STATIC, set_flags);
|
||||
/* configure any dynamic flags */
|
||||
env_attr_walk(value, set_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(flags, on_flags);
|
||||
|
||||
/*
|
||||
* Perform consistency checking before creating, overwriting, or deleting an
|
||||
* environment variable. Called as a callback function by hsearch_r() and
|
||||
* hdelete_r(). Returns 0 in case of success, 1 in case of failure.
|
||||
* When (flag & H_FORCE) is set, do not print out any error message and force
|
||||
* overwriting of write-once variables.
|
||||
*/
|
||||
|
||||
int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
|
||||
int flag)
|
||||
{
|
||||
const char *name;
|
||||
const char *oldval = NULL;
|
||||
|
||||
if (op != env_op_create)
|
||||
oldval = item->data;
|
||||
|
||||
name = item->key;
|
||||
|
||||
/* Default value for NULL to protect string-manipulating functions */
|
||||
newval = newval ? : "";
|
||||
|
||||
/* validate the value to match the variable type */
|
||||
if (op != env_op_delete) {
|
||||
enum env_flags_vartype type = (enum env_flags_vartype)
|
||||
(ENV_FLAGS_VARTYPE_BIN_MASK & item->flags);
|
||||
|
||||
if (_env_flags_validate_type(newval, type) < 0) {
|
||||
printf("## Error: flags type check failure for "
|
||||
"\"%s\" <= \"%s\" (type: %c)\n",
|
||||
name, newval, env_flags_vartype_rep[type]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for access permission */
|
||||
#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE
|
||||
if (flag & H_FORCE)
|
||||
return 0;
|
||||
#endif
|
||||
switch (op) {
|
||||
case env_op_delete:
|
||||
if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) {
|
||||
printf("## Error: Can't delete \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case env_op_overwrite:
|
||||
if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_OVERWR) {
|
||||
printf("## Error: Can't overwrite \"%s\"\n", name);
|
||||
return 1;
|
||||
} else if (item->flags &
|
||||
ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR) {
|
||||
const char *defval = getenv_default(name);
|
||||
|
||||
if (defval == NULL)
|
||||
defval = "";
|
||||
printf("oldval: %s defval: %s\n", oldval, defval);
|
||||
if (strcmp(oldval, defval) != 0) {
|
||||
printf("## Error: Can't overwrite \"%s\"\n",
|
||||
name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case env_op_create:
|
||||
if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_CREATE) {
|
||||
printf("## Error: Can't create \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -142,7 +142,7 @@ int saveenv(void)
|
||||
goto done;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
goto done;
|
||||
@ -275,7 +275,7 @@ int saveenv(void)
|
||||
goto done;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
goto done;
|
||||
|
@ -130,7 +130,7 @@ int saveenv(void)
|
||||
}
|
||||
|
||||
res = (char *)&env_new->data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
ret = 1;
|
||||
|
@ -186,7 +186,7 @@ int saveenv(void)
|
||||
return 1;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
@ -239,7 +239,7 @@ int saveenv(void)
|
||||
return 1;
|
||||
|
||||
res = (char *)&env_new->data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -90,7 +90,7 @@ int saveenv(void)
|
||||
int rcode = 0;
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -95,7 +95,7 @@ int saveenv(void)
|
||||
};
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
|
@ -79,7 +79,7 @@ int saveenv(void)
|
||||
}
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
return 1;
|
||||
@ -277,7 +277,7 @@ int saveenv(void)
|
||||
}
|
||||
|
||||
res = (char *)&env_new.data;
|
||||
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
|
||||
len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
|
||||
if (len < 0) {
|
||||
error("Cannot export environment: errno = %d\n", errno);
|
||||
goto done;
|
||||
|
@ -1315,7 +1315,7 @@ int fdt_set_status_by_alias(void *fdt, const char* alias,
|
||||
return fdt_set_node_status(fdt, offset, status, error_code);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_VIDEO)
|
||||
#if defined(CONFIG_VIDEO) || defined(CONFIG_LCD)
|
||||
int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
|
||||
{
|
||||
int noff;
|
||||
|
221
common/hash.c
Normal file
221
common/hash.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
*
|
||||
* (C) Copyright 2011
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <hash.h>
|
||||
#include <sha1.h>
|
||||
#include <sha256.h>
|
||||
|
||||
/*
|
||||
* These are the hash algorithms we support. Chips which support accelerated
|
||||
* crypto could perhaps add named version of these algorithms here.
|
||||
*/
|
||||
static struct hash_algo hash_algo[] = {
|
||||
#ifdef CONFIG_SHA1
|
||||
{
|
||||
"SHA1",
|
||||
SHA1_SUM_LEN,
|
||||
sha1_csum_wd,
|
||||
CHUNKSZ_SHA1,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SHA256
|
||||
{
|
||||
"SHA256",
|
||||
SHA256_SUM_LEN,
|
||||
sha256_csum_wd,
|
||||
CHUNKSZ_SHA256,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* store_result: Store the resulting sum to an address or variable
|
||||
*
|
||||
* @algo: Hash algorithm being used
|
||||
* @sum: Hash digest (algo->digest_size bytes)
|
||||
* @dest: Destination, interpreted as a hex address if it starts
|
||||
* with * or otherwise as an environment variable.
|
||||
*/
|
||||
static void store_result(struct hash_algo *algo, const u8 *sum,
|
||||
const char *dest)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (*dest == '*') {
|
||||
u8 *ptr;
|
||||
|
||||
ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
|
||||
memcpy(ptr, sum, algo->digest_size);
|
||||
} else {
|
||||
char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
|
||||
char *str_ptr = str_output;
|
||||
|
||||
for (i = 0; i < algo->digest_size; i++) {
|
||||
sprintf(str_ptr, "%02x", sum[i]);
|
||||
str_ptr += 2;
|
||||
}
|
||||
str_ptr = '\0';
|
||||
setenv(dest, str_output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_verify_sum: Parse a hash verification parameter
|
||||
*
|
||||
* @algo: Hash algorithm being used
|
||||
* @verify_str: Argument to parse. If it starts with * then it is
|
||||
* interpreted as a hex address containing the hash.
|
||||
* If the length is exactly the right number of hex digits
|
||||
* for the digest size, then we assume it is a hex digest.
|
||||
* Otherwise we assume it is an environment variable, and
|
||||
* look up its value (it must contain a hex digest).
|
||||
* @vsum: Returns binary digest value (algo->digest_size bytes)
|
||||
* @return 0 if ok, non-zero on error
|
||||
*/
|
||||
static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum)
|
||||
{
|
||||
if (*verify_str == '*') {
|
||||
u8 *ptr;
|
||||
|
||||
ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
|
||||
memcpy(vsum, ptr, algo->digest_size);
|
||||
} else {
|
||||
unsigned int i;
|
||||
char *vsum_str;
|
||||
int digits = algo->digest_size * 2;
|
||||
|
||||
/*
|
||||
* As with the original code from sha1sum.c, we assume that a
|
||||
* string which matches the digest size exactly is a hex
|
||||
* string and not an environment variable.
|
||||
*/
|
||||
if (strlen(verify_str) == digits)
|
||||
vsum_str = verify_str;
|
||||
else {
|
||||
vsum_str = getenv(verify_str);
|
||||
if (vsum_str == NULL || strlen(vsum_str) != digits) {
|
||||
printf("Expected %d hex digits in env var\n",
|
||||
digits);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < algo->digest_size; i++) {
|
||||
char *nullp = vsum_str + (i + 1) * 2;
|
||||
char end = *nullp;
|
||||
|
||||
*nullp = '\0';
|
||||
vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16);
|
||||
*nullp = end;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hash_algo *find_hash_algo(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
|
||||
if (!strcasecmp(name, hash_algo[i].name))
|
||||
return &hash_algo[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
|
||||
u8 *output)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1);
|
||||
for (i = 0; i < algo->digest_size; i++)
|
||||
printf("%02x", output[i]);
|
||||
}
|
||||
|
||||
int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct hash_algo *algo;
|
||||
ulong addr, len;
|
||||
u8 output[HASH_MAX_DIGEST_SIZE];
|
||||
u8 vsum[HASH_MAX_DIGEST_SIZE];
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
algo = find_hash_algo(algo_name);
|
||||
if (!algo) {
|
||||
printf("Unknown hash algorithm '%s'\n", algo_name);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
addr = simple_strtoul(*argv++, NULL, 16);
|
||||
len = simple_strtoul(*argv++, NULL, 16);
|
||||
argc -= 2;
|
||||
|
||||
if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
|
||||
puts("HASH_MAX_DIGEST_SIZE exceeded\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
algo->hash_func_ws((const unsigned char *)addr, len, output,
|
||||
algo->chunk_size);
|
||||
|
||||
/* Try to avoid code bloat when verify is not needed */
|
||||
#ifdef CONFIG_HASH_VERIFY
|
||||
if (verify) {
|
||||
#else
|
||||
if (0) {
|
||||
#endif
|
||||
if (!argc)
|
||||
return CMD_RET_USAGE;
|
||||
if (parse_verify_sum(algo, *argv, vsum)) {
|
||||
printf("ERROR: %s does not contain a valid %s sum\n",
|
||||
*argv, algo->name);
|
||||
return 1;
|
||||
}
|
||||
if (memcmp(output, vsum, algo->digest_size) != 0) {
|
||||
int i;
|
||||
|
||||
show_hash(algo, addr, len, output);
|
||||
printf(" != ");
|
||||
for (i = 0; i < algo->digest_size; i++)
|
||||
printf("%02x", vsum[i]);
|
||||
puts(" ** ERROR **\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
show_hash(algo, addr, len, output);
|
||||
printf("\n");
|
||||
|
||||
if (argc)
|
||||
store_result(algo, output, *argv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -43,6 +43,7 @@
|
||||
#include <rtc.h>
|
||||
#endif
|
||||
|
||||
#include <environment.h>
|
||||
#include <image.h>
|
||||
|
||||
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
|
||||
@ -416,11 +417,25 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
|
||||
/* Shared dual-format routines */
|
||||
/*****************************************************************************/
|
||||
#ifndef USE_HOSTCC
|
||||
int getenv_yesno(char *var)
|
||||
ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */
|
||||
ulong save_addr; /* Default Save Address */
|
||||
ulong save_size; /* Default Save Size (in bytes) */
|
||||
|
||||
static int on_loadaddr(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
char *s = getenv(var);
|
||||
return (s && (*s == 'n')) ? 0 : 1;
|
||||
switch (op) {
|
||||
case env_op_create:
|
||||
case env_op_overwrite:
|
||||
load_addr = simple_strtoul(value, NULL, 16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr);
|
||||
|
||||
ulong getenv_bootm_low(void)
|
||||
{
|
||||
|
@ -376,6 +376,8 @@ void main_loop (void)
|
||||
char bcs_set[16];
|
||||
#endif /* CONFIG_BOOTCOUNT_LIMIT */
|
||||
|
||||
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
|
||||
|
||||
#ifdef CONFIG_BOOTCOUNT_LIMIT
|
||||
bootcount = bootcount_load();
|
||||
bootcount++;
|
||||
|
@ -135,7 +135,6 @@ struct stdio_dev* stdio_clone(struct stdio_dev *dev)
|
||||
return NULL;
|
||||
|
||||
memcpy(_dev, dev, sizeof(struct stdio_dev));
|
||||
strncpy(_dev->name, dev->name, 16);
|
||||
|
||||
return _dev;
|
||||
}
|
||||
|
394
disk/part_efi.c
394
disk/part_efi.c
@ -34,9 +34,11 @@
|
||||
#include <command.h>
|
||||
#include <ide.h>
|
||||
#include <malloc.h>
|
||||
#include "part_efi.h"
|
||||
#include <part_efi.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if defined(CONFIG_CMD_IDE) || \
|
||||
defined(CONFIG_CMD_SATA) || \
|
||||
defined(CONFIG_CMD_SCSI) || \
|
||||
@ -44,34 +46,6 @@
|
||||
defined(CONFIG_MMC) || \
|
||||
defined(CONFIG_SYSTEMACE)
|
||||
|
||||
/* Convert char[2] in little endian format to the host format integer
|
||||
*/
|
||||
static inline unsigned short le16_to_int(unsigned char *le16)
|
||||
{
|
||||
return ((le16[1] << 8) + le16[0]);
|
||||
}
|
||||
|
||||
/* Convert char[4] in little endian format to the host format integer
|
||||
*/
|
||||
static inline unsigned long le32_to_int(unsigned char *le32)
|
||||
{
|
||||
return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]);
|
||||
}
|
||||
|
||||
/* Convert char[8] in little endian format to the host format integer
|
||||
*/
|
||||
static inline unsigned long long le64_to_int(unsigned char *le64)
|
||||
{
|
||||
return (((unsigned long long)le64[7] << 56) +
|
||||
((unsigned long long)le64[6] << 48) +
|
||||
((unsigned long long)le64[5] << 40) +
|
||||
((unsigned long long)le64[4] << 32) +
|
||||
((unsigned long long)le64[3] << 24) +
|
||||
((unsigned long long)le64[2] << 16) +
|
||||
((unsigned long long)le64[1] << 8) +
|
||||
(unsigned long long)le64[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_crc32() - EFI version of crc32 function
|
||||
* @buf: buffer to calculate crc32 of
|
||||
@ -79,7 +53,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)
|
||||
*
|
||||
* Description: Returns EFI-style CRC32 value for @buf
|
||||
*/
|
||||
static inline unsigned long efi_crc32(const void *buf, unsigned long len)
|
||||
static inline u32 efi_crc32(const void *buf, u32 len)
|
||||
{
|
||||
return crc32(0, buf, len);
|
||||
}
|
||||
@ -90,13 +64,10 @@ static inline unsigned long efi_crc32(const void *buf, unsigned long len)
|
||||
|
||||
static int pmbr_part_valid(struct partition *part);
|
||||
static int is_pmbr_valid(legacy_mbr * mbr);
|
||||
|
||||
static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
|
||||
gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
|
||||
|
||||
static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
|
||||
gpt_header * pgpt_head);
|
||||
|
||||
static int is_pte_valid(gpt_entry * pte);
|
||||
|
||||
static char *print_efiname(gpt_entry *pte)
|
||||
@ -142,6 +113,7 @@ static inline int is_bootable(gpt_entry *p)
|
||||
sizeof(efi_guid_t));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI_PARTITION
|
||||
/*
|
||||
* Public Functions (include/part.h)
|
||||
*/
|
||||
@ -171,14 +143,14 @@ void print_part_efi(block_dev_desc_t * dev_desc)
|
||||
printf("\tType UUID\n");
|
||||
printf("\tPartition UUID\n");
|
||||
|
||||
for (i = 0; i < le32_to_int(gpt_head->num_partition_entries); i++) {
|
||||
for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
|
||||
/* Stop at the first non valid PTE */
|
||||
if (!is_pte_valid(&gpt_pte[i]))
|
||||
break;
|
||||
|
||||
printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1),
|
||||
le64_to_int(gpt_pte[i].starting_lba),
|
||||
le64_to_int(gpt_pte[i].ending_lba),
|
||||
le64_to_cpu(gpt_pte[i].starting_lba),
|
||||
le64_to_cpu(gpt_pte[i].ending_lba),
|
||||
print_efiname(&gpt_pte[i]));
|
||||
printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw);
|
||||
uuid_string(gpt_pte[i].partition_type_guid.b, uuid);
|
||||
@ -211,7 +183,7 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (part > le32_to_int(gpt_head->num_partition_entries) ||
|
||||
if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
|
||||
!is_pte_valid(&gpt_pte[part - 1])) {
|
||||
printf("%s: *** ERROR: Invalid partition number %d ***\n",
|
||||
__func__, part);
|
||||
@ -219,9 +191,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
|
||||
}
|
||||
|
||||
/* The ulong casting limits the maximum disk size to 2 TB */
|
||||
info->start = (ulong) le64_to_int(gpt_pte[part - 1].starting_lba);
|
||||
info->start = (u64)le64_to_cpu(gpt_pte[part - 1].starting_lba);
|
||||
/* The ending LBA is inclusive, to calculate size, add 1 to it */
|
||||
info->size = ((ulong)le64_to_int(gpt_pte[part - 1].ending_lba) + 1)
|
||||
info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1)
|
||||
- info->start;
|
||||
info->blksz = GPT_BLOCK_SIZE;
|
||||
|
||||
@ -253,6 +225,281 @@ int test_part_efi(block_dev_desc_t * dev_desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_protective_mbr(): Set the EFI protective MBR
|
||||
* @param dev_desc - block device descriptor
|
||||
*
|
||||
* @return - zero on success, otherwise error
|
||||
*/
|
||||
static int set_protective_mbr(block_dev_desc_t *dev_desc)
|
||||
{
|
||||
legacy_mbr *p_mbr;
|
||||
|
||||
/* Setup the Protective MBR */
|
||||
p_mbr = calloc(1, sizeof(p_mbr));
|
||||
if (p_mbr == NULL) {
|
||||
printf("%s: calloc failed!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
/* Append signature */
|
||||
p_mbr->signature = MSDOS_MBR_SIGNATURE;
|
||||
p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
|
||||
p_mbr->partition_record[0].start_sect = 1;
|
||||
p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba;
|
||||
|
||||
/* Write MBR sector to the MMC device */
|
||||
if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) {
|
||||
printf("** Can't write to device %d **\n",
|
||||
dev_desc->dev);
|
||||
free(p_mbr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(p_mbr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* string_uuid(); Convert UUID stored as string to bytes
|
||||
*
|
||||
* @param uuid - UUID represented as string
|
||||
* @param dst - GUID buffer
|
||||
*
|
||||
* @return return 0 on successful conversion
|
||||
*/
|
||||
static int string_uuid(char *uuid, u8 *dst)
|
||||
{
|
||||
efi_guid_t guid;
|
||||
u16 b, c, d;
|
||||
u64 e;
|
||||
u32 a;
|
||||
u8 *p;
|
||||
u8 i;
|
||||
|
||||
const u8 uuid_str_len = 36;
|
||||
|
||||
/* The UUID is written in text: */
|
||||
/* 1 9 14 19 24 */
|
||||
/* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */
|
||||
|
||||
debug("%s: uuid: %s\n", __func__, uuid);
|
||||
|
||||
if (strlen(uuid) != uuid_str_len)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < uuid_str_len; i++) {
|
||||
if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
|
||||
if (uuid[i] != '-')
|
||||
return -1;
|
||||
} else {
|
||||
if (!isxdigit(uuid[i]))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
a = (u32)simple_strtoul(uuid, NULL, 16);
|
||||
b = (u16)simple_strtoul(uuid + 9, NULL, 16);
|
||||
c = (u16)simple_strtoul(uuid + 14, NULL, 16);
|
||||
d = (u16)simple_strtoul(uuid + 19, NULL, 16);
|
||||
e = (u64)simple_strtoull(uuid + 24, NULL, 16);
|
||||
|
||||
p = (u8 *) &e;
|
||||
guid = EFI_GUID(a, b, c, d >> 8, d & 0xFF,
|
||||
*(p + 5), *(p + 4), *(p + 3),
|
||||
*(p + 2), *(p + 1) , *p);
|
||||
|
||||
memcpy(dst, guid.b, sizeof(efi_guid_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_gpt_table(block_dev_desc_t *dev_desc,
|
||||
gpt_header *gpt_h, gpt_entry *gpt_e)
|
||||
{
|
||||
const int pte_blk_num = (gpt_h->num_partition_entries
|
||||
* sizeof(gpt_entry)) / dev_desc->blksz;
|
||||
|
||||
u32 calc_crc32;
|
||||
u64 val;
|
||||
|
||||
debug("max lba: %x\n", (u32) dev_desc->lba);
|
||||
/* Setup the Protective MBR */
|
||||
if (set_protective_mbr(dev_desc) < 0)
|
||||
goto err;
|
||||
|
||||
/* Generate CRC for the Primary GPT Header */
|
||||
calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
|
||||
le32_to_cpu(gpt_h->num_partition_entries) *
|
||||
le32_to_cpu(gpt_h->sizeof_partition_entry));
|
||||
gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
|
||||
|
||||
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
|
||||
le32_to_cpu(gpt_h->header_size));
|
||||
gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
|
||||
|
||||
/* Write the First GPT to the block right after the Legacy MBR */
|
||||
if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1)
|
||||
goto err;
|
||||
|
||||
if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num, gpt_e)
|
||||
!= pte_blk_num)
|
||||
goto err;
|
||||
|
||||
/* recalculate the values for the Second GPT Header */
|
||||
val = le64_to_cpu(gpt_h->my_lba);
|
||||
gpt_h->my_lba = gpt_h->alternate_lba;
|
||||
gpt_h->alternate_lba = cpu_to_le64(val);
|
||||
gpt_h->header_crc32 = 0;
|
||||
|
||||
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
|
||||
le32_to_cpu(gpt_h->header_size));
|
||||
gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
|
||||
|
||||
if (dev_desc->block_write(dev_desc->dev,
|
||||
le32_to_cpu(gpt_h->last_usable_lba + 1),
|
||||
pte_blk_num, gpt_e) != pte_blk_num)
|
||||
goto err;
|
||||
|
||||
if (dev_desc->block_write(dev_desc->dev,
|
||||
le32_to_cpu(gpt_h->my_lba), 1, gpt_h) != 1)
|
||||
goto err;
|
||||
|
||||
debug("GPT successfully written to block device!\n");
|
||||
return 0;
|
||||
|
||||
err:
|
||||
printf("** Can't write to device %d **\n", dev_desc->dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
|
||||
disk_partition_t *partitions, int parts)
|
||||
{
|
||||
u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba);
|
||||
ulong start;
|
||||
int i, k;
|
||||
size_t name_len;
|
||||
#ifdef CONFIG_PARTITION_UUIDS
|
||||
char *str_uuid;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < parts; i++) {
|
||||
/* partition starting lba */
|
||||
start = partitions[i].start;
|
||||
if (start && (start < offset)) {
|
||||
printf("Partition overlap\n");
|
||||
return -1;
|
||||
}
|
||||
if (start) {
|
||||
gpt_e[i].starting_lba = cpu_to_le64(start);
|
||||
offset = start + partitions[i].size;
|
||||
} else {
|
||||
gpt_e[i].starting_lba = cpu_to_le64(offset);
|
||||
offset += partitions[i].size;
|
||||
}
|
||||
if (offset >= gpt_h->last_usable_lba) {
|
||||
printf("Partitions layout exceds disk size\n");
|
||||
return -1;
|
||||
}
|
||||
/* partition ending lba */
|
||||
if ((i == parts - 1) && (partitions[i].size == 0))
|
||||
/* extend the last partition to maximuim */
|
||||
gpt_e[i].ending_lba = gpt_h->last_usable_lba;
|
||||
else
|
||||
gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
|
||||
|
||||
/* partition type GUID */
|
||||
memcpy(gpt_e[i].partition_type_guid.b,
|
||||
&PARTITION_BASIC_DATA_GUID, 16);
|
||||
|
||||
#ifdef CONFIG_PARTITION_UUIDS
|
||||
str_uuid = partitions[i].uuid;
|
||||
if (string_uuid(str_uuid, gpt_e[i].unique_partition_guid.b)) {
|
||||
printf("Partition no. %d: invalid guid: %s\n",
|
||||
i, str_uuid);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* partition attributes */
|
||||
memset(&gpt_e[i].attributes, 0,
|
||||
sizeof(gpt_entry_attributes));
|
||||
|
||||
/* partition name */
|
||||
name_len = sizeof(gpt_e[i].partition_name)
|
||||
/ sizeof(efi_char16_t);
|
||||
for (k = 0; k < name_len; k++)
|
||||
gpt_e[i].partition_name[k] =
|
||||
(efi_char16_t)(partitions[i].name[k]);
|
||||
|
||||
debug("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n",
|
||||
__func__, partitions[i].name, i,
|
||||
offset, i, partitions[i].size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
|
||||
char *str_guid, int parts_count)
|
||||
{
|
||||
gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
|
||||
gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
|
||||
gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
|
||||
gpt_h->my_lba = cpu_to_le64(1);
|
||||
gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
|
||||
gpt_h->first_usable_lba = cpu_to_le64(34);
|
||||
gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
|
||||
gpt_h->partition_entry_lba = cpu_to_le64(2);
|
||||
gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
|
||||
gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
|
||||
gpt_h->header_crc32 = 0;
|
||||
gpt_h->partition_entry_array_crc32 = 0;
|
||||
|
||||
if (string_uuid(str_guid, gpt_h->disk_guid.b))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
|
||||
disk_partition_t *partitions, int parts_count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
gpt_header *gpt_h = calloc(1, sizeof(gpt_header));
|
||||
if (gpt_h == NULL) {
|
||||
printf("%s: calloc failed!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpt_entry *gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry));
|
||||
if (gpt_e == NULL) {
|
||||
printf("%s: calloc failed!\n", __func__);
|
||||
free(gpt_h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate Primary GPT header (LBA1) */
|
||||
ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Generate partition entries */
|
||||
ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Write GPT partition table */
|
||||
ret = write_gpt_table(dev_desc, gpt_h, gpt_e);
|
||||
|
||||
err:
|
||||
free(gpt_e);
|
||||
free(gpt_h);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private functions
|
||||
*/
|
||||
@ -264,7 +511,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)
|
||||
static int pmbr_part_valid(struct partition *part)
|
||||
{
|
||||
if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
|
||||
le32_to_int(part->start_sect) == 1UL) {
|
||||
le32_to_cpu(part->start_sect) == 1UL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -283,9 +530,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!mbr || le16_to_int(mbr->signature) != MSDOS_MBR_SIGNATURE) {
|
||||
if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (pmbr_part_valid(&mbr->partition_record[i])) {
|
||||
@ -308,8 +554,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)
|
||||
static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
|
||||
gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
|
||||
{
|
||||
unsigned char crc32_backup[4] = { 0 };
|
||||
unsigned long calc_crc32;
|
||||
u32 crc32_backup = 0;
|
||||
u32 calc_crc32;
|
||||
unsigned long long lastlba;
|
||||
|
||||
if (!dev_desc || !pgpt_head) {
|
||||
@ -324,54 +570,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
|
||||
}
|
||||
|
||||
/* Check the GPT header signature */
|
||||
if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
|
||||
if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
|
||||
printf("GUID Partition Table Header signature is wrong:"
|
||||
"0x%llX != 0x%llX\n",
|
||||
(unsigned long long)le64_to_int(pgpt_head->signature),
|
||||
(unsigned long long)GPT_HEADER_SIGNATURE);
|
||||
le64_to_cpu(pgpt_head->signature),
|
||||
GPT_HEADER_SIGNATURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the GUID Partition Table CRC */
|
||||
memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup));
|
||||
memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
|
||||
memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup));
|
||||
memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
|
||||
|
||||
calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
|
||||
le32_to_int(pgpt_head->header_size));
|
||||
le32_to_cpu(pgpt_head->header_size));
|
||||
|
||||
memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup));
|
||||
memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup));
|
||||
|
||||
if (calc_crc32 != le32_to_int(crc32_backup)) {
|
||||
if (calc_crc32 != le32_to_cpu(crc32_backup)) {
|
||||
printf("GUID Partition Table Header CRC is wrong:"
|
||||
"0x%08lX != 0x%08lX\n",
|
||||
le32_to_int(crc32_backup), calc_crc32);
|
||||
"0x%x != 0x%x\n",
|
||||
le32_to_cpu(crc32_backup), calc_crc32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that the my_lba entry points to the LBA that contains the GPT */
|
||||
if (le64_to_int(pgpt_head->my_lba) != lba) {
|
||||
if (le64_to_cpu(pgpt_head->my_lba) != lba) {
|
||||
printf("GPT: my_lba incorrect: %llX != %llX\n",
|
||||
(unsigned long long)le64_to_int(pgpt_head->my_lba),
|
||||
(unsigned long long)lba);
|
||||
le64_to_cpu(pgpt_head->my_lba),
|
||||
lba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the first_usable_lba and last_usable_lba are within the disk. */
|
||||
lastlba = (unsigned long long)dev_desc->lba;
|
||||
if (le64_to_int(pgpt_head->first_usable_lba) > lastlba) {
|
||||
if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) {
|
||||
printf("GPT: first_usable_lba incorrect: %llX > %llX\n",
|
||||
le64_to_int(pgpt_head->first_usable_lba), lastlba);
|
||||
le64_to_cpu(pgpt_head->first_usable_lba), lastlba);
|
||||
return 0;
|
||||
}
|
||||
if (le64_to_int(pgpt_head->last_usable_lba) > lastlba) {
|
||||
if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) {
|
||||
printf("GPT: last_usable_lba incorrect: %llX > %llX\n",
|
||||
le64_to_int(pgpt_head->last_usable_lba), lastlba);
|
||||
(u64) le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n",
|
||||
le64_to_int(pgpt_head->first_usable_lba),
|
||||
le64_to_int(pgpt_head->last_usable_lba), lastlba);
|
||||
le64_to_cpu(pgpt_head->first_usable_lba),
|
||||
le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
|
||||
|
||||
/* Read and allocate Partition Table Entries */
|
||||
*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
|
||||
@ -382,13 +628,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
|
||||
|
||||
/* Check the GUID Partition Table Entry Array CRC */
|
||||
calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
|
||||
le32_to_int(pgpt_head->num_partition_entries) *
|
||||
le32_to_int(pgpt_head->sizeof_partition_entry));
|
||||
le32_to_cpu(pgpt_head->num_partition_entries) *
|
||||
le32_to_cpu(pgpt_head->sizeof_partition_entry));
|
||||
|
||||
if (calc_crc32 != le32_to_int(pgpt_head->partition_entry_array_crc32)) {
|
||||
if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) {
|
||||
printf("GUID Partition Table Entry Array CRC is wrong:"
|
||||
"0x%08lX != 0x%08lX\n",
|
||||
le32_to_int(pgpt_head->partition_entry_array_crc32),
|
||||
"0x%x != 0x%x\n",
|
||||
le32_to_cpu(pgpt_head->partition_entry_array_crc32),
|
||||
calc_crc32);
|
||||
|
||||
free(*pgpt_pte);
|
||||
@ -419,12 +665,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
count = le32_to_int(pgpt_head->num_partition_entries) *
|
||||
le32_to_int(pgpt_head->sizeof_partition_entry);
|
||||
count = le32_to_cpu(pgpt_head->num_partition_entries) *
|
||||
le32_to_cpu(pgpt_head->sizeof_partition_entry);
|
||||
|
||||
debug("%s: count = %lu * %lu = %zu\n", __func__,
|
||||
le32_to_int(pgpt_head->num_partition_entries),
|
||||
le32_to_int(pgpt_head->sizeof_partition_entry), count);
|
||||
debug("%s: count = %u * %u = %zu\n", __func__,
|
||||
(u32) le32_to_cpu(pgpt_head->num_partition_entries),
|
||||
(u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count);
|
||||
|
||||
/* Allocate memory for PTE, remember to FREE */
|
||||
if (count != 0) {
|
||||
@ -440,7 +686,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
|
||||
|
||||
/* Read GPT Entries from device */
|
||||
if (dev_desc->block_read (dev_desc->dev,
|
||||
(unsigned long)le64_to_int(pgpt_head->partition_entry_lba),
|
||||
le64_to_cpu(pgpt_head->partition_entry_lba),
|
||||
(lbaint_t) (count / GPT_BLOCK_SIZE), pte)
|
||||
!= (count / GPT_BLOCK_SIZE)) {
|
||||
|
||||
|
201
doc/README.gpt
Normal file
201
doc/README.gpt
Normal file
@ -0,0 +1,201 @@
|
||||
#
|
||||
# Copyright (C) 2012 Samsung Electronics
|
||||
#
|
||||
# Lukasz Majewski <l.majewski@samsung.com>
|
||||
#
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
|
||||
|
||||
Glossary:
|
||||
========
|
||||
- UUID -(Universally Unique Identifier)
|
||||
- GUID - (Globally Unique ID)
|
||||
- EFI - (Extensible Firmware Interface)
|
||||
- UEFI - (Unified EFI) - EFI evolution
|
||||
- GPT (GUID Partition Table) - it is the EFI standard part
|
||||
- partitions - lists of available partitions (defined at u-boot):
|
||||
./include/configs/{target}.h
|
||||
|
||||
Introduction:
|
||||
=============
|
||||
This document describes the GPT partition table format and usage of
|
||||
the gpt command in u-boot.
|
||||
|
||||
|
||||
UUID introduction:
|
||||
====================
|
||||
|
||||
GPT for marking disks/partitions is using the UUID. It is supposed to be a
|
||||
globally unique value. A UUID is a 16-byte (128-bit) number. The number of
|
||||
theoretically possible UUIDs is therefore about 3 x 10^38.
|
||||
More often UUID is displayed as 32 hexadecimal digits, in 5 groups,
|
||||
separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters
|
||||
(32 digits and 4 hyphens)
|
||||
|
||||
For instance, GUID of Linux data partition: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
|
||||
|
||||
Historically there are 5 methods to generate this number. The oldest one is
|
||||
combining machine's MAC address and timer (epoch) value.
|
||||
|
||||
Successive versions are using MD5 hash, random numbers and SHA-1 hash. All major
|
||||
OSes and programming languages are providing libraries to compute UUID (e.g.
|
||||
uuid command line tool).
|
||||
|
||||
GPT brief explanation:
|
||||
======================
|
||||
|
||||
Layout:
|
||||
-------
|
||||
|
||||
--------------------------------------------------
|
||||
LBA 0 |Protective MBR |
|
||||
----------------------------------------------------------
|
||||
LBA 1 |Primary GPT Header | Primary
|
||||
-------------------------------------------------- GPT
|
||||
LBA 2 |Entry 1|Entry 2| Entry 3| Entry 4|
|
||||
--------------------------------------------------
|
||||
LBA 3 |Entries 5 - 128 |
|
||||
| |
|
||||
| |
|
||||
----------------------------------------------------------
|
||||
LBA 34 |Partition 1 |
|
||||
| |
|
||||
-----------------------------------
|
||||
|Partition 2 |
|
||||
| |
|
||||
-----------------------------------
|
||||
|Partition n |
|
||||
| |
|
||||
----------------------------------------------------------
|
||||
LBA -34 |Entry 1|Entry 2| Entry 3| Entry 4| Secondary
|
||||
-------------------------------------------------- (bkp)
|
||||
LBA -33 |Entries 5 - 128 | GPT
|
||||
| |
|
||||
| |
|
||||
LBA -2 | |
|
||||
--------------------------------------------------
|
||||
LBA -1 |Secondary GPT Header |
|
||||
----------------------------------------------------------
|
||||
|
||||
|
||||
For a legacy reasons, GPT's LBA 0 sector has a MBR structure. It is called
|
||||
"protective MBR".
|
||||
Its first partition entry ID has 0xEE value, and disk software, which is not
|
||||
handling the GPT sees it as a storage device without free space.
|
||||
|
||||
It is possible to define 128 linearly placed partition entries.
|
||||
|
||||
"LBA -1" means the last addressable block (in the mmc subsystem:
|
||||
"dev_desc->lba - 1")
|
||||
|
||||
Primary/Secondary GPT header:
|
||||
----------------------------
|
||||
Offset Size Description
|
||||
|
||||
0 8 B Signature ("EFI PART", 45 46 49 20 50 41 52 54)
|
||||
8 4 B Revision (For version 1.0, the value is 00 00 01 00)
|
||||
12 4 B Header size (in bytes, usually 5C 00 00 00 meaning 92 bytes)
|
||||
16 4 B CRC32 of header (0 to header size), with this field zeroed
|
||||
during calculation
|
||||
20 4 B Reserved (ZERO);
|
||||
24 8 B Current LBA (location of this header copy)
|
||||
32 8 B Backup LBA (location of the other header copy)
|
||||
40 8 B First usable LBA for partitions (primary partition table last
|
||||
LBA + 1)
|
||||
48 8 B Last usable LBA (secondary partition table first LBA - 1)
|
||||
56 16 B Disk GUID (also referred as UUID on UNIXes)
|
||||
72 8 B Partition entries starting LBA (always 2 in primary copy)
|
||||
80 4 B Number of partition entries
|
||||
84 4 B Size of a partition entry (usually 128)
|
||||
88 4 B CRC32 of partition array
|
||||
92 * Reserved; must be ZERO (420 bytes for a 512-byte LBA)
|
||||
|
||||
TOTAL: 512 B
|
||||
|
||||
|
||||
|
||||
IMPORTANT:
|
||||
|
||||
GPT headers and partition entries are protected by CRC32 (the POSIX CRC32).
|
||||
|
||||
Primary GPT header and Secondary GPT header have swapped values of "Current LBA"
|
||||
and "Backup LBA" and therefore different CRC32 check-sum.
|
||||
|
||||
CRC32 for GPT headers (field "CRC of header") are calculated up till
|
||||
"Header size" (92), NOT 512 bytes.
|
||||
|
||||
CRC32 for partition entries (field "CRC32 of partition array") is calculated for
|
||||
the whole array entry ( Number_of_partition_entries *
|
||||
sizeof(partition_entry_size (usually 128)))
|
||||
|
||||
Observe, how Secondary GPT is placed in the memory. It is NOT a mirror reflect
|
||||
of the Primary.
|
||||
|
||||
|
||||
Partition Entry Format:
|
||||
----------------------
|
||||
Offset Size Description
|
||||
|
||||
0 16 B Partition type GUID
|
||||
16 16 B Unique partition GUID
|
||||
32 8 B First LBA (Little Endian)
|
||||
40 8 B Last LBA (inclusive)
|
||||
48 8 B Attribute flags [+]
|
||||
56 72 B Partition name (text)
|
||||
|
||||
Attribute flags:
|
||||
Bit 0 - System partition
|
||||
Bit 60 - Read-only
|
||||
Bit 62 - Hidden
|
||||
Bit 63 - Not mount
|
||||
|
||||
|
||||
Creating GPT partitions in U-Boot:
|
||||
==============
|
||||
|
||||
To restore GUID partition table one needs to:
|
||||
1. Define partition layout in the environment.
|
||||
Format of partitions layout:
|
||||
"partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
|
||||
name=kernel,size=60MiB,uuid=...;"
|
||||
or
|
||||
"partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name},
|
||||
size=${uboot_size},uuid=${uboot_uuid};"
|
||||
|
||||
Fields 'name', 'size' and 'uuid' are mandatory for every partition.
|
||||
The field 'start' is optional.
|
||||
|
||||
2. Define 'CONFIG_EFI_PARTITION' and 'CONFIG_CMD_GPT'
|
||||
|
||||
2. From u-boot prompt type:
|
||||
gpt write mmc 0 $partitions
|
||||
|
||||
|
||||
Useful info:
|
||||
============
|
||||
|
||||
Two programs, namely: 'fdisk' and 'parted' are recommended to work with GPT
|
||||
recovery. Parted is able to handle GUID partitions. Unfortunately the 'fdisk'
|
||||
hasn't got such ability.
|
||||
Please, pay attention at -l switch for parted.
|
||||
|
||||
"uuid" program is recommended to generate UUID string. Moreover it can decode
|
||||
(-d switch) passed in UUID string. It can be used to generate partitions UUID
|
||||
passed to u-boot environment variables.
|
@ -1,9 +1,15 @@
|
||||
The config option CONFIG_SILENT_CONSOLE can be used to quiet messages
|
||||
on the console. If the option has been enabled, the output can be
|
||||
silenced by setting the environment variable "silent". The variable
|
||||
is latched into the global data at an early stage in the boot process
|
||||
so deleting it with "setenv" will not take effect until the system is
|
||||
restarted.
|
||||
silenced by setting the environment variable "silent".
|
||||
|
||||
- CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
|
||||
When the "silent" variable is changed with env set, the change
|
||||
will take effect immediately.
|
||||
|
||||
- CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC
|
||||
Some environments are not available until relocation (e.g. NAND)
|
||||
so this will make the value in the flash env take effect at
|
||||
relocation.
|
||||
|
||||
The following actions are taken if "silent" is set at boot time:
|
||||
|
||||
|
@ -26,7 +26,12 @@
|
||||
#include <asm/arch/hardware.h>
|
||||
#include "designware_i2c.h"
|
||||
|
||||
static struct i2c_regs *const i2c_regs_p =
|
||||
#ifdef CONFIG_I2C_MULTI_BUS
|
||||
static unsigned int bus_initialized[CONFIG_SYS_I2C_BUS_MAX];
|
||||
static unsigned int current_bus = 0;
|
||||
#endif
|
||||
|
||||
static struct i2c_regs *i2c_regs_p =
|
||||
(struct i2c_regs *)CONFIG_SYS_I2C_BASE;
|
||||
|
||||
/*
|
||||
@ -39,7 +44,6 @@ static void set_speed(int i2c_spd)
|
||||
{
|
||||
unsigned int cntl;
|
||||
unsigned int hcnt, lcnt;
|
||||
unsigned int high, low;
|
||||
unsigned int enbl;
|
||||
|
||||
/* to set speed cltr must be disabled */
|
||||
@ -47,39 +51,38 @@ static void set_speed(int i2c_spd)
|
||||
enbl &= ~IC_ENABLE_0B;
|
||||
writel(enbl, &i2c_regs_p->ic_enable);
|
||||
|
||||
|
||||
cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK));
|
||||
|
||||
switch (i2c_spd) {
|
||||
case IC_SPEED_MODE_MAX:
|
||||
cntl |= IC_CON_SPD_HS;
|
||||
high = MIN_HS_SCL_HIGHTIME;
|
||||
low = MIN_HS_SCL_LOWTIME;
|
||||
hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
|
||||
writel(hcnt, &i2c_regs_p->ic_hs_scl_hcnt);
|
||||
lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
|
||||
writel(lcnt, &i2c_regs_p->ic_hs_scl_lcnt);
|
||||
break;
|
||||
|
||||
case IC_SPEED_MODE_STANDARD:
|
||||
cntl |= IC_CON_SPD_SS;
|
||||
high = MIN_SS_SCL_HIGHTIME;
|
||||
low = MIN_SS_SCL_LOWTIME;
|
||||
hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
|
||||
writel(hcnt, &i2c_regs_p->ic_ss_scl_hcnt);
|
||||
lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
|
||||
writel(lcnt, &i2c_regs_p->ic_ss_scl_lcnt);
|
||||
break;
|
||||
|
||||
case IC_SPEED_MODE_FAST:
|
||||
default:
|
||||
cntl |= IC_CON_SPD_FS;
|
||||
high = MIN_FS_SCL_HIGHTIME;
|
||||
low = MIN_FS_SCL_LOWTIME;
|
||||
hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
|
||||
writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
|
||||
lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
|
||||
writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(cntl, &i2c_regs_p->ic_con);
|
||||
|
||||
hcnt = (IC_CLK * high) / NANO_TO_MICRO;
|
||||
writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
|
||||
|
||||
lcnt = (IC_CLK * low) / NANO_TO_MICRO;
|
||||
writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
|
||||
|
||||
/* re-enable i2c ctrl back now that speed is set */
|
||||
/* Enable back i2c now speed set */
|
||||
enbl |= IC_ENABLE_0B;
|
||||
writel(enbl, &i2c_regs_p->ic_enable);
|
||||
}
|
||||
@ -150,6 +153,10 @@ void i2c_init(int speed, int slaveadd)
|
||||
enbl = readl(&i2c_regs_p->ic_enable);
|
||||
enbl |= IC_ENABLE_0B;
|
||||
writel(enbl, &i2c_regs_p->ic_enable);
|
||||
|
||||
#ifdef CONFIG_I2C_MULTI_BUS
|
||||
bus_initialized[current_bus] = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -274,7 +281,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||
|
||||
start_time_rx = get_timer(0);
|
||||
while (len) {
|
||||
writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
|
||||
if (len == 1)
|
||||
writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data);
|
||||
else
|
||||
writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
|
||||
|
||||
if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
|
||||
*buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
|
||||
@ -313,9 +323,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||
start_time_tx = get_timer(0);
|
||||
while (len) {
|
||||
if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
|
||||
writel(*buffer, &i2c_regs_p->ic_cmd_data);
|
||||
if (--len == 0)
|
||||
writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data);
|
||||
else
|
||||
writel(*buffer, &i2c_regs_p->ic_cmd_data);
|
||||
buffer++;
|
||||
len--;
|
||||
start_time_tx = get_timer(0);
|
||||
|
||||
} else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
|
||||
@ -344,3 +356,74 @@ int i2c_probe(uchar chip)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_I2C_MULTI_BUS
|
||||
int i2c_set_bus_num(unsigned int bus)
|
||||
{
|
||||
switch (bus) {
|
||||
case 0:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE;
|
||||
break;
|
||||
#ifdef CONFIG_SYS_I2C_BASE1
|
||||
case 1:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE2
|
||||
case 2:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE2;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE3
|
||||
case 3:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE3;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE4
|
||||
case 4:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE4;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE5
|
||||
case 5:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE5;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE6
|
||||
case 6:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE6;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE7
|
||||
case 7:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE7;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE8
|
||||
case 8:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE8;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_BASE9
|
||||
case 9:
|
||||
i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE9;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("Bad bus: %d\n", bus);
|
||||
return -1;
|
||||
}
|
||||
|
||||
current_bus = bus;
|
||||
|
||||
if (!bus_initialized[current_bus])
|
||||
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_get_bus_num(void)
|
||||
{
|
||||
return current_bus;
|
||||
}
|
||||
#endif
|
||||
|
@ -60,14 +60,16 @@ struct i2c_regs {
|
||||
u32 ic_tx_abrt_source;
|
||||
};
|
||||
|
||||
#if !defined(IC_CLK)
|
||||
#define IC_CLK 166
|
||||
#endif
|
||||
#define NANO_TO_MICRO 1000
|
||||
|
||||
/* High and low times in different speed modes (in ns) */
|
||||
#define MIN_SS_SCL_HIGHTIME 4000
|
||||
#define MIN_SS_SCL_LOWTIME 5000
|
||||
#define MIN_FS_SCL_HIGHTIME 800
|
||||
#define MIN_FS_SCL_LOWTIME 1700
|
||||
#define MIN_SS_SCL_LOWTIME 4700
|
||||
#define MIN_FS_SCL_HIGHTIME 600
|
||||
#define MIN_FS_SCL_LOWTIME 1300
|
||||
#define MIN_HS_SCL_HIGHTIME 60
|
||||
#define MIN_HS_SCL_LOWTIME 160
|
||||
|
||||
@ -95,6 +97,7 @@ struct i2c_regs {
|
||||
|
||||
/* i2c data buffer and command register definitions */
|
||||
#define IC_CMD 0x0100
|
||||
#define IC_STOP 0x0200
|
||||
|
||||
/* i2c interrupt status register definitions */
|
||||
#define IC_GEN_CALL 0x0800
|
||||
|
@ -115,7 +115,7 @@ static uint8_t i2c_imx_get_clk(unsigned int rate)
|
||||
/*
|
||||
* Set I2C Bus speed
|
||||
*/
|
||||
int bus_i2c_set_bus_speed(void *base, int speed)
|
||||
static int bus_i2c_set_bus_speed(void *base, int speed)
|
||||
{
|
||||
struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base;
|
||||
u8 clk_idx = i2c_imx_get_clk(speed);
|
||||
@ -133,7 +133,7 @@ int bus_i2c_set_bus_speed(void *base, int speed)
|
||||
/*
|
||||
* Get I2C Speed
|
||||
*/
|
||||
unsigned int bus_i2c_get_bus_speed(void *base)
|
||||
static unsigned int bus_i2c_get_bus_speed(void *base)
|
||||
{
|
||||
struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base;
|
||||
u8 clk_idx = readb(&i2c_regs->ifdr);
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/clock.h>
|
||||
@ -40,6 +41,7 @@ void mxs_i2c_reset(void)
|
||||
{
|
||||
struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
|
||||
int ret;
|
||||
int speed = i2c_get_bus_speed();
|
||||
|
||||
ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
|
||||
if (ret) {
|
||||
@ -53,6 +55,8 @@ void mxs_i2c_reset(void)
|
||||
&i2c_regs->hw_i2c_ctrl1_clr);
|
||||
|
||||
writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
|
||||
|
||||
i2c_set_bus_speed(speed);
|
||||
}
|
||||
|
||||
void mxs_i2c_setup_read(uint8_t chip, int len)
|
||||
@ -210,37 +214,65 @@ int i2c_probe(uchar chip)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void i2c_init(int speed, int slaveadd)
|
||||
int i2c_set_bus_speed(unsigned int speed)
|
||||
{
|
||||
struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
|
||||
/*
|
||||
* The timing derivation algorithm. There is no documentation for this
|
||||
* algorithm available, it was derived by using the scope and fiddling
|
||||
* with constants until the result observed on the scope was good enough
|
||||
* for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
|
||||
* possible to assume the algorithm works for other frequencies as well.
|
||||
*
|
||||
* Note it was necessary to cap the frequency on both ends as it's not
|
||||
* possible to configure completely arbitrary frequency for the I2C bus
|
||||
* clock.
|
||||
*/
|
||||
uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
|
||||
uint32_t base = ((clk / speed) - 38) / 2;
|
||||
uint16_t high_count = base + 3;
|
||||
uint16_t low_count = base - 3;
|
||||
uint16_t rcv_count = (high_count * 3) / 4;
|
||||
uint16_t xmit_count = low_count / 4;
|
||||
|
||||
mxs_i2c_reset();
|
||||
|
||||
switch (speed) {
|
||||
case 100000:
|
||||
writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
|
||||
(0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
|
||||
&i2c_regs->hw_i2c_timing0);
|
||||
writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
|
||||
(0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
|
||||
&i2c_regs->hw_i2c_timing1);
|
||||
break;
|
||||
case 400000:
|
||||
writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
|
||||
(0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
|
||||
&i2c_regs->hw_i2c_timing0);
|
||||
writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
|
||||
(0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
|
||||
&i2c_regs->hw_i2c_timing1);
|
||||
break;
|
||||
default:
|
||||
printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
|
||||
return;
|
||||
if (speed > 540000) {
|
||||
printf("MXS I2C: Speed too high (%d Hz)\n", speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
|
||||
(0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
|
||||
if (speed < 12000) {
|
||||
printf("MXS I2C: Speed too low (%d Hz)\n", speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0);
|
||||
writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1);
|
||||
|
||||
writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) |
|
||||
(0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET),
|
||||
&i2c_regs->hw_i2c_timing2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int i2c_get_bus_speed(void)
|
||||
{
|
||||
struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
|
||||
uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
|
||||
uint32_t timing0;
|
||||
|
||||
timing0 = readl(&i2c_regs->hw_i2c_timing0);
|
||||
/*
|
||||
* This is a reverse version of the algorithm presented in
|
||||
* i2c_set_bus_speed(). Please refer there for details.
|
||||
*/
|
||||
return clk / ((((timing0 >> 16) - 3) * 2) + 38);
|
||||
}
|
||||
|
||||
void i2c_init(int speed, int slaveadd)
|
||||
{
|
||||
mxs_i2c_reset();
|
||||
i2c_set_bus_speed(speed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -179,7 +179,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)
|
||||
if (status & I2C_STAT_XRDY) {
|
||||
w = tmpbuf[i++];
|
||||
#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX))
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_OMAP54XX))
|
||||
w |= tmpbuf[i++] << 8;
|
||||
#endif
|
||||
writew(w, &i2c_base->data);
|
||||
@ -209,7 +210,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)
|
||||
}
|
||||
if (status & I2C_STAT_RRDY) {
|
||||
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_OMAP54XX)
|
||||
*value = readb(&i2c_base->data);
|
||||
#else
|
||||
*value = readw(&i2c_base->data);
|
||||
@ -239,7 +241,8 @@ static void flush_fifo(void)
|
||||
stat = readw(&i2c_base->stat);
|
||||
if (stat == I2C_STAT_RRDY) {
|
||||
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_OMAP54XX)
|
||||
readb(&i2c_base->data);
|
||||
#else
|
||||
readw(&i2c_base->data);
|
||||
@ -289,7 +292,8 @@ int i2c_probe(uchar chip)
|
||||
if (status & I2C_STAT_RRDY) {
|
||||
res = 0;
|
||||
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_OMAP54XX)
|
||||
readb(&i2c_base->data);
|
||||
#else
|
||||
readw(&i2c_base->data);
|
||||
@ -376,7 +380,8 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||
if (status & I2C_STAT_XRDY) {
|
||||
w = (i < 0) ? tmpbuf[2+i] : buffer[i];
|
||||
#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX))
|
||||
defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_OMAP54XX))
|
||||
w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8;
|
||||
#endif
|
||||
writew(w, &i2c_base->data);
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#ifdef CONFIG_EXYNOS5
|
||||
#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#else
|
||||
@ -62,7 +62,7 @@
|
||||
|
||||
static unsigned int g_current_bus; /* Stores Current I2C Bus */
|
||||
|
||||
#ifndef CONFIG_EXYNOS5
|
||||
#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
|
||||
static int GetI2CSDA(void)
|
||||
{
|
||||
struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
|
||||
@ -121,7 +121,12 @@ static void ReadWriteByte(struct s3c24x0_i2c *i2c)
|
||||
|
||||
static struct s3c24x0_i2c *get_base_i2c(void)
|
||||
{
|
||||
#ifdef CONFIG_EXYNOS5
|
||||
#ifdef CONFIG_EXYNOS4
|
||||
struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
|
||||
+ (EXYNOS4_I2C_SPACING
|
||||
* g_current_bus));
|
||||
return i2c;
|
||||
#elif defined CONFIG_EXYNOS5
|
||||
struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
|
||||
+ (EXYNOS5_I2C_SPACING
|
||||
* g_current_bus));
|
||||
@ -134,7 +139,7 @@ static struct s3c24x0_i2c *get_base_i2c(void)
|
||||
static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
|
||||
{
|
||||
ulong freq, pres = 16, div;
|
||||
#ifdef CONFIG_EXYNOS5
|
||||
#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
|
||||
freq = get_i2c_clk();
|
||||
#else
|
||||
freq = get_PCLK();
|
||||
@ -188,7 +193,7 @@ unsigned int i2c_get_bus_num(void)
|
||||
void i2c_init(int speed, int slaveadd)
|
||||
{
|
||||
struct s3c24x0_i2c *i2c;
|
||||
#ifndef CONFIG_EXYNOS5
|
||||
#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
|
||||
struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
|
||||
#endif
|
||||
int i;
|
||||
@ -204,7 +209,7 @@ void i2c_init(int speed, int slaveadd)
|
||||
i--;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_EXYNOS5
|
||||
#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
|
||||
if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
|
||||
#ifdef CONFIG_S3C2410
|
||||
ulong old_gpecon = readl(&gpio->gpecon);
|
||||
@ -248,7 +253,7 @@ void i2c_init(int speed, int slaveadd)
|
||||
writel(old_gpecon, &gpio->pgcon);
|
||||
#endif
|
||||
}
|
||||
#endif /* #ifndef CONFIG_EXYNOS5 */
|
||||
#endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
|
||||
i2c_ch_init(i2c, speed, slaveadd);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include <ioports.h>
|
||||
#include <asm/io.h>
|
||||
#endif
|
||||
#if defined(CONFIG_AVR32)
|
||||
#include <asm/arch/portmux.h>
|
||||
#endif
|
||||
#if defined(CONFIG_AT91FAMILY)
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <environment.h>
|
||||
#include <serial.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <post.h>
|
||||
@ -32,6 +33,11 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static struct serial_device *serial_devices;
|
||||
static struct serial_device *serial_current;
|
||||
/*
|
||||
* Table with supported baudrates (defined in config_xyz.h)
|
||||
*/
|
||||
static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
|
||||
#define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
|
||||
|
||||
/**
|
||||
* serial_null() - Void registration routine of a serial driver
|
||||
@ -45,6 +51,70 @@ static void serial_null(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* on_baudrate() - Update the actual baudrate when the env var changes
|
||||
*
|
||||
* This will check for a valid baudrate and only apply it if valid.
|
||||
*/
|
||||
static int on_baudrate(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
int i;
|
||||
int baudrate;
|
||||
|
||||
switch (op) {
|
||||
case env_op_create:
|
||||
case env_op_overwrite:
|
||||
/*
|
||||
* Switch to new baudrate if new baudrate is supported
|
||||
*/
|
||||
baudrate = simple_strtoul(value, NULL, 10);
|
||||
|
||||
/* Not actually changing */
|
||||
if (gd->baudrate == baudrate)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < N_BAUDRATES; ++i) {
|
||||
if (baudrate == baudrate_table[i])
|
||||
break;
|
||||
}
|
||||
if (i == N_BAUDRATES) {
|
||||
if ((flags & H_FORCE) == 0)
|
||||
printf("## Baudrate %d bps not supported\n",
|
||||
baudrate);
|
||||
return 1;
|
||||
}
|
||||
if ((flags & H_INTERACTIVE) != 0) {
|
||||
printf("## Switch baudrate to %d"
|
||||
" bps and press ENTER ...\n", baudrate);
|
||||
udelay(50000);
|
||||
}
|
||||
|
||||
gd->baudrate = baudrate;
|
||||
#if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
|
||||
gd->bd->bi_baudrate = baudrate;
|
||||
#endif
|
||||
|
||||
serial_setbrg();
|
||||
|
||||
udelay(50000);
|
||||
|
||||
if ((flags & H_INTERACTIVE) != 0)
|
||||
while (1) {
|
||||
if (getc() == '\r')
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
case env_op_delete:
|
||||
printf("## Baudrate may not be deleted\n");
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
|
||||
|
||||
/**
|
||||
* serial_initfunc() - Forward declare of driver registration routine
|
||||
* @name: Name of the real driver registration routine.
|
||||
|
@ -42,10 +42,11 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Request ownership of a GPIO.
|
||||
* Request a gpio. This should be called before any of the other functions
|
||||
* are used on this gpio.
|
||||
*
|
||||
* @param gpio GPIO number
|
||||
* @param label Name given to the GPIO
|
||||
* @param gp GPIO number
|
||||
* @param label User label for this GPIO
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
int gpio_request(unsigned gpio, const char *label);
|
||||
@ -93,14 +94,4 @@ int gpio_get_value(unsigned gpio);
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
int gpio_set_value(unsigned gpio, int value);
|
||||
|
||||
/**
|
||||
* Request a gpio. This should be called before any of the other functions
|
||||
* are used on this gpio.
|
||||
*
|
||||
* @param gp GPIO number
|
||||
* @param label User label for this GPIO
|
||||
* @return 0 if ok, -1 on error
|
||||
*/
|
||||
int gpio_request(unsigned gpio, const char *label);
|
||||
#endif /* _ASM_GENERIC_GPIO_H_ */
|
||||
|
@ -89,10 +89,10 @@ extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_CMD_MEMORY) \
|
||||
|| defined(CONFIG_CMD_I2C) \
|
||||
|| defined(CONFIG_CMD_ITEST) \
|
||||
|| defined(CONFIG_CMD_PCI) \
|
||||
|| defined(CONFIG_CMD_PORTIO)
|
||||
|| defined(CONFIG_CMD_I2C) \
|
||||
|| defined(CONFIG_CMD_ITEST) \
|
||||
|| defined(CONFIG_CMD_PCI) \
|
||||
|| defined(CONFIG_CMD_PORTIO)
|
||||
#define CMD_DATA_SIZE
|
||||
extern int cmd_get_data_size(char* arg, int default_size);
|
||||
#endif
|
||||
|
@ -340,6 +340,11 @@ int envmatch (uchar *, int);
|
||||
char *getenv (const char *);
|
||||
int getenv_f (const char *name, char *buf, unsigned len);
|
||||
ulong getenv_ulong(const char *name, int base, ulong default_val);
|
||||
/*
|
||||
* Read an environment variable as a boolean
|
||||
* Return -1 if variable does not exist (default to true)
|
||||
*/
|
||||
int getenv_yesno(const char *var);
|
||||
int saveenv (void);
|
||||
int setenv (const char *, const char *);
|
||||
int setenv_ulong(const char *varname, ulong value);
|
||||
|
@ -40,12 +40,15 @@
|
||||
#define CONFIG_CMD_FDOS /* Floppy DOS support */
|
||||
#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
|
||||
#define CONFIG_CMD_FPGA /* FPGA configuration Support */
|
||||
#define CONFIG_CMD_GETTIME /* Get time since boot */
|
||||
#define CONFIG_CMD_HASH /* calculate hash / digest */
|
||||
#define CONFIG_CMD_HWFLOW /* RTS/CTS hw flow control */
|
||||
#define CONFIG_CMD_I2C /* I2C serial bus support */
|
||||
#define CONFIG_CMD_IDE /* IDE harddisk support */
|
||||
#define CONFIG_CMD_IMI /* iminfo */
|
||||
#define CONFIG_CMD_IMLS /* List all found images */
|
||||
#define CONFIG_CMD_IMMAP /* IMMR dump support */
|
||||
#define CONFIG_CMD_IO /* Access to X86 IO space */
|
||||
#define CONFIG_CMD_IRQ /* irqinfo */
|
||||
#define CONFIG_CMD_ITEST /* Integer (and string) test */
|
||||
#define CONFIG_CMD_JFFS2 /* JFFS2 Support */
|
||||
@ -70,6 +73,7 @@
|
||||
#define CONFIG_CMD_REGINFO /* Register dump */
|
||||
#define CONFIG_CMD_REISER /* Reiserfs support */
|
||||
#define CONFIG_CMD_RARP /* rarpboot support */
|
||||
#define CONFIG_CMD_READ /* Read data from partition */
|
||||
#define CONFIG_CMD_RUN /* run command in env variable */
|
||||
#define CONFIG_CMD_SAVEENV /* saveenv */
|
||||
#define CONFIG_CMD_SAVES /* save S record dump */
|
||||
|
@ -95,10 +95,7 @@
|
||||
#define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME "u-boot.img"
|
||||
|
||||
/* Partition tables */
|
||||
/* Only need DOS partition support for SPL, currently */
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
#define CONFIG_EFI_PARTITION
|
||||
#endif
|
||||
#define CONFIG_DOS_PARTITION
|
||||
|
||||
/* USB
|
||||
|
@ -203,6 +203,7 @@
|
||||
#define CONFIG_I2C_MULTI_BUS
|
||||
#define CONFIG_MAX_I2C_NUM 8
|
||||
#define CONFIG_SYS_I2C_SLAVE 0x0
|
||||
#define CONFIG_I2C_EDID
|
||||
|
||||
/* Ethernet Controllor Driver */
|
||||
#ifdef CONFIG_CMD_NET
|
||||
@ -215,4 +216,10 @@
|
||||
/* Enable devicetree support */
|
||||
#define CONFIG_OF_LIBFDT
|
||||
|
||||
/* SHA hashing */
|
||||
#define CONFIG_CMD_HASH
|
||||
#define CONFIG_HASH_VERIFY
|
||||
#define CONFIG_SHA1
|
||||
#define CONFIG_SHA256
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
@ -98,6 +98,7 @@
|
||||
#undef CONFIG_CMD_MTDPARTS
|
||||
#define CONFIG_CMD_MMC
|
||||
#define CONFIG_CMD_DFU
|
||||
#define CONFIG_CMD_GPT
|
||||
|
||||
/* FAT */
|
||||
#define CONFIG_CMD_FAT
|
||||
@ -122,6 +123,26 @@
|
||||
#define CONFIG_BOOTBLOCK "10"
|
||||
#define CONFIG_ENV_COMMON_BOOT "${console} ${meminfo}"
|
||||
|
||||
/* Tizen - partitions definitions */
|
||||
#define PARTS_CSA "csa-mmc"
|
||||
#define PARTS_BOOTLOADER "u-boot"
|
||||
#define PARTS_BOOT "boot"
|
||||
#define PARTS_ROOT "platform"
|
||||
#define PARTS_DATA "data"
|
||||
#define PARTS_CSC "csc"
|
||||
#define PARTS_UMS "ums"
|
||||
|
||||
#define PARTS_DEFAULT \
|
||||
"uuid_disk=${uuid_gpt_disk};" \
|
||||
"name="PARTS_CSA",size=8MiB,uuid=${uuid_gpt_"PARTS_CSA"};" \
|
||||
"name="PARTS_BOOTLOADER",size=60MiB," \
|
||||
"uuid=${uuid_gpt_"PARTS_BOOTLOADER"};" \
|
||||
"name="PARTS_BOOT",size=100MiB,uuid=${uuid_gpt_"PARTS_BOOT"};" \
|
||||
"name="PARTS_ROOT",size=1GiB,uuid=${uuid_gpt_"PARTS_ROOT"};" \
|
||||
"name="PARTS_DATA",size=3GiB,uuid=${uuid_gpt_"PARTS_DATA"};" \
|
||||
"name="PARTS_CSC",size=150MiB,uuid=${uuid_gpt_"PARTS_CSC"};" \
|
||||
"name="PARTS_UMS",size=-,uuid=${uuid_gpt_"PARTS_UMS"}\0" \
|
||||
|
||||
#define CONFIG_DFU_ALT \
|
||||
"dfu_alt_info=" \
|
||||
"u-boot mmc 80 400;" \
|
||||
@ -171,7 +192,8 @@
|
||||
"mmcbootpart=2\0" \
|
||||
"mmcrootpart=3\0" \
|
||||
"opts=always_resume=1\0" \
|
||||
CONFIG_DFU_ALT
|
||||
"partitions=" PARTS_DEFAULT \
|
||||
CONFIG_DFU_ALT \
|
||||
|
||||
/* Miscellaneous configurable options */
|
||||
#define CONFIG_SYS_LONGHELP /* undef to save memory */
|
||||
@ -208,6 +230,10 @@
|
||||
|
||||
#define CONFIG_DOS_PARTITION
|
||||
|
||||
/* GPT */
|
||||
#define CONFIG_EFI_PARTITION
|
||||
#define CONFIG_PARTITION_UUIDS
|
||||
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)
|
||||
#define CONFIG_SYS_CACHELINE_SIZE 32
|
||||
|
||||
|
275
include/edid.h
Normal file
275
include/edid.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
*
|
||||
* (C) Copyright 2010
|
||||
* Petr Stetiar <ynezz@true.cz>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Contains stolen code from ddcprobe project which is:
|
||||
* Copyright (C) Nalin Dahyabhai <bigfun@pobox.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __EDID_H_
|
||||
#define __EDID_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define GET_BIT(_x, _pos) \
|
||||
(((_x) >> (_pos)) & 1)
|
||||
#define GET_BITS(_x, _pos_msb, _pos_lsb) \
|
||||
(((_x) >> (_pos_lsb)) & ((1 << ((_pos_msb) - (_pos_lsb) + 1)) - 1))
|
||||
|
||||
/* Aspect ratios used in EDID info. */
|
||||
enum edid_aspect {
|
||||
ASPECT_625 = 0,
|
||||
ASPECT_75,
|
||||
ASPECT_8,
|
||||
ASPECT_5625,
|
||||
};
|
||||
|
||||
/* Detailed timing information used in EDID v1.x */
|
||||
struct edid_detailed_timing {
|
||||
unsigned char pixel_clock[2];
|
||||
#define EDID_DETAILED_TIMING_PIXEL_CLOCK(_x) \
|
||||
(((((uint32_t)(_x).pixel_clock[1]) << 8) + \
|
||||
(_x).pixel_clock[0]) * 10000)
|
||||
unsigned char horizontal_active;
|
||||
unsigned char horizontal_blanking;
|
||||
unsigned char horizontal_active_blanking_hi;
|
||||
#define EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(_x) \
|
||||
((GET_BITS((_x).horizontal_active_blanking_hi, 7, 4) << 8) + \
|
||||
(_x).horizontal_active)
|
||||
#define EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(_x) \
|
||||
((GET_BITS((_x).horizontal_active_blanking_hi, 3, 0) << 8) + \
|
||||
(_x).horizontal_blanking)
|
||||
unsigned char vertical_active;
|
||||
unsigned char vertical_blanking;
|
||||
unsigned char vertical_active_blanking_hi;
|
||||
#define EDID_DETAILED_TIMING_VERTICAL_ACTIVE(_x) \
|
||||
((GET_BITS((_x).vertical_active_blanking_hi, 7, 4) << 8) + \
|
||||
(_x).vertical_active)
|
||||
#define EDID_DETAILED_TIMING_VERTICAL_BLANKING(_x) \
|
||||
((GET_BITS((_x).vertical_active_blanking_hi, 3, 0) << 8) + \
|
||||
(_x).vertical_blanking)
|
||||
unsigned char hsync_offset;
|
||||
unsigned char hsync_pulse_width;
|
||||
unsigned char sync_offset_pulse_width;
|
||||
unsigned char hsync_vsync_offset_pulse_width_hi;
|
||||
#define EDID_DETAILED_TIMING_HSYNC_OFFSET(_x) \
|
||||
((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 7, 6) << 8) + \
|
||||
(_x).hsync_offset)
|
||||
#define EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(_x) \
|
||||
((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 5, 4) << 8) + \
|
||||
(_x).hsync_pulse_width)
|
||||
#define EDID_DETAILED_TIMING_VSYNC_OFFSET(_x) \
|
||||
((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 3, 2) << 4) + \
|
||||
GET_BITS((_x).vsync_offset_pulse_width, 7, 4))
|
||||
#define EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(_x) \
|
||||
((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 1, 0) << 4) + \
|
||||
GET_BITS((_x).vsync_offset_pulse_width, 3, 0))
|
||||
unsigned char himage_size;
|
||||
unsigned char vimage_size;
|
||||
unsigned char himage_vimage_size_hi;
|
||||
#define EDID_DETAILED_TIMING_HIMAGE_SIZE(_x) \
|
||||
((GET_BITS((_x).himage_vimage_size_hi, 7, 4) << 8) + (_x).himage_size)
|
||||
#define EDID_DETAILED_TIMING_VIMAGE_SIZE(_x) \
|
||||
((GET_BITS((_x).himage_vimage_size_hi, 3, 0) << 8) + (_x).vimage_size)
|
||||
unsigned char hborder;
|
||||
unsigned char vborder;
|
||||
unsigned char flags;
|
||||
#define EDID_DETAILED_TIMING_FLAG_INTERLACED(_x) \
|
||||
GET_BIT((_x).flags, 7)
|
||||
#define EDID_DETAILED_TIMING_FLAG_STEREO(_x) \
|
||||
GET_BITS((_x).flags, 6, 5)
|
||||
#define EDID_DETAILED_TIMING_FLAG_DIGITAL_COMPOSITE(_x) \
|
||||
GET_BITS((_x).flags, 4, 3)
|
||||
#define EDID_DETAILED_TIMING_FLAG_POLARITY(_x) \
|
||||
GET_BITS((_x).flags, 2, 1)
|
||||
#define EDID_DETAILED_TIMING_FLAG_INTERLEAVED(_x) \
|
||||
GET_BIT((_x).flags, 0)
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum edid_monitor_descriptor_types {
|
||||
EDID_MONITOR_DESCRIPTOR_SERIAL = 0xff,
|
||||
EDID_MONITOR_DESCRIPTOR_ASCII = 0xfe,
|
||||
EDID_MONITOR_DESCRIPTOR_RANGE = 0xfd,
|
||||
EDID_MONITOR_DESCRIPTOR_NAME = 0xfc,
|
||||
};
|
||||
|
||||
struct edid_monitor_descriptor {
|
||||
uint16_t zero_flag_1;
|
||||
unsigned char zero_flag_2;
|
||||
unsigned char type;
|
||||
unsigned char zero_flag_3;
|
||||
union {
|
||||
char string[13];
|
||||
struct {
|
||||
unsigned char vertical_min;
|
||||
unsigned char vertical_max;
|
||||
unsigned char horizontal_min;
|
||||
unsigned char horizontal_max;
|
||||
unsigned char pixel_clock_max;
|
||||
unsigned char gtf_data[8];
|
||||
} range_data;
|
||||
} data;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct edid1_info {
|
||||
unsigned char header[8];
|
||||
unsigned char manufacturer_name[2];
|
||||
#define EDID1_INFO_MANUFACTURER_NAME_ZERO(_x) \
|
||||
GET_BIT(((_x).manufacturer_name[0]), 7)
|
||||
#define EDID1_INFO_MANUFACTURER_NAME_CHAR1(_x) \
|
||||
GET_BITS(((_x).manufacturer_name[0]), 6, 2)
|
||||
#define EDID1_INFO_MANUFACTURER_NAME_CHAR2(_x) \
|
||||
((GET_BITS(((_x).manufacturer_name[0]), 1, 0) << 3) + \
|
||||
GET_BITS(((_x).manufacturer_name[1]), 7, 5))
|
||||
#define EDID1_INFO_MANUFACTURER_NAME_CHAR3(_x) \
|
||||
GET_BITS(((_x).manufacturer_name[1]), 4, 0)
|
||||
unsigned char product_code[2];
|
||||
#define EDID1_INFO_PRODUCT_CODE(_x) \
|
||||
(((uint16_t)(_x).product_code[1] << 8) + (_x).product_code[0])
|
||||
unsigned char serial_number[4];
|
||||
#define EDID1_INFO_SERIAL_NUMBER(_x) \
|
||||
(((uint32_t)(_x).serial_number[3] << 24) + \
|
||||
((_x).serial_number[2] << 16) + ((_x).serial_number[1] << 8) + \
|
||||
(_x).serial_number[0])
|
||||
unsigned char week;
|
||||
unsigned char year;
|
||||
unsigned char version;
|
||||
unsigned char revision;
|
||||
unsigned char video_input_definition;
|
||||
#define EDID1_INFO_VIDEO_INPUT_DIGITAL(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 7)
|
||||
#define EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(_x) \
|
||||
GET_BITS(((_x).video_input_definition), 6, 5)
|
||||
#define EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 4)
|
||||
#define EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 3)
|
||||
#define EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 2)
|
||||
#define EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 1)
|
||||
#define EDID1_INFO_VIDEO_INPUT_SERRATION_V(_x) \
|
||||
GET_BIT(((_x).video_input_definition), 0)
|
||||
unsigned char max_size_horizontal;
|
||||
unsigned char max_size_vertical;
|
||||
unsigned char gamma;
|
||||
unsigned char feature_support;
|
||||
#define EDID1_INFO_FEATURE_STANDBY(_x) \
|
||||
GET_BIT(((_x).feature_support), 7)
|
||||
#define EDID1_INFO_FEATURE_SUSPEND(_x) \
|
||||
GET_BIT(((_x).feature_support), 6)
|
||||
#define EDID1_INFO_FEATURE_ACTIVE_OFF(_x) \
|
||||
GET_BIT(((_x).feature_support), 5)
|
||||
#define EDID1_INFO_FEATURE_DISPLAY_TYPE(_x) \
|
||||
GET_BITS(((_x).feature_support), 4, 3)
|
||||
#define EDID1_INFO_FEATURE_RGB(_x) \
|
||||
GET_BIT(((_x).feature_support), 2)
|
||||
#define EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(_x) \
|
||||
GET_BIT(((_x).feature_support), 1)
|
||||
#define EDID1_INFO_FEATURE_DEFAULT_GTF_SUPPORT(_x) \
|
||||
GET_BIT(((_x).feature_support), 0)
|
||||
unsigned char color_characteristics[10];
|
||||
unsigned char established_timings[3];
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_720X400_70(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 7)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_720X400_88(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 6)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_640X480_60(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 5)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_640X480_67(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 4)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_640X480_72(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 3)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_640X480_75(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 2)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_800X600_56(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 1)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_800X600_60(_x) \
|
||||
GET_BIT(((_x).established_timings[0]), 0)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_800X600_72(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 7)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_800X600_75(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 6)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_832X624_75(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 5)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 4)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 3)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 2)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 1)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(_x) \
|
||||
GET_BIT(((_x).established_timings[1]), 0)
|
||||
#define EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(_x) \
|
||||
GET_BIT(((_x).established_timings[2]), 7)
|
||||
struct {
|
||||
unsigned char xresolution;
|
||||
unsigned char aspect_vfreq;
|
||||
} __attribute__((__packed__)) standard_timings[8];
|
||||
#define EDID1_INFO_STANDARD_TIMING_XRESOLUTION(_x, _i) \
|
||||
(((_x).standard_timings[_i]).xresolution)
|
||||
#define EDID1_INFO_STANDARD_TIMING_ASPECT(_x, _i) \
|
||||
GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 7, 6)
|
||||
#define EDID1_INFO_STANDARD_TIMING_VFREQ(_x, _i) \
|
||||
GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 5, 0)
|
||||
union {
|
||||
unsigned char timing[72];
|
||||
struct edid_monitor_descriptor descriptor[4];
|
||||
} monitor_details;
|
||||
unsigned char extension_flag;
|
||||
unsigned char checksum;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/**
|
||||
* Print the EDID info.
|
||||
*
|
||||
* @param edid_info The EDID info to be printed
|
||||
*/
|
||||
void edid_print_info(struct edid1_info *edid_info);
|
||||
|
||||
/**
|
||||
* Check the EDID info.
|
||||
*
|
||||
* @param info The EDID info to be checked
|
||||
* @return 0 on valid, or -1 on invalid
|
||||
*/
|
||||
int edid_check_info(struct edid1_info *info);
|
||||
|
||||
/**
|
||||
* Get the horizontal and vertical rate ranges of the monitor.
|
||||
*
|
||||
* @param edid The EDID info
|
||||
* @param hmin Returns the minimum horizontal rate
|
||||
* @param hmax Returns the maxium horizontal rate
|
||||
* @param vmin Returns the minimum vertical rate
|
||||
* @param vmax Returns the maxium vertical rate
|
||||
* @return 0 on success, or -1 on error
|
||||
*/
|
||||
int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
|
||||
unsigned int *hmax, unsigned int *vmin,
|
||||
unsigned int *vmax);
|
||||
|
||||
#endif /* __EDID_H_ */
|
55
include/env_attr.h
Normal file
55
include/env_attr.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ENV_ATTR_H__
|
||||
#define __ENV_ATTR_H__
|
||||
|
||||
#define ENV_ATTR_LIST_DELIM ','
|
||||
#define ENV_ATTR_SEP ':'
|
||||
|
||||
/*
|
||||
* env_attr_walk takes as input an "attr_list" that takes the form:
|
||||
* attributes = [^,:\s]*
|
||||
* entry = name[:attributes]
|
||||
* list = entry[,list]
|
||||
* It will call the "callback" function with the "name" and attribute as "value"
|
||||
* The callback may return a non-0 to abort the list walk.
|
||||
* This return value will be passed through to the caller.
|
||||
* 0 is returned on success.
|
||||
*/
|
||||
extern int env_attr_walk(const char *attr_list,
|
||||
int (*callback)(const char *name, const char *value));
|
||||
|
||||
/*
|
||||
* env_attr_lookup takes as input an "attr_list" with the same form as above.
|
||||
* It also takes as input a "name" to look for.
|
||||
* If the name is found in the list, it's value is copied into "attributes".
|
||||
* There is no protection on attributes being too small for the value.
|
||||
* It returns -1 if attributes is NULL, 1 if "name" is not found, 2 if
|
||||
* "attr_list" is NULL.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
extern int env_attr_lookup(const char *attr_list, const char *name,
|
||||
char *attributes);
|
||||
|
||||
#endif /* __ENV_ATTR_H__ */
|
75
include/env_callback.h
Normal file
75
include/env_callback.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ENV_CALLBACK_H__
|
||||
#define __ENV_CALLBACK_H__
|
||||
|
||||
#include <env_flags.h>
|
||||
#include <linker_lists.h>
|
||||
#include <search.h>
|
||||
|
||||
#define ENV_CALLBACK_VAR ".callbacks"
|
||||
|
||||
/* Board configs can define additional static callback bindings */
|
||||
#ifndef CONFIG_ENV_CALLBACK_LIST_STATIC
|
||||
#define CONFIG_ENV_CALLBACK_LIST_STATIC
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
#define SILENT_CALLBACK "silent:silent,"
|
||||
#else
|
||||
#define SILENT_CALLBACK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This list of callback bindings is static, but may be overridden by defining
|
||||
* a new association in the ".callbacks" environment variable.
|
||||
*/
|
||||
#define ENV_CALLBACK_LIST_STATIC ENV_CALLBACK_VAR ":callbacks," \
|
||||
ENV_FLAGS_VAR ":flags," \
|
||||
"baudrate:baudrate," \
|
||||
"bootfile:bootfile," \
|
||||
"loadaddr:loadaddr," \
|
||||
SILENT_CALLBACK \
|
||||
"stdin:console,stdout:console,stderr:console," \
|
||||
CONFIG_ENV_CALLBACK_LIST_STATIC
|
||||
|
||||
struct env_clbk_tbl {
|
||||
const char *name; /* Callback name */
|
||||
int (*callback)(const char *name, const char *value, enum env_op op,
|
||||
int flags);
|
||||
};
|
||||
|
||||
struct env_clbk_tbl *find_env_callback(const char *);
|
||||
void env_callback_init(ENTRY *var_entry);
|
||||
|
||||
/*
|
||||
* Define a callback that can be associated with variables.
|
||||
* when associated through the ".callbacks" environment variable, the callback
|
||||
* will be executed any time the variable is inserted, overwritten, or deleted.
|
||||
*/
|
||||
#define U_BOOT_ENV_CALLBACK(name, callback) \
|
||||
ll_entry_declare(struct env_clbk_tbl, name, env_clbk, env_clbk) = \
|
||||
{#name, callback}
|
||||
|
||||
#endif /* __ENV_CALLBACK_H__ */
|
@ -24,6 +24,8 @@
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <env_callback.h>
|
||||
|
||||
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
|
||||
env_t environment __PPCENV__ = {
|
||||
ENV_CRC, /* CRC Sum */
|
||||
@ -36,6 +38,12 @@ static char default_environment[] = {
|
||||
#else
|
||||
const uchar default_environment[] = {
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
|
||||
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
|
||||
ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTARGS
|
||||
"bootargs=" CONFIG_BOOTARGS "\0"
|
||||
#endif
|
||||
|
172
include/env_flags.h
Normal file
172
include/env_flags.h
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger, National Instruments, joe.hershberger@ni.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ENV_FLAGS_H__
|
||||
#define __ENV_FLAGS_H__
|
||||
|
||||
enum env_flags_vartype {
|
||||
env_flags_vartype_string,
|
||||
env_flags_vartype_decimal,
|
||||
env_flags_vartype_hex,
|
||||
env_flags_vartype_bool,
|
||||
#ifdef CONFIG_CMD_NET
|
||||
env_flags_vartype_ipaddr,
|
||||
env_flags_vartype_macaddr,
|
||||
#endif
|
||||
env_flags_vartype_end
|
||||
};
|
||||
|
||||
enum env_flags_varaccess {
|
||||
env_flags_varaccess_any,
|
||||
env_flags_varaccess_readonly,
|
||||
env_flags_varaccess_writeonce,
|
||||
env_flags_varaccess_changedefault,
|
||||
env_flags_varaccess_end
|
||||
};
|
||||
|
||||
#define ENV_FLAGS_VAR ".flags"
|
||||
#define ENV_FLAGS_ATTR_MAX_LEN 2
|
||||
#define ENV_FLAGS_VARTYPE_LOC 0
|
||||
#define ENV_FLAGS_VARACCESS_LOC 1
|
||||
|
||||
#ifndef CONFIG_ENV_FLAGS_LIST_STATIC
|
||||
#define CONFIG_ENV_FLAGS_LIST_STATIC ""
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#ifdef CONFIG_ENV_OVERWRITE
|
||||
#define ETHADDR_FLAGS "ethaddr:ma,"
|
||||
#else
|
||||
#ifdef CONFIG_OVERWRITE_ETHADDR_ONCE
|
||||
#define ETHADDR_FLAGS "ethaddr:mc,"
|
||||
#else
|
||||
#define ETHADDR_FLAGS "ethaddr:mo,"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define ETHADDR_FLAGS ""
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ENV_OVERWRITE
|
||||
#define SERIAL_FLAGS "serial#:so,"
|
||||
#else
|
||||
#define SERIAL_FLAGS ""
|
||||
#endif
|
||||
|
||||
#define ENV_FLAGS_LIST_STATIC \
|
||||
ETHADDR_FLAGS \
|
||||
SERIAL_FLAGS \
|
||||
CONFIG_ENV_FLAGS_LIST_STATIC
|
||||
|
||||
#ifdef CONFIG_CMD_ENV_FLAGS
|
||||
/*
|
||||
* Print the whole list of available type flags.
|
||||
*/
|
||||
void env_flags_print_vartypes(void);
|
||||
/*
|
||||
* Print the whole list of available access flags.
|
||||
*/
|
||||
void env_flags_print_varaccess(void);
|
||||
/*
|
||||
* Return the name of the type.
|
||||
*/
|
||||
const char *env_flags_get_vartype_name(enum env_flags_vartype type);
|
||||
/*
|
||||
* Return the name of the access.
|
||||
*/
|
||||
const char *env_flags_get_varaccess_name(enum env_flags_varaccess access);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse the flags string from a .flags attribute list into the vartype enum.
|
||||
*/
|
||||
enum env_flags_vartype env_flags_parse_vartype(const char *flags);
|
||||
/*
|
||||
* Parse the flags string from a .flags attribute list into the varaccess enum.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_parse_varaccess(const char *flags);
|
||||
/*
|
||||
* Parse the binary flags from a hash table entry into the varaccess enum.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags);
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
/*
|
||||
* Look up the type of a variable directly from the .flags var.
|
||||
*/
|
||||
enum env_flags_vartype env_flags_get_type(const char *name);
|
||||
/*
|
||||
* Look up the access of a variable directly from the .flags var.
|
||||
*/
|
||||
enum env_flags_varaccess env_flags_get_access(const char *name);
|
||||
/*
|
||||
* Validate the newval for its type to conform with the requirements defined by
|
||||
* its flags (directly looked at the .flags var).
|
||||
*/
|
||||
int env_flags_validate_type(const char *name, const char *newval);
|
||||
/*
|
||||
* Validate the newval for its access to conform with the requirements defined
|
||||
* by its flags (directly looked at the .flags var).
|
||||
*/
|
||||
int env_flags_validate_access(const char *name, int check_mask);
|
||||
/*
|
||||
* Validate that the proposed access to variable "name" is valid according to
|
||||
* the defined flags for that variable, if any.
|
||||
*/
|
||||
int env_flags_validate_varaccess(const char *name, int check_mask);
|
||||
/*
|
||||
* Validate the parameters passed to "env set" for type compliance
|
||||
*/
|
||||
int env_flags_validate_env_set_params(int argc, char * const argv[]);
|
||||
|
||||
#else /* !USE_HOSTCC */
|
||||
|
||||
#include <search.h>
|
||||
|
||||
/*
|
||||
* When adding a variable to the environment, initialize the flags for that
|
||||
* variable.
|
||||
*/
|
||||
void env_flags_init(ENTRY *var_entry);
|
||||
|
||||
/*
|
||||
* Validate the newval for to conform with the requirements defined by its flags
|
||||
*/
|
||||
int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
|
||||
int flag);
|
||||
|
||||
#endif /* USE_HOSTCC */
|
||||
|
||||
/*
|
||||
* These are the binary flags used in the environment entry->flags variable to
|
||||
* decribe properties of veriables in the table
|
||||
*/
|
||||
#define ENV_FLAGS_VARTYPE_BIN_MASK 0x00000007
|
||||
/* The actual variable type values use the enum value (within the mask) */
|
||||
#define ENV_FLAGS_VARACCESS_PREVENT_DELETE 0x00000008
|
||||
#define ENV_FLAGS_VARACCESS_PREVENT_CREATE 0x00000010
|
||||
#define ENV_FLAGS_VARACCESS_PREVENT_OVERWR 0x00000020
|
||||
#define ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR 0x00000040
|
||||
#define ENV_FLAGS_VARACCESS_BIN_MASK 0x00000078
|
||||
|
||||
#endif /* __ENV_FLAGS_H__ */
|
@ -164,6 +164,9 @@ extern void env_reloc(void);
|
||||
|
||||
#ifndef DO_DEPS_ONLY
|
||||
|
||||
#include <env_attr.h>
|
||||
#include <env_callback.h>
|
||||
#include <env_flags.h>
|
||||
#include <search.h>
|
||||
|
||||
extern struct hsearch_data env_htab;
|
||||
@ -178,6 +181,9 @@ unsigned char env_get_char_memory(int index);
|
||||
/* Function that updates CRC of the enironment */
|
||||
void env_crc_update(void);
|
||||
|
||||
/* Look up the variable from the default environment */
|
||||
char *getenv_default(const char *name);
|
||||
|
||||
/* [re]set to the default environment */
|
||||
void set_default_env(const char *s);
|
||||
|
||||
@ -187,15 +193,6 @@ int set_default_vars(int nvars, char * const vars[]);
|
||||
/* Import from binary representation into hash table */
|
||||
int env_import(const char *buf, int check);
|
||||
|
||||
/*
|
||||
* Check if variable "name" can be changed from oldval to newval,
|
||||
* and if so, apply the changes (e.g. baudrate).
|
||||
* When (flag & H_FORCE) is set, it does not print out any error
|
||||
* message and forces overwriting of write-once variables.
|
||||
*/
|
||||
int env_check_apply(const char *name, const char *oldval,
|
||||
const char *newval, int flag);
|
||||
|
||||
#endif /* DO_DEPS_ONLY */
|
||||
|
||||
#endif /* _ENVIRONMENT_H_ */
|
||||
|
@ -23,7 +23,7 @@ char *getenv (const char *name);
|
||||
int setenv (const char *varname, const char *varvalue);
|
||||
long simple_strtol(const char *cp,char **endp,unsigned int base);
|
||||
int strcmp(const char * cs,const char * ct);
|
||||
int ustrtoul(const char *cp, char **endp, unsigned int base);
|
||||
unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
|
||||
#if defined(CONFIG_CMD_I2C)
|
||||
int i2c_write (uchar, uint, int , uchar* , int);
|
||||
int i2c_read (uchar, uint, int , uchar* , int);
|
||||
|
69
include/hash.h
Normal file
69
include/hash.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _HASH_H
|
||||
#define _HASH_H
|
||||
|
||||
#ifdef CONFIG_SHA1SUM_VERIFY
|
||||
#define CONFIG_HASH_VERIFY
|
||||
#endif
|
||||
|
||||
struct hash_algo {
|
||||
const char *name; /* Name of algorithm */
|
||||
int digest_size; /* Length of digest */
|
||||
/**
|
||||
* hash_func_ws: Generic hashing function
|
||||
*
|
||||
* This is the generic prototype for a hashing function. We only
|
||||
* have the watchdog version at present.
|
||||
*
|
||||
* @input: Input buffer
|
||||
* @ilen: Input buffer length
|
||||
* @output: Checksum result (length depends on algorithm)
|
||||
* @chunk_sz: Trigger watchdog after processing this many bytes
|
||||
*/
|
||||
void (*hash_func_ws)(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz);
|
||||
int chunk_size; /* Watchdog chunk size */
|
||||
};
|
||||
|
||||
/*
|
||||
* Maximum digest size for all algorithms we support. Having this value
|
||||
* avoids a malloc() or C99 local declaration in common/cmd_hash.c.
|
||||
*/
|
||||
#define HASH_MAX_DIGEST_SIZE 32
|
||||
|
||||
/**
|
||||
* hash_command: Process a hash command for a particular algorithm
|
||||
*
|
||||
* This common function is used to implement specific hash commands.
|
||||
*
|
||||
* @algo_name: Hash algorithm being used
|
||||
* @verify: Non-zero to enable verify mode
|
||||
* @cmdtp: Pointer to command table entry
|
||||
* @flag: Some flags normally 0 (see CMD_FLAG_.. above)
|
||||
* @argc: Number of arguments (arg 0 must be the command text)
|
||||
* @argv: Arguments
|
||||
*/
|
||||
int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[]);
|
||||
|
||||
#endif
|
@ -460,7 +460,6 @@ static inline void image_set_name(image_header_t *hdr, const char *name)
|
||||
int image_check_hcrc(const image_header_t *hdr);
|
||||
int image_check_dcrc(const image_header_t *hdr);
|
||||
#ifndef USE_HOSTCC
|
||||
int getenv_yesno(char *var);
|
||||
ulong getenv_bootm_low(void);
|
||||
phys_size_t getenv_bootm_size(void);
|
||||
phys_size_t getenv_bootm_mapsize(void);
|
||||
|
8
include/linux/linux_string.h
Normal file
8
include/linux/linux_string.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _LINUX_LINUX_STRING_H_
|
||||
#define _LINUX_LINUX_STRING_H_
|
||||
|
||||
extern char * skip_spaces(const char *);
|
||||
|
||||
extern char *strim(char *);
|
||||
|
||||
#endif
|
@ -38,8 +38,11 @@ extern int strcmp(const char *,const char *);
|
||||
#ifndef __HAVE_ARCH_STRNCMP
|
||||
extern int strncmp(const char *,const char *,__kernel_size_t);
|
||||
#endif
|
||||
#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
|
||||
extern int strnicmp(const char *, const char *, __kernel_size_t);
|
||||
#ifndef __HAVE_ARCH_STRCASECMP
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
#endif
|
||||
#ifndef __HAVE_ARCH_STRNCASECMP
|
||||
extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
|
||||
#endif
|
||||
#ifndef __HAVE_ARCH_STRCHR
|
||||
extern char * strchr(const char *,int);
|
||||
@ -47,10 +50,7 @@ extern char * strchr(const char *,int);
|
||||
#ifndef __HAVE_ARCH_STRRCHR
|
||||
extern char * strrchr(const char *,int);
|
||||
#endif
|
||||
extern char * skip_spaces(const char *);
|
||||
|
||||
extern char *strim(char *);
|
||||
|
||||
#include <linux/linux_string.h>
|
||||
#ifndef __HAVE_ARCH_STRSTR
|
||||
extern char * strstr(const char *,const char *);
|
||||
#endif
|
||||
|
@ -176,10 +176,62 @@ int test_part_amiga (block_dev_desc_t *dev_desc);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EFI_PARTITION
|
||||
#include <part_efi.h>
|
||||
/* disk/part_efi.c */
|
||||
int get_partition_info_efi (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part_efi (block_dev_desc_t *dev_desc);
|
||||
int test_part_efi (block_dev_desc_t *dev_desc);
|
||||
|
||||
/**
|
||||
* write_gpt_table() - Write the GUID Partition Table to disk
|
||||
*
|
||||
* @param dev_desc - block device descriptor
|
||||
* @param gpt_h - pointer to GPT header representation
|
||||
* @param gpt_e - pointer to GPT partition table entries
|
||||
*
|
||||
* @return - zero on success, otherwise error
|
||||
*/
|
||||
int write_gpt_table(block_dev_desc_t *dev_desc,
|
||||
gpt_header *gpt_h, gpt_entry *gpt_e);
|
||||
|
||||
/**
|
||||
* gpt_fill_pte(): Fill the GPT partition table entry
|
||||
*
|
||||
* @param gpt_h - GPT header representation
|
||||
* @param gpt_e - GPT partition table entries
|
||||
* @param partitions - list of partitions
|
||||
* @param parts - number of partitions
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
|
||||
disk_partition_t *partitions, int parts);
|
||||
|
||||
/**
|
||||
* gpt_fill_header(): Fill the GPT header
|
||||
*
|
||||
* @param dev_desc - block device descriptor
|
||||
* @param gpt_h - GPT header representation
|
||||
* @param str_guid - disk guid string representation
|
||||
* @param parts_count - number of partitions
|
||||
*
|
||||
* @return - error on str_guid conversion error
|
||||
*/
|
||||
int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
|
||||
char *str_guid, int parts_count);
|
||||
|
||||
/**
|
||||
* gpt_restore(): Restore GPT partition table
|
||||
*
|
||||
* @param dev_desc - block device descriptor
|
||||
* @param str_disk_guid - disk GUID
|
||||
* @param partitions - list of partitions
|
||||
* @param parts - number of partitions
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
|
||||
disk_partition_t *partitions, const int parts_count);
|
||||
#endif
|
||||
|
||||
#endif /* _PART_H */
|
||||
|
@ -29,6 +29,8 @@
|
||||
* http://developer.intel.com/technology/efi/efi.htm
|
||||
*/
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifndef _DISK_PART_EFI_H
|
||||
#define _DISK_PART_EFI_H
|
||||
|
||||
@ -41,6 +43,8 @@
|
||||
#define GPT_HEADER_REVISION_V1 0x00010000
|
||||
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL
|
||||
#define GPT_ENTRY_NAME "gpt"
|
||||
#define GPT_ENTRY_NUMBERS 128
|
||||
#define GPT_ENTRY_SIZE 128
|
||||
|
||||
#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
|
||||
((efi_guid_t) \
|
||||
@ -72,73 +76,72 @@
|
||||
0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
|
||||
|
||||
/* linux/include/efi.h */
|
||||
typedef unsigned short efi_char16_t;
|
||||
typedef u16 efi_char16_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char b[16];
|
||||
u8 b[16];
|
||||
} efi_guid_t;
|
||||
|
||||
/* based on linux/include/genhd.h */
|
||||
struct partition {
|
||||
unsigned char boot_ind; /* 0x80 - active */
|
||||
unsigned char head; /* starting head */
|
||||
unsigned char sector; /* starting sector */
|
||||
unsigned char cyl; /* starting cylinder */
|
||||
unsigned char sys_ind; /* What partition type */
|
||||
unsigned char end_head; /* end head */
|
||||
unsigned char end_sector; /* end sector */
|
||||
unsigned char end_cyl; /* end cylinder */
|
||||
unsigned char start_sect[4]; /* starting sector counting from 0 */
|
||||
unsigned char nr_sects[4]; /* nr of sectors in partition */
|
||||
} __attribute__ ((packed));
|
||||
u8 boot_ind; /* 0x80 - active */
|
||||
u8 head; /* starting head */
|
||||
u8 sector; /* starting sector */
|
||||
u8 cyl; /* starting cylinder */
|
||||
u8 sys_ind; /* What partition type */
|
||||
u8 end_head; /* end head */
|
||||
u8 end_sector; /* end sector */
|
||||
u8 end_cyl; /* end cylinder */
|
||||
__le32 start_sect; /* starting sector counting from 0 */
|
||||
__le32 nr_sects; /* nr of sectors in partition */
|
||||
} __packed;
|
||||
|
||||
/* based on linux/fs/partitions/efi.h */
|
||||
typedef struct _gpt_header {
|
||||
unsigned char signature[8];
|
||||
unsigned char revision[4];
|
||||
unsigned char header_size[4];
|
||||
unsigned char header_crc32[4];
|
||||
unsigned char reserved1[4];
|
||||
unsigned char my_lba[8];
|
||||
unsigned char alternate_lba[8];
|
||||
unsigned char first_usable_lba[8];
|
||||
unsigned char last_usable_lba[8];
|
||||
__le64 signature;
|
||||
__le32 revision;
|
||||
__le32 header_size;
|
||||
__le32 header_crc32;
|
||||
__le32 reserved1;
|
||||
__le64 my_lba;
|
||||
__le64 alternate_lba;
|
||||
__le64 first_usable_lba;
|
||||
__le64 last_usable_lba;
|
||||
efi_guid_t disk_guid;
|
||||
unsigned char partition_entry_lba[8];
|
||||
unsigned char num_partition_entries[4];
|
||||
unsigned char sizeof_partition_entry[4];
|
||||
unsigned char partition_entry_array_crc32[4];
|
||||
unsigned char reserved2[GPT_BLOCK_SIZE - 92];
|
||||
} __attribute__ ((packed)) gpt_header;
|
||||
__le64 partition_entry_lba;
|
||||
__le32 num_partition_entries;
|
||||
__le32 sizeof_partition_entry;
|
||||
__le32 partition_entry_array_crc32;
|
||||
u8 reserved2[GPT_BLOCK_SIZE - 92];
|
||||
} __packed gpt_header;
|
||||
|
||||
typedef union _gpt_entry_attributes {
|
||||
struct {
|
||||
unsigned long long required_to_function:1;
|
||||
unsigned long long no_block_io_protocol:1;
|
||||
unsigned long long legacy_bios_bootable:1;
|
||||
unsigned long long reserved:45;
|
||||
unsigned long long type_guid_specific:16;
|
||||
u64 required_to_function:1;
|
||||
u64 no_block_io_protocol:1;
|
||||
u64 legacy_bios_bootable:1;
|
||||
u64 reserved:45;
|
||||
u64 type_guid_specific:16;
|
||||
} fields;
|
||||
unsigned long long raw;
|
||||
} __attribute__ ((packed)) gpt_entry_attributes;
|
||||
} __packed gpt_entry_attributes;
|
||||
|
||||
#define PARTNAME_SZ (72 / sizeof(efi_char16_t))
|
||||
typedef struct _gpt_entry {
|
||||
efi_guid_t partition_type_guid;
|
||||
efi_guid_t unique_partition_guid;
|
||||
unsigned char starting_lba[8];
|
||||
unsigned char ending_lba[8];
|
||||
__le64 starting_lba;
|
||||
__le64 ending_lba;
|
||||
gpt_entry_attributes attributes;
|
||||
efi_char16_t partition_name[PARTNAME_SZ];
|
||||
}
|
||||
__attribute__ ((packed)) gpt_entry;
|
||||
} __packed gpt_entry;
|
||||
|
||||
typedef struct _legacy_mbr {
|
||||
unsigned char boot_code[440];
|
||||
unsigned char unique_mbr_signature[4];
|
||||
unsigned char unknown[2];
|
||||
u8 boot_code[440];
|
||||
__le32 unique_mbr_signature;
|
||||
__le16 unknown;
|
||||
struct partition partition_record[4];
|
||||
unsigned char signature[2];
|
||||
} __attribute__ ((packed)) legacy_mbr;
|
||||
__le16 signature;
|
||||
} __packed legacy_mbr;
|
||||
|
||||
#endif /* _DISK_PART_EFI_H */
|
@ -32,6 +32,12 @@
|
||||
|
||||
#define __set_errno(val) do { errno = val; } while (0)
|
||||
|
||||
enum env_op {
|
||||
env_op_create,
|
||||
env_op_delete,
|
||||
env_op_overwrite,
|
||||
};
|
||||
|
||||
/* Action which shall be performed in the call the hsearch. */
|
||||
typedef enum {
|
||||
FIND,
|
||||
@ -41,6 +47,9 @@ typedef enum {
|
||||
typedef struct entry {
|
||||
const char *key;
|
||||
char *data;
|
||||
int (*callback)(const char *name, const char *value, enum env_op op,
|
||||
int flags);
|
||||
int flags;
|
||||
} ENTRY;
|
||||
|
||||
/* Opaque type for internal use. */
|
||||
@ -59,21 +68,20 @@ struct hsearch_data {
|
||||
unsigned int filled;
|
||||
/*
|
||||
* Callback function which will check whether the given change for variable
|
||||
* "name" from "oldval" to "newval" may be applied or not, and possibly apply
|
||||
* such change.
|
||||
* "item" to "newval" may be applied or not, and possibly apply such change.
|
||||
* When (flag & H_FORCE) is set, it shall not print out any error message and
|
||||
* shall force overwriting of write-once variables.
|
||||
.* Must return 0 for approval, 1 for denial.
|
||||
*/
|
||||
int (*apply)(const char *name, const char *oldval,
|
||||
const char *newval, int flag);
|
||||
int (*change_ok)(const ENTRY *__item, const char *newval, enum env_op,
|
||||
int flag);
|
||||
};
|
||||
|
||||
/* Create a new hashing table which will at most contain NEL elements. */
|
||||
extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
|
||||
|
||||
/* Destroy current internal hashing table. */
|
||||
extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
|
||||
extern void hdestroy_r(struct hsearch_data *__htab);
|
||||
|
||||
/*
|
||||
* Search for entry matching ITEM.key in internal hash table. If
|
||||
@ -82,7 +90,7 @@ extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
|
||||
* ITEM.data.
|
||||
* */
|
||||
extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
|
||||
struct hsearch_data *__htab);
|
||||
struct hsearch_data *__htab, int __flag);
|
||||
|
||||
/*
|
||||
* Search for an entry matching `MATCH'. Otherwise, Same semantics
|
||||
@ -99,10 +107,10 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
|
||||
|
||||
/* Search and delete entry matching ITEM.key in internal hash table. */
|
||||
extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
|
||||
int do_apply);
|
||||
int __flag);
|
||||
|
||||
extern ssize_t hexport_r(struct hsearch_data *__htab,
|
||||
const char __sep, char **__resp, size_t __size,
|
||||
const char __sep, int __flag, char **__resp, size_t __size,
|
||||
int argc, char * const argv[]);
|
||||
|
||||
/*
|
||||
@ -113,10 +121,15 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
|
||||
*/
|
||||
extern int himport_r(struct hsearch_data *__htab,
|
||||
const char *__env, size_t __size, const char __sep,
|
||||
int __flag, int nvars, char * const vars[], int do_apply);
|
||||
int __flag, int nvars, char * const vars[]);
|
||||
|
||||
/* Flags for himport_r() */
|
||||
#define H_NOCLEAR (1 << 0) /* do not clear hash table before importing */
|
||||
#define H_FORCE (1 << 1) /* overwrite read-only/write-once variables */
|
||||
/* Walk the whole table calling the callback on each element */
|
||||
extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
|
||||
|
||||
/* Flags for himport_r(), hexport_r(), hdelete_r(), and hsearch_r() */
|
||||
#define H_NOCLEAR (1 << 0) /* do not clear hash table before importing */
|
||||
#define H_FORCE (1 << 1) /* overwrite read-only/write-once variables */
|
||||
#define H_INTERACTIVE (1 << 2) /* indicate that an import is user directed */
|
||||
#define H_HIDE_DOT (1 << 3) /* don't print env vars that begin with '.' */
|
||||
|
||||
#endif /* search.h */
|
||||
|
@ -59,7 +59,8 @@ void sha1_starts( sha1_context *ctx );
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );
|
||||
void sha1_update(sha1_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
@ -76,8 +77,8 @@ void sha1_finish( sha1_context *ctx, unsigned char output[20] );
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void sha1_csum( unsigned char *input, int ilen,
|
||||
unsigned char output[20] );
|
||||
void sha1_csum(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output);
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer ), with watchdog triggering
|
||||
@ -87,17 +88,8 @@ void sha1_csum( unsigned char *input, int ilen,
|
||||
* \param output SHA-1 checksum result
|
||||
* \param chunk_sz watchdog triggering period (in bytes of input processed)
|
||||
*/
|
||||
void sha1_csum_wd (unsigned char *input, int ilen,
|
||||
unsigned char output[20], unsigned int chunk_sz);
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( file contents )
|
||||
*
|
||||
* \param path input file name
|
||||
* \param output SHA-1 checksum result
|
||||
* \return 0 if successful, or 1 if fopen failed
|
||||
*/
|
||||
int sha1_file( char *path, unsigned char output[20] );
|
||||
void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz);
|
||||
|
||||
/**
|
||||
* \brief Output = HMAC-SHA-1( input buffer, hmac key )
|
||||
@ -108,9 +100,9 @@ int sha1_file( char *path, unsigned char output[20] );
|
||||
* \param ilen length of the input data
|
||||
* \param output HMAC-SHA-1 result
|
||||
*/
|
||||
void sha1_hmac( unsigned char *key, int keylen,
|
||||
unsigned char *input, int ilen,
|
||||
unsigned char output[20] );
|
||||
void sha1_hmac(const unsigned char *key, int keylen,
|
||||
const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output);
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#define SHA256_SUM_LEN 32
|
||||
|
||||
/* Reset watchdog each time we process this many bytes */
|
||||
#define CHUNKSZ_SHA256 (64 * 1024)
|
||||
|
||||
typedef struct {
|
||||
uint32_t total[2];
|
||||
uint32_t state[8];
|
||||
@ -10,7 +13,10 @@ typedef struct {
|
||||
} sha256_context;
|
||||
|
||||
void sha256_starts(sha256_context * ctx);
|
||||
void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length);
|
||||
void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length);
|
||||
void sha256_finish(sha256_context * ctx, uint8_t digest[SHA256_SUM_LEN]);
|
||||
|
||||
void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz);
|
||||
|
||||
#endif /* _SHA256_H */
|
||||
|
@ -69,6 +69,7 @@ endif
|
||||
COBJS-y += crc32.o
|
||||
COBJS-y += ctype.o
|
||||
COBJS-y += div64.o
|
||||
COBJS-y += linux_string.o
|
||||
COBJS-y += string.o
|
||||
COBJS-y += time.o
|
||||
COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
|
||||
|
244
lib/hashtable.c
244
lib/hashtable.c
@ -54,7 +54,9 @@
|
||||
#define CONFIG_ENV_MAX_ENTRIES 512
|
||||
#endif
|
||||
|
||||
#include "search.h"
|
||||
#include <env_callback.h>
|
||||
#include <env_flags.h>
|
||||
#include <search.h>
|
||||
|
||||
/*
|
||||
* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
||||
@ -66,12 +68,16 @@
|
||||
* Instead the interface of all functions is extended to take an argument
|
||||
* which describes the current status.
|
||||
*/
|
||||
|
||||
typedef struct _ENTRY {
|
||||
int used;
|
||||
ENTRY entry;
|
||||
} _ENTRY;
|
||||
|
||||
|
||||
static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
|
||||
int idx);
|
||||
|
||||
/*
|
||||
* hcreate()
|
||||
*/
|
||||
@ -142,7 +148,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
|
||||
* be freed and the local static variable can be marked as not used.
|
||||
*/
|
||||
|
||||
void hdestroy_r(struct hsearch_data *htab, int do_apply)
|
||||
void hdestroy_r(struct hsearch_data *htab)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -156,10 +162,7 @@ void hdestroy_r(struct hsearch_data *htab, int do_apply)
|
||||
for (i = 1; i <= htab->size; ++i) {
|
||||
if (htab->table[i].used > 0) {
|
||||
ENTRY *ep = &htab->table[i].entry;
|
||||
if (do_apply && htab->apply != NULL) {
|
||||
/* deletion is always forced */
|
||||
htab->apply(ep->key, ep->data, NULL, H_FORCE);
|
||||
}
|
||||
|
||||
free((void *)ep->key);
|
||||
free(ep->data);
|
||||
}
|
||||
@ -250,14 +253,65 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare an existing entry with the desired key, and overwrite if the action
|
||||
* is ENTER. This is simply a helper function for hsearch_r().
|
||||
*/
|
||||
static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
|
||||
ENTRY **retval, struct hsearch_data *htab, int flag,
|
||||
unsigned int hval, unsigned int idx)
|
||||
{
|
||||
if (htab->table[idx].used == hval
|
||||
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
|
||||
/* Overwrite existing value? */
|
||||
if ((action == ENTER) && (item.data != NULL)) {
|
||||
/* check for permission */
|
||||
if (htab->change_ok != NULL && htab->change_ok(
|
||||
&htab->table[idx].entry, item.data,
|
||||
env_op_overwrite, flag)) {
|
||||
debug("change_ok() rejected setting variable "
|
||||
"%s, skipping it!\n", item.key);
|
||||
__set_errno(EPERM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If there is a callback, call it */
|
||||
if (htab->table[idx].entry.callback &&
|
||||
htab->table[idx].entry.callback(item.key,
|
||||
item.data, env_op_overwrite, flag)) {
|
||||
debug("callback() rejected setting variable "
|
||||
"%s, skipping it!\n", item.key);
|
||||
__set_errno(EINVAL);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(htab->table[idx].entry.data);
|
||||
htab->table[idx].entry.data = strdup(item.data);
|
||||
if (!htab->table[idx].entry.data) {
|
||||
__set_errno(ENOMEM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* return found entry */
|
||||
*retval = &htab->table[idx].entry;
|
||||
return idx;
|
||||
}
|
||||
/* keep searching */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
||||
struct hsearch_data *htab)
|
||||
struct hsearch_data *htab, int flag)
|
||||
{
|
||||
unsigned int hval;
|
||||
unsigned int count;
|
||||
unsigned int len = strlen(item.key);
|
||||
unsigned int idx;
|
||||
unsigned int first_deleted = 0;
|
||||
int ret;
|
||||
|
||||
/* Compute an value for the given string. Perhaps use a better method. */
|
||||
hval = len;
|
||||
@ -289,23 +343,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
||||
&& !first_deleted)
|
||||
first_deleted = idx;
|
||||
|
||||
if (htab->table[idx].used == hval
|
||||
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
|
||||
/* Overwrite existing value? */
|
||||
if ((action == ENTER) && (item.data != NULL)) {
|
||||
free(htab->table[idx].entry.data);
|
||||
htab->table[idx].entry.data =
|
||||
strdup(item.data);
|
||||
if (!htab->table[idx].entry.data) {
|
||||
__set_errno(ENOMEM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* return found entry */
|
||||
*retval = &htab->table[idx].entry;
|
||||
return idx;
|
||||
}
|
||||
ret = _compare_and_overwrite_entry(item, action, retval, htab,
|
||||
flag, hval, idx);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Second hash function:
|
||||
@ -331,23 +372,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
||||
break;
|
||||
|
||||
/* If entry is found use it. */
|
||||
if ((htab->table[idx].used == hval)
|
||||
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
|
||||
/* Overwrite existing value? */
|
||||
if ((action == ENTER) && (item.data != NULL)) {
|
||||
free(htab->table[idx].entry.data);
|
||||
htab->table[idx].entry.data =
|
||||
strdup(item.data);
|
||||
if (!htab->table[idx].entry.data) {
|
||||
__set_errno(ENOMEM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* return found entry */
|
||||
*retval = &htab->table[idx].entry;
|
||||
return idx;
|
||||
}
|
||||
ret = _compare_and_overwrite_entry(item, action, retval,
|
||||
htab, flag, hval, idx);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
}
|
||||
while (htab->table[idx].used);
|
||||
}
|
||||
@ -383,6 +411,34 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
||||
|
||||
++htab->filled;
|
||||
|
||||
/* This is a new entry, so look up a possible callback */
|
||||
env_callback_init(&htab->table[idx].entry);
|
||||
/* Also look for flags */
|
||||
env_flags_init(&htab->table[idx].entry);
|
||||
|
||||
/* check for permission */
|
||||
if (htab->change_ok != NULL && htab->change_ok(
|
||||
&htab->table[idx].entry, item.data, env_op_create, flag)) {
|
||||
debug("change_ok() rejected setting variable "
|
||||
"%s, skipping it!\n", item.key);
|
||||
_hdelete(item.key, htab, &htab->table[idx].entry, idx);
|
||||
__set_errno(EPERM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If there is a callback, call it */
|
||||
if (htab->table[idx].entry.callback &&
|
||||
htab->table[idx].entry.callback(item.key, item.data,
|
||||
env_op_create, flag)) {
|
||||
debug("callback() rejected setting variable "
|
||||
"%s, skipping it!\n", item.key);
|
||||
_hdelete(item.key, htab, &htab->table[idx].entry, idx);
|
||||
__set_errno(EINVAL);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return new entry */
|
||||
*retval = &htab->table[idx].entry;
|
||||
return 1;
|
||||
@ -404,7 +460,21 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
||||
* do that.
|
||||
*/
|
||||
|
||||
int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
|
||||
static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
|
||||
int idx)
|
||||
{
|
||||
/* free used ENTRY */
|
||||
debug("hdelete: DELETING key \"%s\"\n", key);
|
||||
free((void *)ep->key);
|
||||
free(ep->data);
|
||||
ep->callback = NULL;
|
||||
ep->flags = 0;
|
||||
htab->table[idx].used = -1;
|
||||
|
||||
--htab->filled;
|
||||
}
|
||||
|
||||
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
|
||||
{
|
||||
ENTRY e, *ep;
|
||||
int idx;
|
||||
@ -413,20 +483,31 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
|
||||
|
||||
e.key = (char *)key;
|
||||
|
||||
if ((idx = hsearch_r(e, FIND, &ep, htab)) == 0) {
|
||||
idx = hsearch_r(e, FIND, &ep, htab, 0);
|
||||
if (idx == 0) {
|
||||
__set_errno(ESRCH);
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/* free used ENTRY */
|
||||
debug("hdelete: DELETING key \"%s\"\n", key);
|
||||
if (do_apply && htab->apply != NULL)
|
||||
htab->apply(ep->key, ep->data, NULL, H_FORCE);
|
||||
free((void *)ep->key);
|
||||
free(ep->data);
|
||||
htab->table[idx].used = -1;
|
||||
/* Check for permission */
|
||||
if (htab->change_ok != NULL &&
|
||||
htab->change_ok(ep, NULL, env_op_delete, flag)) {
|
||||
debug("change_ok() rejected deleting variable "
|
||||
"%s, skipping it!\n", key);
|
||||
__set_errno(EPERM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--htab->filled;
|
||||
/* If there is a callback, call it */
|
||||
if (htab->table[idx].entry.callback &&
|
||||
htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
|
||||
debug("callback() rejected deleting variable "
|
||||
"%s, skipping it!\n", key);
|
||||
__set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_hdelete(key, htab, ep, idx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -482,7 +563,7 @@ static int cmpkey(const void *p1, const void *p2)
|
||||
return (strcmp(e1->key, e2->key));
|
||||
}
|
||||
|
||||
ssize_t hexport_r(struct hsearch_data *htab, const char sep,
|
||||
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
|
||||
char **resp, size_t size,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
@ -519,6 +600,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
|
||||
if ((argc > 0) && (found == 0))
|
||||
continue;
|
||||
|
||||
if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
|
||||
continue;
|
||||
|
||||
list[n++] = ep;
|
||||
|
||||
totlen += strlen(ep->key) + 2;
|
||||
@ -674,7 +758,7 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])
|
||||
|
||||
int himport_r(struct hsearch_data *htab,
|
||||
const char *env, size_t size, const char sep, int flag,
|
||||
int nvars, char * const vars[], int do_apply)
|
||||
int nvars, char * const vars[])
|
||||
{
|
||||
char *data, *sp, *dp, *name, *value;
|
||||
char *localvars[nvars];
|
||||
@ -704,7 +788,7 @@ int himport_r(struct hsearch_data *htab,
|
||||
debug("Destroy Hash Table: %p table = %p\n", htab,
|
||||
htab->table);
|
||||
if (htab->table)
|
||||
hdestroy_r(htab, do_apply);
|
||||
hdestroy_r(htab);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -770,7 +854,7 @@ int himport_r(struct hsearch_data *htab,
|
||||
if (!drop_var_from_set(name, nvars, localvars))
|
||||
continue;
|
||||
|
||||
if (hdelete_r(name, htab, do_apply) == 0)
|
||||
if (hdelete_r(name, htab, flag) == 0)
|
||||
debug("DELETE ERROR ##############################\n");
|
||||
|
||||
continue;
|
||||
@ -794,30 +878,10 @@ int himport_r(struct hsearch_data *htab,
|
||||
e.key = name;
|
||||
e.data = value;
|
||||
|
||||
/* if there is an apply function, check what it has to say */
|
||||
if (do_apply && htab->apply != NULL) {
|
||||
debug("searching before calling cb function"
|
||||
" for %s\n", name);
|
||||
/*
|
||||
* Search for variable in existing env, so to pass
|
||||
* its previous value to the apply callback
|
||||
*/
|
||||
hsearch_r(e, FIND, &rv, htab);
|
||||
debug("previous value was %s\n", rv ? rv->data : "");
|
||||
if (htab->apply(name, rv ? rv->data : NULL,
|
||||
value, flag)) {
|
||||
debug("callback function refused to set"
|
||||
" variable %s, skipping it!\n", name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
hsearch_r(e, ENTER, &rv, htab);
|
||||
if (rv == NULL) {
|
||||
hsearch_r(e, ENTER, &rv, htab, flag);
|
||||
if (rv == NULL)
|
||||
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
|
||||
name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
|
||||
htab, htab->filled, htab->size,
|
||||
@ -839,7 +903,7 @@ int himport_r(struct hsearch_data *htab,
|
||||
* b) if the variable was not present in current env, we notify
|
||||
* it might be a typo
|
||||
*/
|
||||
if (hdelete_r(localvars[i], htab, do_apply) == 0)
|
||||
if (hdelete_r(localvars[i], htab, flag) == 0)
|
||||
printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
|
||||
else
|
||||
printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
|
||||
@ -848,3 +912,27 @@ int himport_r(struct hsearch_data *htab,
|
||||
debug("INSERT: done\n");
|
||||
return 1; /* everything OK */
|
||||
}
|
||||
|
||||
/*
|
||||
* hwalk_r()
|
||||
*/
|
||||
|
||||
/*
|
||||
* Walk all of the entries in the hash, calling the callback for each one.
|
||||
* this allows some generic operation to be performed on each element.
|
||||
*/
|
||||
int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *))
|
||||
{
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
for (i = 1; i <= htab->size; ++i) {
|
||||
if (htab->table[i].used > 0) {
|
||||
retval = callback(&htab->table[i].entry);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
51
lib/linux_string.c
Normal file
51
lib/linux_string.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* linux/lib/string.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#ifdef USE_HOSTCC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/**
|
||||
* skip_spaces - Removes leading whitespace from @str.
|
||||
* @str: The string to be stripped.
|
||||
*
|
||||
* Returns a pointer to the first non-whitespace character in @str.
|
||||
*/
|
||||
char *skip_spaces(const char *str)
|
||||
{
|
||||
while (isspace(*str))
|
||||
++str;
|
||||
return (char *)str;
|
||||
}
|
||||
|
||||
/**
|
||||
* strim - Removes leading and trailing whitespace from @s.
|
||||
* @s: The string to be stripped.
|
||||
*
|
||||
* Note that the first trailing whitespace is replaced with a %NUL-terminator
|
||||
* in the given string @s. Returns a pointer to the first non-whitespace
|
||||
* character in @s.
|
||||
*/
|
||||
char *strim(char *s)
|
||||
{
|
||||
size_t size;
|
||||
char *end;
|
||||
|
||||
s = skip_spaces(s);
|
||||
size = strlen(s);
|
||||
if (!size)
|
||||
return s;
|
||||
|
||||
end = s + size - 1;
|
||||
while (end >= s && isspace(*end))
|
||||
end--;
|
||||
*(end + 1) = '\0';
|
||||
|
||||
return s;
|
||||
}
|
19
lib/sha1.c
19
lib/sha1.c
@ -73,7 +73,7 @@ void sha1_starts (sha1_context * ctx)
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
static void sha1_process (sha1_context * ctx, unsigned char data[64])
|
||||
static void sha1_process(sha1_context *ctx, const unsigned char data[64])
|
||||
{
|
||||
unsigned long temp, W[16], A, B, C, D, E;
|
||||
|
||||
@ -230,7 +230,8 @@ static void sha1_process (sha1_context * ctx, unsigned char data[64])
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void sha1_update (sha1_context * ctx, unsigned char *input, int ilen)
|
||||
void sha1_update(sha1_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen)
|
||||
{
|
||||
int fill;
|
||||
unsigned long left;
|
||||
@ -305,7 +306,8 @@ void sha1_finish (sha1_context * ctx, unsigned char output[20])
|
||||
/*
|
||||
* Output = SHA-1( input buffer )
|
||||
*/
|
||||
void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])
|
||||
void sha1_csum(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output)
|
||||
{
|
||||
sha1_context ctx;
|
||||
|
||||
@ -318,12 +320,12 @@ void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])
|
||||
* Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
|
||||
* bytes of input processed.
|
||||
*/
|
||||
void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],
|
||||
unsigned int chunk_sz)
|
||||
void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz)
|
||||
{
|
||||
sha1_context ctx;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
unsigned char *end, *curr;
|
||||
const unsigned char *end, *curr;
|
||||
int chunk;
|
||||
#endif
|
||||
|
||||
@ -350,8 +352,9 @@ void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],
|
||||
/*
|
||||
* Output = HMAC-SHA-1( input buffer, hmac key )
|
||||
*/
|
||||
void sha1_hmac (unsigned char *key, int keylen,
|
||||
unsigned char *input, int ilen, unsigned char output[20])
|
||||
void sha1_hmac(const unsigned char *key, int keylen,
|
||||
const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output)
|
||||
{
|
||||
int i;
|
||||
sha1_context ctx;
|
||||
|
37
lib/sha256.c
37
lib/sha256.c
@ -60,7 +60,7 @@ void sha256_starts(sha256_context * ctx)
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
|
||||
void sha256_process(sha256_context * ctx, uint8_t data[64])
|
||||
static void sha256_process(sha256_context *ctx, const uint8_t data[64])
|
||||
{
|
||||
uint32_t temp1, temp2;
|
||||
uint32_t W[64];
|
||||
@ -191,7 +191,7 @@ void sha256_process(sha256_context * ctx, uint8_t data[64])
|
||||
ctx->state[7] += H;
|
||||
}
|
||||
|
||||
void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length)
|
||||
void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
|
||||
{
|
||||
uint32_t left, fill;
|
||||
|
||||
@ -260,3 +260,36 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32])
|
||||
PUT_UINT32_BE(ctx->state[6], digest, 24);
|
||||
PUT_UINT32_BE(ctx->state[7], digest, 28);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
|
||||
* bytes of input processed.
|
||||
*/
|
||||
void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
|
||||
unsigned char *output, unsigned int chunk_sz)
|
||||
{
|
||||
sha256_context ctx;
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
unsigned char *end, *curr;
|
||||
int chunk;
|
||||
#endif
|
||||
|
||||
sha256_starts(&ctx);
|
||||
|
||||
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
|
||||
curr = input;
|
||||
end = input + ilen;
|
||||
while (curr < end) {
|
||||
chunk = end - curr;
|
||||
if (chunk > chunk_sz)
|
||||
chunk = chunk_sz;
|
||||
sha256_update(&ctx, curr, chunk);
|
||||
curr += chunk;
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
#else
|
||||
sha256_update(&ctx, input, ilen);
|
||||
#endif
|
||||
|
||||
sha256_finish(&ctx, output);
|
||||
}
|
||||
|
55
lib/string.c
55
lib/string.c
@ -21,14 +21,13 @@
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
|
||||
/**
|
||||
* strnicmp - Case insensitive, length-limited string comparison
|
||||
* strncasecmp - Case insensitive, length-limited string comparison
|
||||
* @s1: One string
|
||||
* @s2: The other string
|
||||
* @len: the maximum number of characters to compare
|
||||
*/
|
||||
int strnicmp(const char *s1, const char *s2, size_t len)
|
||||
int strncasecmp(const char *s1, const char *s2, size_t len)
|
||||
{
|
||||
/* Yes, Virginia, it had better be unsigned */
|
||||
unsigned char c1, c2;
|
||||
@ -52,7 +51,16 @@ int strnicmp(const char *s1, const char *s2, size_t len)
|
||||
}
|
||||
return (int)c1 - (int)c2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strcasecmp - Case insensitive string comparison
|
||||
* @s1: One string
|
||||
* @s2: The other string
|
||||
*/
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
return strncasecmp(s1, s2, -1U);
|
||||
}
|
||||
|
||||
char * ___strtok;
|
||||
|
||||
@ -214,45 +222,6 @@ char * strrchr(const char * s, int c)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* skip_spaces - Removes leading whitespace from @str.
|
||||
* @str: The string to be stripped.
|
||||
*
|
||||
* Returns a pointer to the first non-whitespace character in @str.
|
||||
*/
|
||||
char *skip_spaces(const char *str)
|
||||
{
|
||||
while (isspace(*str))
|
||||
++str;
|
||||
return (char *)str;
|
||||
}
|
||||
|
||||
/**
|
||||
* strim - Removes leading and trailing whitespace from @s.
|
||||
* @s: The string to be stripped.
|
||||
*
|
||||
* Note that the first trailing whitespace is replaced with a %NUL-terminator
|
||||
* in the given string @s. Returns a pointer to the first non-whitespace
|
||||
* character in @s.
|
||||
*/
|
||||
char *strim(char *s)
|
||||
{
|
||||
size_t size;
|
||||
char *end;
|
||||
|
||||
s = skip_spaces(s);
|
||||
size = strlen(s);
|
||||
if (!size)
|
||||
return s;
|
||||
|
||||
end = s + size - 1;
|
||||
while (end >= s && isspace(*end))
|
||||
end--;
|
||||
*(end + 1) = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
#ifndef __HAVE_ARCH_STRLEN
|
||||
/**
|
||||
* strlen - Find the length of a string
|
||||
|
@ -103,7 +103,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
|
||||
return simple_strtoul(cp, endp, base);
|
||||
}
|
||||
|
||||
int ustrtoul(const char *cp, char **endp, unsigned int base)
|
||||
unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
unsigned long result = simple_strtoul(cp, endp, base);
|
||||
switch (**endp) {
|
||||
|
49
net/net.c
49
net/net.c
@ -82,6 +82,7 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <net.h>
|
||||
#if defined(CONFIG_STATUS_LED)
|
||||
#include <miiphy.h>
|
||||
@ -208,32 +209,46 @@ static int NetTryCount;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static int on_bootfile(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
switch (op) {
|
||||
case env_op_create:
|
||||
case env_op_overwrite:
|
||||
copy_filename(BootFile, value, sizeof(BootFile));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(bootfile, on_bootfile);
|
||||
|
||||
/*
|
||||
* Check if autoload is enabled. If so, use either NFS or TFTP to download
|
||||
* the boot file.
|
||||
*/
|
||||
void net_auto_load(void)
|
||||
{
|
||||
#if defined(CONFIG_CMD_NFS)
|
||||
const char *s = getenv("autoload");
|
||||
|
||||
if (s != NULL) {
|
||||
if (*s == 'n') {
|
||||
/*
|
||||
* Just use BOOTP/RARP to configure system;
|
||||
* Do not use TFTP to load the bootfile.
|
||||
*/
|
||||
net_set_state(NETLOOP_SUCCESS);
|
||||
return;
|
||||
}
|
||||
#if defined(CONFIG_CMD_NFS)
|
||||
if (strcmp(s, "NFS") == 0) {
|
||||
/*
|
||||
* Use NFS to load the bootfile.
|
||||
*/
|
||||
NfsStart();
|
||||
return;
|
||||
}
|
||||
if (s != NULL && strcmp(s, "NFS") == 0) {
|
||||
/*
|
||||
* Use NFS to load the bootfile.
|
||||
*/
|
||||
NfsStart();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (getenv_yesno("autoload") == 0) {
|
||||
/*
|
||||
* Just use BOOTP/RARP to configure system;
|
||||
* Do not use TFTP to load the bootfile.
|
||||
*/
|
||||
net_set_state(NETLOOP_SUCCESS);
|
||||
return;
|
||||
}
|
||||
TftpStart(TFTPGET);
|
||||
}
|
||||
|
3
tools/env/Makefile
vendored
3
tools/env/Makefile
vendored
@ -24,12 +24,15 @@
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
HOSTSRCS := $(SRCTREE)/lib/crc32.c fw_env.c fw_env_main.c
|
||||
HOSTSRCS += $(SRCTREE)/lib/ctype.c $(SRCTREE)/lib/linux_string.c
|
||||
HOSTSRCS += $(SRCTREE)/common/env_attr.c $(SRCTREE)/common/env_flags.c
|
||||
HEADERS := fw_env.h $(OBJTREE)/include/config.h
|
||||
|
||||
# Compile for a hosted environment on the target
|
||||
HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \
|
||||
-idirafter $(OBJTREE)/include2 \
|
||||
-idirafter $(OBJTREE)/include \
|
||||
-idirafter $(SRCTREE)/tools/env \
|
||||
-DUSE_HOSTCC \
|
||||
-DTEXT_BASE=$(TEXT_BASE)
|
||||
|
||||
|
92
tools/env/fw_env.c
vendored
92
tools/env/fw_env.c
vendored
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <env_flags.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <stdio.h>
|
||||
@ -180,6 +181,32 @@ char *fw_getenv (char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the default environment for a variable.
|
||||
* Return the value, if found, or NULL, if not found.
|
||||
*/
|
||||
char *fw_getdefenv(char *name)
|
||||
{
|
||||
char *env, *nxt;
|
||||
|
||||
for (env = default_environment; *env; env = nxt + 1) {
|
||||
char *val;
|
||||
|
||||
for (nxt = env; *nxt; ++nxt) {
|
||||
if (nxt >= &default_environment[ENV_SIZE]) {
|
||||
fprintf(stderr, "## Error: "
|
||||
"default environment not terminated\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
val = envmatch(name, env);
|
||||
if (!val)
|
||||
continue;
|
||||
return val;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the current definition of one, or more, or all
|
||||
* environment variables
|
||||
@ -281,6 +308,7 @@ int fw_env_write(char *name, char *value)
|
||||
int len;
|
||||
char *env, *nxt;
|
||||
char *oldval = NULL;
|
||||
int deleting, creating, overwriting;
|
||||
|
||||
/*
|
||||
* search if variable with this name already exists
|
||||
@ -298,27 +326,49 @@ int fw_env_write(char *name, char *value)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete any existing definition
|
||||
*/
|
||||
if (oldval) {
|
||||
#ifndef CONFIG_ENV_OVERWRITE
|
||||
/*
|
||||
* Ethernet Address and serial# can be set only once
|
||||
*/
|
||||
if (
|
||||
(strcmp(name, "serial#") == 0) ||
|
||||
((strcmp(name, "ethaddr") == 0)
|
||||
#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
|
||||
&& (strcmp(oldval, __stringify(CONFIG_ETHADDR)) != 0)
|
||||
#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
|
||||
) ) {
|
||||
fprintf (stderr, "Can't overwrite \"%s\"\n", name);
|
||||
deleting = (oldval && !(value && strlen(value)));
|
||||
creating = (!oldval && (value && strlen(value)));
|
||||
overwriting = (oldval && (value && strlen(value)));
|
||||
|
||||
/* check for permission */
|
||||
if (deleting) {
|
||||
if (env_flags_validate_varaccess(name,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_DELETE)) {
|
||||
printf("Can't delete \"%s\"\n", name);
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_ENV_OVERWRITE */
|
||||
} else if (overwriting) {
|
||||
if (env_flags_validate_varaccess(name,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_OVERWR)) {
|
||||
printf("Can't overwrite \"%s\"\n", name);
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
} else if (env_flags_validate_varaccess(name,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR)) {
|
||||
const char *defval = fw_getdefenv(name);
|
||||
|
||||
if (defval == NULL)
|
||||
defval = "";
|
||||
if (strcmp(oldval, defval)
|
||||
!= 0) {
|
||||
printf("Can't overwrite \"%s\"\n", name);
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (creating) {
|
||||
if (env_flags_validate_varaccess(name,
|
||||
ENV_FLAGS_VARACCESS_PREVENT_CREATE)) {
|
||||
printf("Can't create \"%s\"\n", name);
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
/* Nothing to do */
|
||||
return 0;
|
||||
|
||||
if (deleting || overwriting) {
|
||||
if (*++nxt == '\0') {
|
||||
*env = '\0';
|
||||
} else {
|
||||
@ -395,6 +445,9 @@ int fw_setenv(int argc, char *argv[])
|
||||
|
||||
name = argv[1];
|
||||
|
||||
if (env_flags_validate_env_set_params(argc, argv) < 0)
|
||||
return 1;
|
||||
|
||||
len = 0;
|
||||
for (i = 2; i < argc; ++i) {
|
||||
char *val = argv[i];
|
||||
@ -516,6 +569,11 @@ int fw_parse_script(char *fname)
|
||||
name, val ? val : " removed");
|
||||
#endif
|
||||
|
||||
if (env_flags_validate_type(name, val) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is an error setting a variable,
|
||||
* try to save the environment and returns an error
|
||||
|
@ -80,7 +80,7 @@ static int fit_handle_file (struct mkimage_params *params)
|
||||
}
|
||||
sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
|
||||
|
||||
/* dtc -I dts -O -p 200 datafile > tmpfile */
|
||||
/* dtc -I dts -O dtb -p 500 datafile > tmpfile */
|
||||
sprintf (cmd, "%s %s %s > %s",
|
||||
MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
|
||||
debug ("Trying to execute \"%s\"\n", cmd);
|
||||
|
Loading…
Reference in New Issue
Block a user