summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeer Chen <pchen@nvidia.com>2011-02-24 09:29:23 -0800
committerAnton Staaf <robotboy@chromium.org>2011-02-24 09:29:23 -0800
commit7557d9b11c1aaacdaf531cc38dd4848a36782575 (patch)
treeabc81c6e7b98359f57f250df84e6192fe10d614a
parent52be3bf067653db932e42a2e304a083448774924 (diff)
downloadnvidia-cbootimage-7557d9b11c1aaacdaf531cc38dd4848a36782575.tar.gz
Add the device type/parameters support for cbootimage tool.
Add the bct generated function for cbootimage tool. Change-Id: I2ad282d7dbce1d06d54fa3ee2ef5f550598089b0 BUG=None. TEST=Test using the cfg file. Review URL: http://codereview.chromium.org/6579034 Patch from Peer Chen <pchen@nvidia.com>.
-rw-r--r--GNUmakefile2
-rw-r--r--cbootimage.c20
-rw-r--r--cbootimage.h1
-rw-r--r--nvbctlib.h102
-rw-r--r--nvbctlib_ap20.c89
-rw-r--r--nvboot_bct.h142
-rw-r--r--parse.c299
-rw-r--r--parse.h76
-rw-r--r--set.c118
-rw-r--r--set.h12
10 files changed, 797 insertions, 64 deletions
diff --git a/GNUmakefile b/GNUmakefile
index f5b1e51..9a2fbf1 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -12,7 +12,7 @@ OBJS := $(patsubst %.c,%.o,$(notdir $(C_FILES)))
TARGET = cbootimage
CC = gcc
-CFLAGS=-Wall -O
+CFLAGS=-Wall -O -lm
$(TARGET):$(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(CFLAGS)
diff --git a/cbootimage.c b/cbootimage.c
index 1792749..1df6238 100644
--- a/cbootimage.c
+++ b/cbootimage.c
@@ -59,6 +59,7 @@ usage(void)
printf(" options:\n");
printf(" -h, --help, -? Display this message.\n");
printf(" -d, --debug Output debugging information.\n");
+ printf(" -gbct Generate the new bct file.\n");
printf(" configfile File with configuration information\n");
printf(" imagename Output image name\n");
}
@@ -68,6 +69,8 @@ process_command_line(int argc, char *argv[], build_image_context *context)
{
int arg = 1;
+ context->generate_bct = 0;
+
while (arg < argc) {
/* Process the next argument. */
if (!strcmp(argv[arg], "-h") ||
@@ -80,6 +83,9 @@ process_command_line(int argc, char *argv[], build_image_context *context)
!strcmp(argv[arg], "--debug")) {
enable_debug = 1;
arg++;
+ } else if (!strcmp(argv[arg], "-gbct")) {
+ context->generate_bct = 1;
+ arg++;
} else if (argv[arg][0] == '-') {
printf("Illegal option %s\n", argv[arg]);
usage();
@@ -168,6 +174,20 @@ main(int argc, char *argv[])
/* Parse & process the contents of the config file. */
process_config_file(&context);
+ /* Generate the new bct file */
+ if (context.generate_bct != 0) {
+ /* Signing the bct. */
+ e = sign_bct(&context, context.bct);
+ if (e != 0)
+ printf("Signing BCT failed, error: %d.\n", e);
+
+ fwrite(context.bct, 1, sizeof(nvboot_config_table),
+ context.raw_file);
+ printf("New BCT file %s has been successfully generated!\n",
+ context.image_filename);
+ goto fail;
+ }
+
/* Update the bct file */
/* Update the add on file */
e = update_addon_item(&context);
diff --git a/cbootimage.h b/cbootimage.h
index 41c9baf..173e76a 100644
--- a/cbootimage.h
+++ b/cbootimage.h
@@ -111,6 +111,7 @@ typedef struct build_image_context_rec
u_int32_t newbl_load_addr;
u_int32_t newbl_entry_point;
u_int32_t newbl_attr;
+ u_int8_t generate_bct;
u_int8_t *bct;
struct addon_table_rec addon_tbl;
diff --git a/nvbctlib.h b/nvbctlib.h
index 6613fe0..279fc0f 100644
--- a/nvbctlib.h
+++ b/nvbctlib.h
@@ -42,40 +42,66 @@
* constants.
*/
typedef enum {
- nvbct_lib_id_none = 0,
-
- nvbct_lib_id_crypto_hash,
- nvbct_lib_id_random_aes_blk,
- nvbct_lib_id_boot_data_version,
- nvbct_lib_id_block_size_log2,
- nvbct_lib_id_page_size_log2,
- nvbct_lib_id_partition_size,
- nvbct_lib_id_bootloader_used,
- nvbct_lib_id_bootloaders_max,
- nvbct_lib_id_reserved,
- nvbct_lib_id_reserved_size,
- nvbct_lib_id_reserved_offset,
- nvbct_lib_id_bct_size,
- nvbct_lib_id_hash_size,
- nvbct_lib_id_crypto_offset,
- nvbct_lib_id_crypto_length,
- nvbct_lib_id_max_bct_search_blks,
-
- nvbct_lib_id_bl_version,
- nvbct_lib_id_bl_start_blk,
- nvbct_lib_id_bl_start_page,
- nvbct_lib_id_bl_length,
- nvbct_lib_id_bl_load_addr,
- nvbct_lib_id_bl_entry_point,
- nvbct_lib_id_bl_attribute,
- nvbct_lib_id_bl_crypto_hash,
-
- nvbct_lib_id_max,
-
- nvbct_lib_id_force32 = 0x7fffffff
+ nvbct_lib_id_none = 0,
+
+ nvbct_lib_id_crypto_hash,
+ nvbct_lib_id_random_aes_blk,
+ nvbct_lib_id_boot_data_version,
+ nvbct_lib_id_block_size_log2,
+ nvbct_lib_id_page_size_log2,
+ nvbct_lib_id_partition_size,
+ nvbct_lib_id_dev_type,
+ nvbct_lib_id_bootloader_used,
+ nvbct_lib_id_bootloaders_max,
+ nvbct_lib_id_reserved,
+ nvbct_lib_id_reserved_size,
+ nvbct_lib_id_reserved_offset,
+ nvbct_lib_id_bct_size,
+ nvbct_lib_id_hash_size,
+ nvbct_lib_id_crypto_offset,
+ nvbct_lib_id_crypto_length,
+ nvbct_lib_id_max_bct_search_blks,
+ nvbct_lib_id_num_param_sets,
+ nvbct_lib_id_dev_type_sdmmc,
+ nvbct_lib_id_dev_type_spi,
+
+ nvbct_lib_id_sdmmc_clock_divider,
+ nvbct_lib_id_sdmmc_data_width,
+ nvbct_lib_id_sdmmc_max_power_class_supported,
+ nvbct_lib_id_spiflash_read_command_type_fast,
+ nvbct_lib_id_spiflash_clock_source,
+ nvbct_lib_id_spiflash_clock_divider,
+ nvbct_lib_id_sdmmc_data_width_4bit,
+ nvbct_lib_id_sdmmc_data_width_8bit,
+ nvbct_lib_id_spi_clock_source_pllp_out0,
+ nvbct_lib_id_spi_clock_source_pllc_out0,
+ nvbct_lib_id_spi_clock_source_pllm_out0,
+ nvbct_lib_id_spi_clock_source_clockm,
+
+ nvbct_lib_id_bl_version,
+ nvbct_lib_id_bl_start_blk,
+ nvbct_lib_id_bl_start_page,
+ nvbct_lib_id_bl_length,
+ nvbct_lib_id_bl_load_addr,
+ nvbct_lib_id_bl_entry_point,
+ nvbct_lib_id_bl_attribute,
+ nvbct_lib_id_bl_crypto_hash,
+
+ nvbct_lib_id_max,
+
+ nvbct_lib_id_force32 = 0x7fffffff
} nvbct_lib_id;
+typedef int (*nvbct_lib_get_dev_param)(u_int32_t set,
+ nvbct_lib_id id,
+ u_int32_t *data,
+ u_int8_t *bct);
+typedef int (*nvbct_lib_set_dev_param)(u_int32_t set,
+ nvbct_lib_id id,
+ u_int32_t data,
+ u_int8_t *bct);
+
typedef int (*nvbct_lib_get_bl_param)(u_int32_t set,
nvbct_lib_id id,
u_int32_t *data,
@@ -110,15 +136,17 @@ typedef int (*nvbct_lib_set_data)(nvbct_lib_id id,
*/
typedef struct nvbct_lib_fns_rec
{
- nvbct_lib_get_value get_value;
- nvbct_lib_set_value set_value;
+ nvbct_lib_get_value get_value;
+ nvbct_lib_set_value set_value;
- nvbct_lib_get_data get_data;
- nvbct_lib_set_data set_data;
+ nvbct_lib_get_data get_data;
+ nvbct_lib_set_data set_data;
- nvbct_lib_get_bl_param getbl_param;
- nvbct_lib_set_bl_param setbl_param;
+ nvbct_lib_get_bl_param getbl_param;
+ nvbct_lib_set_bl_param setbl_param;
+ nvbct_lib_get_dev_param getdev_param;
+ nvbct_lib_set_dev_param setdev_param;
} nvbct_lib_fns;
void nvbct_lib_get_fns(nvbct_lib_fns *fns);
diff --git a/nvbctlib_ap20.c b/nvbctlib_ap20.c
index 2535432..2f803b5 100644
--- a/nvbctlib_ap20.c
+++ b/nvbctlib_ap20.c
@@ -28,6 +28,16 @@
/* nvbctlib_ap20.c: The implementation of the nvbctlib API for AP20. */
/* Definitions that simplify the code which follows. */
+#define CASE_GET_DEV_PARAM(dev, x) \
+case nvbct_lib_id_##dev##_##x:\
+ *data = bct_ptr->dev_params[set].dev##_params.x; \
+ break
+
+#define CASE_SET_DEV_PARAM(dev, x) \
+case nvbct_lib_id_##dev##_##x:\
+ bct_ptr->dev_params[set].dev##_params.x = data; \
+ break
+
#define CASE_GET_BL_PARAM(x) \
case nvbct_lib_id_bl_##x:\
*data = bct_ptr->bootloader[set].x; \
@@ -51,7 +61,7 @@ case nvbct_lib_id_##id:\
#define CASE_GET_CONST_PREFIX(id, val_prefix) \
case nvbct_lib_id_##id:\
- *data = val_prefix##id; \
+ *data = val_prefix##_##id; \
break
#define CASE_SET_NVU32(id) \
@@ -72,6 +82,68 @@ case nvbct_lib_id_##id:\
memcpy(&(bct_ptr->id), data, size); \
break
+static int
+getdev_param(u_int32_t set,
+ nvbct_lib_id id,
+ u_int32_t *data,
+ u_int8_t *bct)
+{
+ nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
+
+ if (data == NULL || bct == NULL)
+ return -ENODATA;
+
+ switch (id) {
+ CASE_GET_DEV_PARAM(sdmmc, clock_divider);
+ CASE_GET_DEV_PARAM(sdmmc, data_width);
+ CASE_GET_DEV_PARAM(sdmmc, max_power_class_supported);
+
+ CASE_GET_DEV_PARAM(spiflash, clock_source);
+ CASE_GET_DEV_PARAM(spiflash, clock_divider);
+ CASE_GET_DEV_PARAM(spiflash, read_command_type_fast);
+
+ case nvbct_lib_id_dev_type:
+ *data = bct_ptr->dev_type[set];
+ break;
+
+ default:
+ return -ENODATA;
+ }
+
+ return 0;
+}
+
+static int
+setdev_param(u_int32_t set,
+ nvbct_lib_id id,
+ u_int32_t data,
+ u_int8_t *bct)
+{
+ nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
+
+ if (bct == NULL)
+ return -ENODATA;
+
+ switch (id) {
+ CASE_SET_DEV_PARAM(sdmmc, clock_divider);
+ CASE_SET_DEV_PARAM(sdmmc, data_width);
+ CASE_SET_DEV_PARAM(sdmmc, max_power_class_supported);
+
+ CASE_SET_DEV_PARAM(spiflash, clock_source);
+ CASE_SET_DEV_PARAM(spiflash, clock_divider);
+ CASE_SET_DEV_PARAM(spiflash, read_command_type_fast);
+
+ case nvbct_lib_id_dev_type:
+ bct_ptr->dev_type[set] = data;
+ break;
+
+ default:
+ return -ENODATA;
+ }
+
+ return 0;
+
+}
static int
getbl_param(u_int32_t set,
@@ -166,6 +238,7 @@ bct_get_value(nvbct_lib_id id, u_int32_t *data, u_int8_t *bct)
CASE_GET_NVU32(block_size_log2);
CASE_GET_NVU32(page_size_log2);
CASE_GET_NVU32(partition_size);
+ CASE_GET_NVU32(num_param_sets);
CASE_GET_NVU32(bootloader_used);
/*
@@ -199,6 +272,15 @@ bct_get_value(nvbct_lib_id id, u_int32_t *data, u_int8_t *bct)
CASE_GET_CONST(max_bct_search_blks, NVBOOT_MAX_BCT_SEARCH_BLOCKS);
+ CASE_GET_CONST_PREFIX(dev_type_sdmmc, nvboot);
+ CASE_GET_CONST_PREFIX(dev_type_spi, nvboot);
+ CASE_GET_CONST_PREFIX(sdmmc_data_width_4bit, nvboot);
+ CASE_GET_CONST_PREFIX(sdmmc_data_width_8bit, nvboot);
+ CASE_GET_CONST_PREFIX(spi_clock_source_pllp_out0, nvboot);
+ CASE_GET_CONST_PREFIX(spi_clock_source_pllc_out0, nvboot);
+ CASE_GET_CONST_PREFIX(spi_clock_source_pllm_out0, nvboot);
+ CASE_GET_CONST_PREFIX(spi_clock_source_clockm, nvboot);
+
default:
return -ENODATA;
}
@@ -221,6 +303,7 @@ bct_set_value(nvbct_lib_id id, u_int32_t data, u_int8_t *bct)
CASE_SET_NVU32(block_size_log2);
CASE_SET_NVU32(page_size_log2);
CASE_SET_NVU32(partition_size);
+ CASE_SET_NVU32(num_param_sets);
CASE_SET_NVU32(bootloader_used);
default:
@@ -279,4 +362,8 @@ nvbct_lib_get_fns(nvbct_lib_fns *fns)
fns->getbl_param = getbl_param;
fns->setbl_param = setbl_param;
+
+ fns->getdev_param = getdev_param;
+ fns->setdev_param = setdev_param;
+
}
diff --git a/nvboot_bct.h b/nvboot_bct.h
index 734ed3b..75ffb42 100644
--- a/nvboot_bct.h
+++ b/nvboot_bct.h
@@ -46,7 +46,13 @@
*/
#define NVBOOT_MAX_BOOTLOADERS 4
-#define NVBOOT_BCT_USED_DATA_SIZE 534
+#define NVBOOT_BCT_USED_DATA_SIZE 2052
+
+/**
+ * Defines the maximum number of device parameter sets in the BCT.
+ * The value must be equal to (1 << # of device straps)
+ */
+#define NVBOOT_BCT_MAX_PARAM_SETS 4
/**
* Defines the number of entries (bits) in the bad block table.
@@ -93,6 +99,135 @@ typedef struct nvboot_hash_rec
u_int32_t hash[NVBOOT_CMAC_AES_HASH_LENGTH];
} nvboot_hash;
+/// Defines various data widths supported.
+typedef enum
+{
+ /**
+ * Specifies a 1 bit interface to eMMC.
+ * Note that 1-bit data width is only for the driver's internal use.
+ * Fuses doesn't provide option to select 1-bit data width.
+ * The driver selects 1-bit internally based on need.
+ * It is used for reading Extended CSD and when the power class
+ * requirements of a card for 4-bit or 8-bit transfers are not
+ * supported by the target board.
+ */
+ nvboot_sdmmc_data_width_1bit = 0,
+
+ /// Specifies a 4 bit interface to eMMC.
+ nvboot_sdmmc_data_width_4bit = 1,
+
+ /// Specifies a 8 bit interface to eMMC.
+ nvboot_sdmmc_data_width_8bit = 2,
+
+ nvboot_sdmmc_data_width_num,
+ nvboot_sdmmc_data_width_force32 = 0x7FFFFFFF
+} nvboot_sdmmc_data_width;
+
+/// Defines the parameters that can be changed after BCT is read.
+typedef struct nvboot_sdmmc_params_rec
+{
+ /**
+ * Specifies the clock divider for the SDMMC controller's clock source,
+ * which is PLLP running at 432MHz. If it is set to 18, then the SDMMC
+ * controller runs at 432/18 = 24MHz.
+ */
+ u_int8_t clock_divider;
+
+ /// Specifies the data bus width. Supported data widths are 4/8 bits.
+ nvboot_sdmmc_data_width data_width;
+
+ /**
+ * Max Power class supported by the target board.
+ * The driver determines the best data width and clock frequency
+ * supported within the power class range (0 to Max) if the selected
+ * data width cannot be used at the chosen clock frequency.
+ */
+ u_int8_t max_power_class_supported;
+ u_int32_t reserved;
+} nvboot_sdmmc_params;
+
+typedef enum
+{
+ /// Specifies SPI clock source to be PLLP.
+ nvboot_spi_clock_source_pllp_out0 = 0,
+
+ /// Specifies SPI clock source to be PLLC.
+ nvboot_spi_clock_source_pllc_out0,
+
+ /// Specifies SPI clock source to be PLLM.
+ nvboot_spi_clock_source_pllm_out0,
+
+ /// Specifies SPI clock source to be ClockM.
+ nvboot_spi_clock_source_clockm,
+
+ nvboot_spi_clock_source_num,
+ nvboot_spi_clock_source_force32 = 0x7FFFFFF
+} nvboot_spi_clock_source;
+
+
+/**
+ * Defines the parameters SPI FLASH devices.
+ */
+typedef struct nvboot_spiflash_params_rec
+{
+ /**
+ * Specifies the clock source to use.
+ */
+ nvboot_spi_clock_source clock_source;
+
+ /**
+ * Specifes the clock divider to use.
+ * The value is a 7-bit value based on an input clock of 432Mhz.
+ * Divider = (432+ DesiredFrequency-1)/DesiredFrequency;
+ * Typical values:
+ * NORMAL_READ at 20MHz: 22
+ * FAST_READ at 33MHz: 14
+ * FAST_READ at 40MHz: 11
+ * FAST_READ at 50MHz: 9
+ */
+ u_int8_t clock_divider;
+
+ /**
+ * Specifies the type of command for read operations.
+ * NV_FALSE specifies a NORMAL_READ Command
+ * NV_TRUE specifies a FAST_READ Command
+ */
+ u_int8_t read_command_type_fast;
+} nvboot_spiflash_params;
+
+/**
+* Defines the union of the parameters required by each device.
+*/
+typedef union{
+ /// Specifies optimized parameters for eMMC and eSD
+ nvboot_sdmmc_params sdmmc_params;
+ /// Specifies optimized parameters for SPI NOR
+ nvboot_spiflash_params spiflash_params;
+} nvboot_dev_params;
+
+/**
+ * Identifies the types of devices from which the system booted.
+ * Used to identify primary and secondary boot devices.
+ * @note These no longer match the fuse API device values (for
+ * backward compatibility with AP15).
+ */
+typedef enum
+{
+ /// Specifies a default (unset) value.
+ nvboot_dev_type_none = 0,
+
+ /// Specifies SPI NOR.
+ nvboot_dev_type_spi = 3,
+
+ /// Specifies SDMMC (either eMMC or eSD).
+ nvboot_dev_type_sdmmc,
+
+ nvboot_dev_type_max,
+
+ /// Ignore -- Forces compilers to make 32-bit enums.
+ nvboot_dev_type_force32 = 0x7FFFFFFF
+ } nvboot_dev_type;
+
/**
* Stores information needed to locate and verify a boot loader.
*
@@ -138,7 +273,10 @@ typedef struct nvboot_config_table_rec
u_int32_t block_size_log2;
u_int32_t page_size_log2;
u_int32_t partition_size;
- u_int32_t bct_used_data[NVBOOT_BCT_USED_DATA_SIZE];
+ u_int32_t num_param_sets;
+ nvboot_dev_type dev_type[NVBOOT_BCT_MAX_PARAM_SETS];
+ nvboot_dev_params dev_params[NVBOOT_BCT_MAX_PARAM_SETS];
+ u_int8_t bct_used_data[NVBOOT_BCT_USED_DATA_SIZE];
nvboot_badblock_table badblock_table;
u_int32_t bootloader_used;
nv_bootloader_info bootloader[NVBOOT_MAX_BOOTLOADERS];
diff --git a/parse.c b/parse.c
index e52648a..b0c396d 100644
--- a/parse.c
+++ b/parse.c
@@ -52,7 +52,19 @@
*/
static char *parse_u32(char *statement, u_int32_t *val);
+static char *parse_u8(char *statement, u_int32_t *val);
static char *parse_filename(char *statement, char *name, int chars_remaining);
+static char *parse_enum(build_image_context *context,
+ char *statement,
+ enum_item *table,
+ u_int32_t *val);
+static char
+*parse_field_name(char *rest, field_item *field_table, field_item **field);
+static char
+*parse_field_value(build_image_context *context,
+ char *rest,
+ field_item *field,
+ u_int32_t *value);
static int
parse_array(build_image_context *context, parse_token token, char *rest);
static int
@@ -66,13 +78,111 @@ parse_addon(build_image_context *context, parse_token token, char *rest);
static char *parse_string(char *statement, char *uname, int chars_remaining);
static char
*parse_end_state(char *statement, char *uname, int chars_remaining);
+static int
+parse_dev_param(build_image_context *context, parse_token token, char *rest);
+
static int process_statement(build_image_context *context, char *statement);
+static enum_item s_devtype_table[] =
+{
+ { "NvBootDevType_Sdmmc", nvbct_lib_id_dev_type_sdmmc },
+ { "NvBootDevType_Spi", nvbct_lib_id_dev_type_spi },
+ { "Sdmmc", nvbct_lib_id_dev_type_sdmmc },
+ { "Spi", nvbct_lib_id_dev_type_spi },
+
+ { NULL, 0 }
+};
+
+static enum_item s_sdmmc_data_width_table[] =
+{
+ {
+ "NvBootSdmmcDataWidth_4Bit",
+ nvbct_lib_id_sdmmc_data_width_4bit
+ },
+ {
+ "NvBootSdmmcDataWidth_8Bit",
+ nvbct_lib_id_sdmmc_data_width_8bit
+ },
+ { "4Bit", nvbct_lib_id_sdmmc_data_width_4bit },
+ { "8Bit", nvbct_lib_id_sdmmc_data_width_8bit },
+ { NULL, 0 }
+};
+
+static enum_item s_spi_clock_source_table[] =
+{
+ {
+ "NvBootSpiClockSource_PllPOut0",
+ nvbct_lib_id_spi_clock_source_pllp_out0
+ },
+ {
+ "NvBootSpiClockSource_PllCOut0",
+ nvbct_lib_id_spi_clock_source_pllc_out0
+ },
+ {
+ "NvBootSpiClockSource_PllMOut0",
+ nvbct_lib_id_spi_clock_source_pllm_out0
+ },
+ {
+ "NvBootSpiClockSource_ClockM",
+ nvbct_lib_id_spi_clock_source_clockm
+ },
+
+ { "ClockSource_PllPOut0", nvbct_lib_id_spi_clock_source_pllp_out0 },
+ { "ClockSource_PllCOut0", nvbct_lib_id_spi_clock_source_pllc_out0 },
+ { "ClockSource_PllMOut0", nvbct_lib_id_spi_clock_source_pllm_out0 },
+ { "ClockSource_ClockM", nvbct_lib_id_spi_clock_source_clockm },
+
+
+ { "PllPOut0", nvbct_lib_id_spi_clock_source_pllp_out0 },
+ { "PllCOut0", nvbct_lib_id_spi_clock_source_pllc_out0 },
+ { "PllMOut0", nvbct_lib_id_spi_clock_source_pllm_out0 },
+ { "ClockM", nvbct_lib_id_spi_clock_source_clockm },
+
+ { NULL, 0 }
+};
+
+static field_item s_sdmmc_table[] =
+{
+ { "ClockDivider", token_clock_divider, field_type_u32, NULL },
+ { "DataWidth", token_data_width,
+ field_type_enum, s_sdmmc_data_width_table },
+ { "MaxPowerClassSupported", token_max_power_class_supported,
+ field_type_u32, NULL },
+
+ { NULL, 0, 0, NULL }
+};
+
+static field_item s_spiflash_table[] =
+{
+ { "ReadCommandTypeFast", token_read_command_type_fast,
+ field_type_u8, NULL },
+ { "ClockDivider", token_clock_divider, field_type_u8, NULL },
+ { "ClockSource", token_clock_source,
+ field_type_enum, s_spi_clock_source_table },
+
+ { NULL, 0, 0, NULL }
+};
+
+static parse_subfield_item s_device_type_table[] =
+{
+ { "SdmmcParams.", token_sdmmc_params,
+ s_sdmmc_table, set_sdmmc_param },
+ { "SpiFlashParams.", token_spiflash_params,
+ s_spiflash_table, set_spiflash_param },
+
+ { NULL, 0, NULL }
+};
+
static parse_item s_top_level_items[] =
{
{ "Bctfile=", token_bct_file, parse_bct_file },
{ "Attribute=", token_attribute, parse_value_u32 },
{ "Attribute[", token_attribute, parse_array },
+ { "PageSize=", token_page_size, parse_value_u32 },
+ { "BlockSize=", token_block_size, parse_value_u32 },
+ { "PartitionSize=", token_partition_size, parse_value_u32 },
+ { "DevType[", token_dev_type, parse_array },
+ { "DeviceParam[", token_dev_param, parse_dev_param },
{ "BootLoader=", token_bootloader, parse_bootloader },
{ "Redundancy=", token_redundancy, parse_value_u32 },
{ "Version=", token_version, parse_value_u32 },
@@ -120,6 +230,23 @@ parse_u32(char *statement, u_int32_t *val)
return statement;
}
+char *
+parse_u8(char *statement, u_int32_t *val)
+{
+ char *retval;
+
+ retval = parse_u32(statement, val);
+
+ if (*val > 0xff) {
+ printf("Warning: Parsed 8-bit value that exceeded 8-bits.\n");
+ printf(" Parsed value = %d. Remaining text = %s\n",
+ *val, retval);
+ }
+
+ return retval;
+}
+
+
/* This parsing code was initially borrowed from nvcamera_config_parse.c. */
/* Returns the address of the character after the parsed data. */
static char *
@@ -152,6 +279,100 @@ parse_filename(char *statement, char *name, int chars_remaining)
return statement;
}
+static char
+*parse_field_name(char *rest, field_item *field_table, field_item **field)
+{
+ u_int32_t i;
+ u_int32_t field_name_len = 0;
+
+ assert(field_table != NULL);
+ assert(rest != NULL);
+ assert(field != NULL);
+
+ while(*(rest + field_name_len) != '=')
+ field_name_len++;
+
+ /* Parse the field name. */
+ for (i = 0; field_table[i].name != NULL; i++) {
+ if ((strlen(field_table[i].name) == field_name_len) &&
+ !strncmp(field_table[i].name,
+ rest,
+ field_name_len)) {
+
+ *field = &(field_table[i]);
+ rest = rest + field_name_len;
+ return rest;
+ }
+ }
+
+ /* Field wasn't found or a parse error occurred. */
+ return NULL;
+}
+
+static char
+*parse_field_value(build_image_context *context,
+ char *rest,
+ field_item *field,
+ u_int32_t *value)
+{
+ assert(rest != NULL);
+ assert(field != NULL);
+ assert((field->type != field_type_enum)
+ || (field->enum_table != NULL));
+
+ switch (field->type) {
+ case field_type_enum:
+ rest = parse_enum(context, rest, field->enum_table, value);
+ break;
+
+ case field_type_u32:
+ rest = parse_u32(rest, value);
+ break;
+
+ case field_type_u8:
+ rest = parse_u8(rest, value);
+ break;
+
+ default:
+ printf("Unexpected field type %d at line %d\n",
+ field->type, __LINE__);
+ rest = NULL;
+ break;
+ }
+
+ return rest;
+}
+
+static char *
+parse_enum(build_image_context *context,
+ char *statement,
+ enum_item *table,
+ u_int32_t *val)
+{
+ int i;
+ char *rest;
+ int e;
+
+ for (i = 0; table[i].name != NULL; i++) {
+ if (!strncmp(table[i].name, statement,
+ strlen(table[i].name))) {
+ /* Lookup the correct value for the token. */
+ e = context->bctlib.get_value(table[i].value,
+ val, context->bct);
+ if (e) {
+ printf("Error looking up token %d.\n", table[i].value);
+ printf("\"%s\" is not valid for this chip.\n",
+ table[i].name);
+ *val = -1;
+ }
+
+ rest = statement + strlen(table[i].name);
+ return rest;
+ }
+ }
+ return parse_u32(statement, val);
+
+}
/*
* parse_bootloader(): Processes commands to set a bootloader.
*/
@@ -167,6 +388,8 @@ static int parse_bootloader(build_image_context *context,
assert(context != NULL);
assert(rest != NULL);
+ if (context->generate_bct != 0)
+ return 0;
/* Parse the file name. */
rest = parse_filename(rest, filename, MAX_BUFFER);
if (rest == NULL)
@@ -228,13 +451,16 @@ parse_array(build_image_context *context, parse_token token, char *rest)
/* Parse the value based on the field table. */
switch(token) {
- case token_attribute:
- rest = parse_u32(rest, &value);
- break;
-
- default:
- /* Unknown token */
- return 1;
+ case token_attribute:
+ rest = parse_u32(rest, &value);
+ break;
+ case token_dev_type:
+ rest = parse_enum(context, rest, s_devtype_table, &value);
+ break;
+
+ default:
+ /* Unknown token */
+ return 1;
}
if (rest == NULL)
@@ -394,6 +620,65 @@ parse_addon(build_image_context *context, parse_token token, char *rest)
return 0;
}
+static int
+parse_dev_param(build_image_context *context, parse_token token, char *rest)
+{
+ u_int32_t i;
+ u_int32_t value;
+ field_item *field;
+ u_int32_t index;
+ parse_subfield_item *device_item = NULL;
+
+ assert(context != NULL);
+ assert(rest != NULL);
+
+ /* Parse the index. */
+ rest = parse_u32(rest, &index);
+ if (rest == NULL)
+ return 1;
+
+ /* Parse the closing bracket. */
+ if (*rest != ']')
+ return 1;
+ rest++;
+
+ /* Parse the following '.' */
+ if (*rest != '.')
+ return 1;
+ rest++;
+
+ /* Parse the device name. */
+ for (i = 0; s_device_type_table[i].prefix != NULL; i++) {
+ if (!strncmp(s_device_type_table[i].prefix,
+ rest, strlen(s_device_type_table[i].prefix))) {
+
+ device_item = &(s_device_type_table[i]);
+ rest = rest + strlen(s_device_type_table[i].prefix);
+
+ /* Parse the field name. */
+ rest = parse_field_name(rest,
+ s_device_type_table[i].field_table,
+ &field);
+ if (rest == NULL)
+ return 1;
+
+ /* Parse the equals sign.*/
+ if (*rest != '=')
+ return 1;
+ rest++;
+
+ /* Parse the value based on the field table. */
+ rest = parse_field_value(context, rest, field, &value);
+ if (rest == NULL)
+ return 1;
+ return device_item->process(context,
+ index, field->token, value);
+ }
+ }
+
+ return 1;
+
+}
/* Return 0 on success, 1 on error */
static int
process_statement(build_image_context *context, char *statement)
diff --git a/parse.h b/parse.h
index 457b546..f2e8ad6 100644
--- a/parse.h
+++ b/parse.h
@@ -41,28 +41,76 @@
typedef enum
{
- token_none = 0,
- token_attribute,
- token_bootloader,
- token_page_size,
- token_redundancy,
- token_version,
- token_bct_file,
- token_addon,
-
- token_force32 = 0x7fffffff
+ token_none = 0,
+ token_attribute,
+ token_bootloader,
+ token_block_size,
+ token_page_size,
+ token_partition_size,
+ token_dev_type,
+ token_dev_param,
+ token_redundancy,
+ token_version,
+ token_bct_file,
+ token_addon,
+ token_sdmmc_params,
+ token_spiflash_params,
+ token_data_width,
+ token_clock_divider,
+ token_clock_source,
+ token_read_command_type_fast,
+ token_max_power_class_supported,
+
+ token_force32 = 0x7fffffff
} parse_token;
+typedef enum
+{
+ field_type_none = 0,
+ field_type_enum,
+ field_type_u32,
+ field_type_u8,
+ field_type_force32 = 0x7fffffff
+} field_type;
+
/* Forward declarations */
typedef int (*process_function)(build_image_context *context,
parse_token token,
- char *Remiainder);
+ char *remainder);
+
+typedef int (*process_subfield_function)(build_image_context *context,
+ u_int32_t index,
+ parse_token token,
+ u_int32_t value);
+
+
+typedef struct
+{
+ char *name;
+ u_int32_t value;
+} enum_item;
+
+typedef struct
+{
+ char *name;
+ u_int32_t token;
+ field_type type;
+ enum_item *enum_table;
+} field_item;
+
+typedef struct
+{
+ char *prefix;
+ parse_token token;
+ field_item *field_table;
+ process_subfield_function process;
+} parse_subfield_item;
typedef struct
{
- char *prefix;
- parse_token token;
- process_function process;
+ char *prefix;
+ parse_token token;
+ process_function process;
} parse_item;
/*
diff --git a/set.c b/set.c
index 14fe214..e8ea259 100644
--- a/set.c
+++ b/set.c
@@ -24,6 +24,7 @@
* set.c - State setting support for the cbootimage tool
*/
+#include <math.h>
#include "set.h"
#include "cbootimage.h"
#include "crypto.h"
@@ -39,6 +40,22 @@
* A SetXXX() function may not call any parseing functions.
*/
+#define NV_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#define CASE_DEVICE_VALUE(prefix, id) \
+ case token_##id: \
+ (void)context->bctlib.setdev_param(index, \
+ nvbct_lib_id_##prefix##_##id, \
+ value, \
+ context->bct); \
+ break
+
+#define DEFAULT() \
+ default: \
+ printf("Unexpected token %d at line %d\n", \
+ token, __LINE__); \
+ return 1
+
int
read_from_image(char *filename,
u_int32_t page_size,
@@ -59,7 +76,7 @@ read_from_image(char *filename,
if (stat(filename, &stats) != 0) {
printf("Error: Unable to query info on bootloader path %s\n",
- filename);
+ filename);
result = 1;
goto cleanup;
}
@@ -147,7 +164,14 @@ context_set_array(build_image_context *context,
context->bct);
break;
- DEFAULT();
+ case token_dev_type:
+ (void)context->bctlib.setdev_param(index,
+ nvbct_lib_id_dev_type,
+ value,
+ context->bct);
+ break;
+
+ DEFAULT();
}
return 0;
}
@@ -166,8 +190,41 @@ int context_set_value(build_image_context *context,
context->newbl_attr = value;
break;
+ case token_block_size:
+ context->block_size = value;
+ context->block_size_log2 = log2(value);
+
+ if (context->memory != NULL) {
+ printf("Error: Too late to change block size.\n");
+ return 1;
+ }
+
+ if (value != (u_int32_t)(1 << context->block_size_log2)) {
+ printf("Error: Block size must be a power of 2.\n");
+ return 1;
+ }
+ context->pages_per_blk= 1 << (context->block_size_log2-
+ context->page_size_log2);
+ SET_VALUE(block_size_log2, context->block_size_log2);
+ break;
+
+ case token_partition_size:
+ if (context->memory != NULL) {
+ printf("Error: Too late to change block size.\n");
+ return 1;
+ }
+
+ context->partition_size= value;
+ SET_VALUE(partition_size, value);
+ break;
+
case token_page_size:
context->page_size = value;
+ context->page_size_log2 = log2(value);
+ context->pages_per_blk= 1 << (context->block_size_log2-
+ context->page_size_log2);
+
+ SET_VALUE(page_size_log2, context->page_size_log2);
break;
case token_redundancy:
context->redundancy = value;
@@ -304,3 +361,60 @@ set_other_field(build_image_context *context,
}
+static void
+update_num_param_sets(build_image_context *context, u_int32_t index)
+{
+ u_int32_t num_params;
+
+ GET_VALUE(num_param_sets, &num_params);
+ num_params = NV_MAX(num_params, index + 1);
+ SET_VALUE(num_param_sets, num_params);
+}
+
+/*
+ * set_sdmmc_param(): Processes commands to set MoviNand parameters.
+ */
+int
+set_sdmmc_param(build_image_context *context,
+ u_int32_t index,
+ parse_token token,
+ u_int32_t value)
+{
+ assert(context != NULL);
+ assert(context->bct != NULL);
+
+ update_num_param_sets(context, index);
+
+ switch (token) {
+ CASE_DEVICE_VALUE(sdmmc, clock_divider);
+ CASE_DEVICE_VALUE(sdmmc, data_width);
+ CASE_DEVICE_VALUE(sdmmc, max_power_class_supported);
+ DEFAULT();
+ }
+
+ return 0;
+}
+
+/*
+ * set_spiflash_param(): Processes commands to set SpiFlash parameters.
+ */
+int
+set_spiflash_param(build_image_context *context,
+ u_int32_t index,
+ parse_token token,
+ u_int32_t value)
+{
+ assert(context != NULL);
+ assert(context->bct != NULL);
+
+ update_num_param_sets(context, index);
+
+ switch (token) {
+ CASE_DEVICE_VALUE(spiflash, clock_divider);
+ CASE_DEVICE_VALUE(spiflash, clock_source);
+ CASE_DEVICE_VALUE(spiflash, read_command_type_fast);
+ DEFAULT();
+ }
+
+ return 0;
+}
diff --git a/set.h b/set.h
index 44443f8..5706847 100644
--- a/set.h
+++ b/set.h
@@ -71,6 +71,18 @@ set_other_field(build_image_context *context,
int index);
int
+set_sdmmc_param(build_image_context *context,
+ u_int32_t index,
+ parse_token token,
+ u_int32_t value);
+
+int
+set_spiflash_param(build_image_context *context,
+ u_int32_t index,
+ parse_token token,
+ u_int32_t value);
+
+int
read_from_image(char *filename,
u_int32_t page_size,
u_int8_t **Image,