Merge remote-tracking branch 'origin/master'

This commit is contained in:
Scott Wood 2012-12-14 16:03:55 -06:00
commit 88c5c68ffa
99 changed files with 5071 additions and 848 deletions

105
README
View File

@ -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:
=====================

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -35,6 +35,7 @@ enum mxc_clock {
MXC_SSP1_CLK,
MXC_SSP2_CLK,
MXC_SSP3_CLK,
MXC_XTAL_CLK,
};
enum mxs_ioclock {

View File

@ -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));

View File

@ -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 *);

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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");

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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)

View File

@ -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; */

View File

@ -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; */

View File

@ -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)) {

View File

@ -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;

View File

@ -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 ... ");

View File

@ -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))

View File

@ -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

View File

@ -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
View 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
View 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
View 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

View File

@ -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
View 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");

View File

@ -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
View 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"
);

View File

@ -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,

View File

@ -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);

View File

@ -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"
);

View File

@ -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
View 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
View 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
View 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);

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
View 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;
}

View File

@ -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)
{

View File

@ -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++;

View File

@ -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;
}

View File

@ -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
View 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.

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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>

View File

@ -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.

View File

@ -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_ */

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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
View 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
View 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
View 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__ */

View File

@ -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
View 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__ */

View File

@ -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_ */

View File

@ -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
View 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

View File

@ -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);

View 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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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
View 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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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) {

View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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);