commit
88c5c68ffa
@ -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" |
||||||
|
); |
@ -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" |
||||||
|
); |
@ -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 |
@ -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"); |
@ -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" |
||||||
|
); |
@ -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"); |
||||||
|
} |
@ -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; |
||||||
|
} |
@ -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); |
@ -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 |
@ -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; |
||||||
|
} |
@ -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. |
@ -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_ */ |
@ -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__ */ |
@ -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__ */ |
@ -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__ */ |
@ -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 |
@ -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 |
@ -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; |
||||||
|
} |
Loading…
Reference in new issue