/* * common/tools/genNVRAM/genNVRAM.c * * Copyright (C) 2009 SPiDCOM Technologies * * 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 * * Author(s): * June 2009 Drasko DRASKOVIC */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Include NVRAM structure file. */ #include #include "iomux_cfg.h" #include "miu_cfg.h" /* Common default values. */ #define DEFAULT_PKG_CFG 0x0000024e #define DEFAULT_GPIO_0_7_CFG 0x11331111 #define DEFAULT_GPIO_8_15_CFG 0x00000000 #define DEFAULT_ALLOW_DIR 0xfffff9ff #define DEFAULT_SDRAM_CONFIG 0x001c3168 #define DEFAULT_SDRAM_TIMING0 0x022e569a #define DEFAULT_SDRAM_TIMING1 0x00070008 #define DEFAULT_SDRAM_REFRESH 0x00000410 #define DEFAULT_FLASH_ORG 0x00000006 #define DEFAULT_IMAGE_MAX_SIZE 0x00360000 #define DEFAULT_NB_IMAGES 2 #define DEFAULT_PRODUCT_NAME "SPiDCOM dev board" #define DEFAULT_PRODUCT_PARTNB "" #define DEFAULT_PRODUCT_DESC "SPiDCOM PLC modem" #define DEFAULT_SERIAL_NUMBER "99999" #define DEFAULT_ETH1_PHY_ADDR 0x02 #define DEFAULT_ETH1_ADDRESS { 0x00, 0x13, 0xD7, 0x00, 0x10, 0x01 } #define DEFAULT_ETH_PORT_NB 1 #define DEFAULT_PLC_ADDRESS { 0x00, 0x13, 0xD7, 0x00, 0x00, 0x01 } #define DEFAULT_DEVICE_PASSWORD "SPIDCOM-DEV-01" #define DEFAULT_OEM_INFO "" #define DEFAULT_TONEMASK { \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, \ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, \ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ } #define EOC_TONEMASK { \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ } #define EOC_SPC200_TONEMASK { \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ } #define DEFAULT_MANUFACTORY_INFO "SPiDCOM" #define DEFAULT_CPU_PARTNB 2 #define DEFAULT_BOARD_NUMBER 0 #define DEFAULT_BOARD_DESC "" #define DEFAULT_BOARD_ID 0 #define DEFAULT_SDRAM_SIZE 32 #define DEFAULT_IMAGE1_OFFSET 0x00250000 #define DEFAULT_AFE_TYPE 0 #define DEFAULT_ETH2_PHY_ADDR 0x03 #define DEFAULT_ETH2_ADDRESS { 0x00, 0x13, 0xD7, 0x00, 0x20, 0x01 } /* Specific default values. */ #define DEFAULT_SPC200_IMAGE0_OFFSET 0x000a0000 #define DEFAULT_SPC300_IMAGE0_OFFSET 0x00140000 #define TONEMASK_LABEL_AV "av" #define TONEMASK_LABEL_EOC "eoc" #define TONEMASK_LABEL_EOC_SPC200 "eoc-spc200" char tonemask_av[] = DEFAULT_TONEMASK; char tonemask_eoc[] = EOC_TONEMASK; char tonemask_eoc_spc200[] = EOC_SPC200_TONEMASK; static spidcom_nvram_t nvram = { .magic = SPC300_NVRAM_MAGIC, .pkg_cfg = DEFAULT_PKG_CFG, .io.spcpio = { .gpio_0_7_cfg = DEFAULT_GPIO_0_7_CFG, .gpio_8_15_cfg = DEFAULT_GPIO_8_15_CFG, }, .gpio_allow_dir = DEFAULT_ALLOW_DIR, .dram.sdram = { .config = DEFAULT_SDRAM_CONFIG, .timing0 = DEFAULT_SDRAM_TIMING0, .timing1 = DEFAULT_SDRAM_TIMING1, .refresh = DEFAULT_SDRAM_REFRESH, }, .flash_org = DEFAULT_FLASH_ORG, .img_0_offset = DEFAULT_SPC300_IMAGE0_OFFSET, .nb_images = DEFAULT_NB_IMAGES, .product_name = DEFAULT_PRODUCT_NAME, .product_partnb = DEFAULT_PRODUCT_PARTNB, .product_desc = DEFAULT_PRODUCT_DESC, .serial_number = DEFAULT_SERIAL_NUMBER, .eth1_phy_addr = DEFAULT_ETH1_PHY_ADDR, .eth1_address = DEFAULT_ETH1_ADDRESS, .eth1_port_nb = DEFAULT_ETH_PORT_NB, .plc_address = DEFAULT_PLC_ADDRESS, .device_password = DEFAULT_DEVICE_PASSWORD, .oem_info = DEFAULT_OEM_INFO, .tonemask = DEFAULT_TONEMASK, .manufactory_info = DEFAULT_MANUFACTORY_INFO, .img_max_size = DEFAULT_IMAGE_MAX_SIZE, .cpu_partnb = DEFAULT_CPU_PARTNB, .magicWord1 = SPC200_NVRAM_MAGIC1, .magicWord2 = SPC200_NVRAM_MAGIC2, .boardNumber = DEFAULT_BOARD_NUMBER, .serialNumber = DEFAULT_SERIAL_NUMBER, .sysDescr = DEFAULT_PRODUCT_DESC, .ethPhysAddress = DEFAULT_ETH1_ADDRESS, .plcPhysAddress = DEFAULT_PLC_ADDRESS, .magicNvram2 = SPC200_NVRAM2_MAGIC, .boardDesc = DEFAULT_BOARD_DESC, .boardId = DEFAULT_BOARD_ID, .vendorInfo = DEFAULT_OEM_INFO, .sdramSize = DEFAULT_SDRAM_SIZE, .imageOffset0 = (unsigned char *) DEFAULT_SPC200_IMAGE0_OFFSET, .imageOffset1 = (unsigned char *) DEFAULT_IMAGE1_OFFSET, .ethPortNum = DEFAULT_ETH_PORT_NB, .afeType = DEFAULT_AFE_TYPE, .manufactoryInfo = DEFAULT_MANUFACTORY_INFO, .eth2_phy_addr = DEFAULT_ETH2_PHY_ADDR, .eth2_address = DEFAULT_ETH2_ADDRESS, .eth2_port_nb = DEFAULT_ETH_PORT_NB }; /* Next free position in dynamic NVRAM data. */ static uint32_t *nvram_dynamic = nvram.dynamic; static enum { IO_NOINIT, IO_GPIO, IO_IOMUX, } io = IO_NOINIT; struct iomux_config_table_t { char *name; uint32_t *config; }; /* See iomux_cfg.h. */ static const struct iomux_config_table_t iomux_config_table[] = { { "msk500-ddr2_1", iomux_config_msk500_ddr2_1 }, { "msk500-ddr2_2", iomux_config_msk500_ddr2_2 }, { "msk500-ddr2_3", iomux_config_msk500_ddr2_3 }, { "msk500-ddr2_4", iomux_config_msk500_ddr2_4 }, { "msk500-ddr1_1", iomux_config_msk500_ddr1_1 }, { "msk500-ddr1_2", iomux_config_msk500_ddr1_2 }, { "msk501-ddr2_1", iomux_config_msk501_ddr2_1 }, { "msk501-ddr2_2", iomux_config_msk501_ddr2_2 }, { "mcr510-ddr2", iomux_config_mcr510_ddr2 }, { "mcr510-ddr2_2", iomux_config_mcr510_ddr2_2 }, { "mcr510-ddr1_1", iomux_config_mcr510_ddr1_1 }, { "mcr510-ddr1_2", iomux_config_mcr510_ddr1_2 }, { "mcr500-ddr2_1", iomux_config_mcr500_ddr2_1 }, { "mcr500-ddr2_2", iomux_config_mcr500_ddr2_2 }, NULL }; static enum { DRAM_NOINIT, DRAM_SDRAM, DRAM_MIU, } dram = DRAM_NOINIT; struct miu_config_table_t { char *name; unsigned int ram_size; uint32_t *config; }; /* See miu_cfg.h. */ static const struct miu_config_table_t miu_config_table[] = { { "sdram_dini_64m", 64 * 1024 * 1024, miu_config_sdram_dini_64m }, { "mt47h32m16", 128 * 1024 * 1024, miu_config_mt47h32m16 }, { "h5ps1g63jfr-s6c", 128 * 1024 *1024, miu_config_ddr2_16_4x_cl6_800 }, { "nt5tu64m16gg-ac", 128 * 1024 *1024, miu_config_ddr2_16_4x_cl6_800 }, { "h5du5162etr-fac", 64 * 1024 * 1024, miu_config_ddr1_h5du5162etr_fac_500}, { "h5ps5162gfr-s6c", 64 * 1024 *1024, miu_config_ddr2_16_2x_cl6_800 }, NULL }; /* Is there an infile specified? */ bool infile = false; /* Is there an outfile specified? */ bool outfile = false; /* Type of NVRAM to generate. Those values are also used by the "arch" * bitfield in parse_table. */ enum { NVRAM_TYPE_SPC200 = 0x01, NVRAM_TYPE_SPC300 = 0x02, NVRAM_TYPE_MSE500 = 0x04 }; int nvram_type = 0; /* * Private functions */ static void print_usage(const char *cmd) { fprintf(stderr, "Usage : %s\n" " Mandatory arguments:\n" " [ --type [spc200|spc300|mse500] NVRAM type to generate ]\n" " [ --infile base_conf ]\n" " [ --outfile result_file ]\n" " Optional arguments:\n" " [ --pkgcfg package number ] (300/500)\n" " [ --gpio07 GPIO 0 to 7 config ] (300/500)\n" " [ --gpio815 GPIO 8 to 15 config ] (300/500)\n" " [ --iomux-config IOMUX config ] (500)\n" " [ --gpiodir GPIO allowed directions ] (300/500)\n" " [ --sconr SDRAM config register ] (300/500)\n" " [ --stmg0r SDRAM timing0 register ] (300/500)\n" " [ --stmg1r SDRAM timing1 register ] (300/500)\n" " [ --srefr SDRAM refresh register ] (300/500)\n" " [ --ssize SDRAM size ] (200/500)\n" " [ --miu-config MIU controller config ] (300/500)\n" " [ --forg flash organization ] (300/500)\n" " [ --img0off first image offset in flash ] (200/300/500)\n" " [ --img1off second image offset in flash ] (200/500)\n" " [ --nbimg number of Linux images ] (300/500)\n" " [ --name product name ] (300/500)\n" " [ --partnb product part number ] (300/500)\n" " [ --desc product descrption ] (200/300/500)\n" " [ --serial serial number ] (200/300/500)\n" " [ --phy1 Ethernet PHY address ] (300/500)\n" " [ --ethernet1 ethernet MAC address ] (200/300/500)\n" " [ --portnb1 ethernet port number ] (200/300/500)\n" " [ --plc powerline MAC address ] (200/300/500)\n" " [ --dpw device password ] (300/500)\n" " [ --oem oem informations ] (200/300/500)\n" " [ --tonemask [av|eoc|eoc-spc200] AV carriers tonemask ] (300/500)\n" " [ --factory manufactory informations ] (200/300/500)\n" " [ --imgmaxsize max size of an image in flash ] (300/500)\n" " [ --cpupartnb CPU part number ] (300/500)\n" " [ --brdnb board number ] (200/500)\n" " [ --brddesc board description ] (200/500)\n" " [ --brdid board ID ] (200/500)\n" " [ --afetype AFE type ] (200/500)\n" " [ --phy2 Ethernet PHY address ] (500)\n" " [ --ethernet2 ethernet MAC address ] (500)\n" " [ --portnb2 ethernet port number ] (500)\n", cmd); } void str2hwaddr(unsigned char *hw, const char *s) { int i = 0; char *e = NULL; memset(hw, 0x0, ETH_ALEN); for (i = 0; i < 6; i++) { hw[i] = s ? strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } return; } /* * *** Parser *** */ struct parser { char label[32]; int (*func)(char*); int arch; }; /* * Parser functions */ static int parse_nvram_type (char *arg) { if (!strncmp (arg, "spc200", 6)) nvram_type = NVRAM_TYPE_SPC200; else if (!strncmp (arg, "spc300", 6)) nvram_type = NVRAM_TYPE_SPC300; else if (!strncmp (arg, "mse500", 6)) { nvram_type = NVRAM_TYPE_MSE500; /* NVRAM structure is loaded with different values in the image * offset fields in order to have a clean value if we want to generate * an SPC200 or SPC300 NVRAM. But if we want to generate an MSE500 * NVRAM, we must make sure that the values are consistent. */ nvram.imageOffset0 = (unsigned char *) DEFAULT_SPC300_IMAGE0_OFFSET; nvram.imageOffset1 = (unsigned char *) (DEFAULT_SPC300_IMAGE0_OFFSET + DEFAULT_IMAGE_MAX_SIZE); } else { fprintf (stderr, "Bad NVRAM type specified\n"); return -1; } return 0; } static int parse_infile (char *arg) { if (freopen (arg, "r", stdin) == NULL) { fprintf (stderr, "Bad input file '%s' : %s\n", arg, strerror (errno)); return -1; } infile = true; return 0; } static int parse_outfile (char *arg) { if (freopen (arg, "w", stdout) == NULL) { fprintf (stderr, "Bad output file '%s' : %s\n", arg, strerror (errno)); return -1; } outfile = true; return 0; } static int parse_pkgcfg(char *arg) { unsigned int mse500_mode, phy_mode, pio_mode, freq_mode, xclock_mode; nvram.pkg_cfg = (uint32_t)strtoul(arg, NULL, 0); mse500_mode = (nvram.pkg_cfg & 0x3000) >> 12; if(mse500_mode > 3) { fprintf (stderr, "Bad pkgcfg value %04x (mse500 mode = %d)\n", nvram.pkg_cfg, mse500_mode); return -1; } phy_mode = (nvram.pkg_cfg & 0x0c00) >> 10; if(phy_mode > 3) { fprintf (stderr, "Bad pkgcfg value %04x (phy2 = %d)\n", nvram.pkg_cfg, phy_mode); return -1; } phy_mode = (nvram.pkg_cfg & 0x0300) >> 8; if(phy_mode > 3) { fprintf (stderr, "Bad pkgcfg value %04x (phy1 = %d)\n", nvram.pkg_cfg, phy_mode); return -1; } pio_mode = (nvram.pkg_cfg & 0x00f0) >> 4; if(pio_mode > 7) { fprintf (stderr, "Bad pkgcfg value %04x (pio = %d)\n", nvram.pkg_cfg, pio_mode); return -1; } freq_mode = (nvram.pkg_cfg & 0x000c) >> 2; if(freq_mode > 3) { fprintf (stderr, "Bad pkgcfg value %04x (freq = %d)\n", nvram.pkg_cfg, freq_mode); return -1; } xclock_mode = (nvram.pkg_cfg & 0x0003); if(xclock_mode > 3) { fprintf (stderr, "Bad pkgcfg value %04x (xclock = %d)\n", nvram.pkg_cfg, freq_mode); return -1; } return 0; } static int parse_gpio_check(void) { if (io != IO_NOINIT && io != IO_GPIO) { fprintf (stderr, "Several IO muxing configuration detected\n"); return -1; } else { io = IO_GPIO; return 0; } } static int parse_gpio07(char *arg) { nvram.io.spcpio.gpio_0_7_cfg = (uint32_t)strtoul(arg, NULL, 0); return parse_gpio_check(); } static int parse_gpio815(char *arg) { nvram.io.spcpio.gpio_8_15_cfg = (uint32_t)strtoul(arg, NULL, 0); return parse_gpio_check(); } static void write_dynamic_config (uint16_t *config_offset, uint16_t *config_size, uint32_t *config) { *config_size = 0; *config_offset = (uint32_t) ((uint8_t *) nvram_dynamic - (uint8_t *) &nvram); /* Translate the configuration into NVRAM format, see nvram_dyn_cfg.S in * u-boot. */ for ( ; *config != (uint32_t) -1; config += 3) { assert (!(config[1] & ~0xffff)); assert (!(config[2] & ~0xffff)); *nvram_dynamic++ = config[0]; *nvram_dynamic++ = (config[2] << 16) | config[1]; *config_size += 2 * sizeof (uint32_t); } } static int parse_iomux_config(char *arg) { if (io != IO_NOINIT) { fprintf (stderr, "Several IO muxing configuration detected\n"); return -1; } io = IO_IOMUX; /* Lookup the requested config. */ const struct iomux_config_table_t *p; for (p = iomux_config_table; p->name; p++) { if (strcmp(p->name, arg) == 0) { nvram.io.iomux.reserved = 0; write_dynamic_config (&nvram.io.iomux.config_offset, &nvram.io.iomux.config_size, p->config); return 0; } } return -1; } static int parse_gpiodir(char *arg) { nvram.gpio_allow_dir = (uint32_t)strtoul(arg, NULL, 0); return 0; } static int parse_sdram_check(void) { if (dram != DRAM_NOINIT && dram != DRAM_SDRAM) { fprintf (stderr, "Several DRAM controller configuration detected\n"); return -1; } else { dram = DRAM_SDRAM; return 0; } } static int parse_sdramcfg(char *arg) { nvram.dram.sdram.config = (uint32_t)strtoul(arg, NULL, 0); return parse_sdram_check(); } static int parse_sdramtmg0(char *arg) { nvram.dram.sdram.timing0 = (uint32_t)strtoul(arg, NULL, 0); return parse_sdram_check(); } static int parse_sdramtmg1(char *arg) { nvram.dram.sdram.timing1 = (uint32_t)strtoul(arg, NULL, 0); return parse_sdram_check(); } static int parse_sdramrefr(char *arg) { nvram.dram.sdram.refresh = (uint32_t)strtoul(arg, NULL, 0); return parse_sdram_check(); } static int parse_sdramsize(char *arg) { nvram.sdramSize = atoi (arg); return 0; } static int parse_miu_config(char *arg) { if (dram != DRAM_NOINIT) { fprintf (stderr, "Several DRAM controller configuration detected\n"); return -1; } dram = DRAM_MIU; /* Lookup the requested config. */ const struct miu_config_table_t *p; for (p = miu_config_table; p->name; p++) { if (strcmp(p->name, arg) == 0) { nvram.dram.miu.ram_size = p->ram_size; nvram.dram.miu.reserved[0] = 0; nvram.dram.miu.reserved[1] = 0; write_dynamic_config (&nvram.dram.miu.config_offset, &nvram.dram.miu.config_size, p->config); return 0; } } return -1; } static int parse_forg(char *arg) { unsigned int sector_size; nvram.flash_org = (uint32_t)strtoul(arg, NULL, 0); sector_size = (nvram.flash_org & 0xf0) >> 4; if(sector_size > 2) { fprintf (stderr, "Bad forg value %04x (sector size = %d)\n", nvram.flash_org, sector_size); return -1; } return 0; } static int parse_img0off(char *arg) { nvram.img_0_offset = (uint32_t)strtoul(arg, NULL, 0); nvram.imageOffset0 = (unsigned char *)strtoul(arg, NULL, 0); return 0; } static int parse_img1off(char *arg) { nvram.imageOffset1 = (unsigned char *) atoi (arg); return 0; } static int parse_imgmaxsize(char *arg) { nvram.img_max_size = (uint32_t)strtoul(arg, NULL, 0); return 0; } static int parse_nbimg(char *arg) { nvram.nb_images = (uint32_t)strtoul(arg, NULL, 0); return 0; } static int parse_name(char *arg) { strncpy (nvram.product_name, arg, sizeof(nvram.product_name) - 1); nvram.product_name[sizeof(nvram.product_name) - 1] = '\0'; return 0; } static int parse_partnb(char *arg) { strncpy (nvram.product_partnb, arg, sizeof(nvram.product_partnb) - 1); nvram.product_partnb[sizeof(nvram.product_partnb) - 1] = '\0'; return 0; } static int parse_desc(char *arg) { strncpy (nvram.product_desc, arg, sizeof(nvram.product_desc) - 1); nvram.product_desc[sizeof(nvram.product_desc) - 1] = '\0'; strncpy (nvram.sysDescr, arg, sizeof(nvram.sysDescr) - 1); nvram.sysDescr[sizeof(nvram.sysDescr) - 1] = '\0'; return 0; } static int parse_serial(char *arg) { strncpy (nvram.serial_number, arg, sizeof(nvram.serial_number) - 1); nvram.serial_number[sizeof(nvram.serial_number) - 1] = '\0'; strncpy (nvram.serialNumber, arg, sizeof(nvram.serialNumber) - 1); nvram.serialNumber[sizeof(nvram.serialNumber) - 1] = '\0'; return 0; } static int parse_phy1(char *arg) { nvram.eth1_phy_addr = (uint32_t)strtoul(arg, NULL, 0); return 0; } static int parse_eth1(char *arg) { str2hwaddr(nvram.eth1_address, arg); str2hwaddr(nvram.ethPhysAddress, arg); return 0; } static int parse_portnb1(char *arg) { nvram.eth1_port_nb = atoi(arg); nvram.ethPortNum = atoi(arg); return 0; } static int parse_phy2(char *arg) { nvram.eth2_phy_addr = (uint32_t)strtoul(arg, NULL, 0); return 0; } static int parse_eth2(char *arg) { str2hwaddr(nvram.eth2_address, arg); return 0; } static int parse_portnb2(char *arg) { nvram.eth2_port_nb = atoi(arg); return 0; } static int parse_plc(char *arg) { str2hwaddr(nvram.plc_address, arg); str2hwaddr(nvram.plcPhysAddress, arg); return 0; } static int parse_dpw(char *arg) { strncpy (nvram.device_password, arg, sizeof(nvram.device_password) - 1); nvram.device_password[sizeof(nvram.device_password) - 1] = '\0'; return 0; } static int parse_oem(char *arg) { strncpy (nvram.oem_info, arg, sizeof(nvram.oem_info) - 1); nvram.oem_info[sizeof(nvram.oem_info) - 1] = '\0'; strncpy (nvram.vendorInfo, arg, sizeof(nvram.vendorInfo) - 1); nvram.vendorInfo[sizeof(nvram.vendorInfo) - 1] = '\0'; return 0; } static int parse_tonemask (char *arg) { if(!strcmp (arg, TONEMASK_LABEL_AV)) { memcpy (nvram.tonemask, tonemask_av, sizeof(nvram.tonemask)); } else if(!strcmp (arg, TONEMASK_LABEL_EOC)) { memcpy (nvram.tonemask, tonemask_eoc, sizeof(nvram.tonemask)); } else if(!strcmp (arg, TONEMASK_LABEL_EOC_SPC200)) { memcpy (nvram.tonemask, tonemask_eoc_spc200, sizeof(nvram.tonemask)); } else { fprintf (stderr, "Bad tonemask value (must be av, eoc or eoc-spc200)\n"); return -1; } return 0; } static int parse_factory(char *arg) { strncpy (nvram.manufactory_info, arg, sizeof(nvram.manufactory_info) - 1); nvram.manufactory_info[sizeof(nvram.manufactory_info) - 1] = '\0'; strncpy (nvram.manufactoryInfo, arg, sizeof(nvram.manufactoryInfo) - 1); nvram.manufactoryInfo[sizeof(nvram.manufactoryInfo) - 1] = '\0'; return 0; } static int parse_cpu_partnb(char *arg) { nvram.cpu_partnb = atoi(arg); return 0; } static int parse_brdnb(char *arg) { nvram.boardNumber = atoi (arg); return 0; } static int parse_brddesc(char *arg) { strncpy (nvram.boardDesc, arg, sizeof (nvram.boardDesc) - 1); nvram.boardDesc[sizeof (nvram.boardDesc) - 1] = '\0'; return 0; } static int parse_afetype(char *arg) { nvram.afeType = atoi (arg); return 0; } static int parse_brdid(char *arg) { nvram.boardId = atoi (arg); return 0; } static char *chop(char *str) { int i; for (i = strlen(str); i--;) { if(str[i] == ' ' || str[i] == '\t' || str[i] == '\n') str[i] = '\0'; else break; } while (*str == ' ' || *str == '\t') str++; return str; } /* * Parser tables */ struct parser parse_table[] = { { "type", parse_nvram_type, 0 }, { "infile", parse_infile, 0 }, { "outfile", parse_outfile, 0 }, { "pkgcfg", parse_pkgcfg, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "gpio07", parse_gpio07, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "gpio815", parse_gpio815, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "iomux_config", parse_iomux_config, NVRAM_TYPE_MSE500 }, { "gpiodir", parse_gpiodir, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "sconr", parse_sdramcfg, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "stmg0r", parse_sdramtmg0, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "stmg1r", parse_sdramtmg1, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "srefr", parse_sdramrefr, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "ssize", parse_sdramsize, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "miu_config", parse_miu_config, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "forg", parse_forg, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "img0off", parse_img0off, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "img1off", parse_img1off, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "nbimg", parse_nbimg, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "name", parse_name, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500}, { "partnb", parse_partnb, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "desc", parse_desc, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "serial", parse_serial, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "phy1", parse_phy1, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "ethernet1", parse_eth1, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "plc", parse_plc, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "dpw", parse_dpw, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "oem", parse_oem, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "tonemask", parse_tonemask, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "factory", parse_factory, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "portnb1", parse_portnb1, NVRAM_TYPE_SPC200 | NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "imgmaxsize", parse_imgmaxsize, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "cpupartnb", parse_cpu_partnb, NVRAM_TYPE_SPC300 | NVRAM_TYPE_MSE500 }, { "brdnb", parse_brdnb, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "brddesc", parse_brddesc, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "brdid", parse_brdid, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "afetype", parse_afetype, NVRAM_TYPE_SPC200 | NVRAM_TYPE_MSE500 }, { "phy2", parse_phy2, NVRAM_TYPE_MSE500 }, { "ethernet2", parse_eth2, NVRAM_TYPE_MSE500 }, { "portnb2", parse_portnb2, NVRAM_TYPE_MSE500 }, }; /* * Parser main function */ static int parse_stdin() { int i; FILE *fp; char line[1024]; char *plabel, *parg; while( fgets(line, sizeof(line), stdin) != NULL ) { parg = line; /* Separate fields */ plabel = strsep(&parg, "="); if (!parg) continue; /* keyword processing */ for(i = sizeof(parse_table) / sizeof(struct parser); i--;) { if( !strncasecmp(parse_table[i].label, chop(plabel), sizeof(line)) ) { if (nvram_type & parse_table[i].arch) { if (parse_table[i].func (chop (parg)) < 0) return -1; } else { fprintf (stderr, "%s does not exist in selected NVRAM type\n", parse_table[i].label); return -1; } } } } return 0; } /* * Main program */ int main(int argc, char **argv) { int c; int opt_index = 0; struct option long_opts[] = { /* The val field should be set to the index of the corresponding parse * function in parse_table. */ { "type", required_argument, NULL, 0 }, { "infile", required_argument, NULL, 1 }, { "outfile", required_argument, NULL, 2 }, { "pkgcfg", required_argument, NULL, 3 }, { "gpio07", required_argument, NULL, 4 }, { "gpio815", required_argument, NULL, 5 }, { "iomux-config", required_argument, NULL, 6 }, { "gpiodir", required_argument, NULL, 7 }, { "sconr", required_argument, NULL, 8 }, { "stmg0r", required_argument, NULL, 9 }, { "stmg1r", required_argument, NULL, 10 }, { "srefr", required_argument, NULL, 11 }, { "ssize", required_argument, NULL, 12 }, { "miu-config", required_argument, NULL, 13 }, { "forg", required_argument, NULL, 14 }, { "img0off", required_argument, NULL, 15 }, { "img1off", required_argument, NULL, 16 }, { "nbimg", required_argument, NULL, 17 }, { "name", required_argument, NULL, 18 }, { "partnb", required_argument, NULL, 19 }, { "desc", required_argument, NULL, 20 }, { "serial", required_argument, NULL, 21 }, { "phy1", required_argument, NULL, 22 }, { "ethernet1", required_argument, NULL, 23 }, { "plc", required_argument, NULL, 24 }, { "dpw", required_argument, NULL, 25 }, { "oem", required_argument, NULL, 26 }, { "tonemask", required_argument, NULL, 27 }, { "factory", required_argument, NULL, 28 }, { "portnb1", required_argument, NULL, 29 }, { "imgmaxsize", required_argument, NULL, 30 }, { "cpupartnb", required_argument, NULL, 31 }, { "brdnb", required_argument, NULL, 32 }, { "brddesc", required_argument, NULL, 33 }, { "brdid", required_argument, NULL, 34 }, { "afetype", required_argument, NULL, 35 }, { "phy2", required_argument, NULL, 36 }, { "ethernet2", required_argument, NULL, 37 }, { "portnb2", required_argument, NULL, 38 }, { 0, 0, 0, 0 } }; while( ( c = getopt_long_only(argc, argv, "", long_opts, &opt_index) ) != -1 ) { if (c != '?') { if (c < 3 || nvram_type & parse_table[c].arch) { if ((parse_table[c].func (optarg)) < 0) { print_usage (argv[0]); exit (1); } } else { fprintf (stderr, "%s does not exist in selected NVRAM type\n", parse_table[c].label); print_usage (argv[0]); exit (1); } } else { print_usage (argv[0]); exit (1); } } if (infile == false || outfile == false || nvram_type == 0) { fprintf (stderr, "Error: infile, outfile and NVRAM type are mandatory" " arguments!!\n\n"); print_usage (argv[0]); exit (1); } /* parse the input file */ if(parse_stdin () < 0) { print_usage (argv[0]); exit (1); } /* Output image */ unsigned char *nvram_src; size_t nvram_size; if (nvram_type == NVRAM_TYPE_SPC300) { nvram_src = (unsigned char *) &nvram; nvram_size = SPC300_NVRAM_SIZE; } else if (nvram_type == NVRAM_TYPE_SPC200) { nvram_src = (unsigned char *) ((unsigned int) &nvram + SPC300_NVRAM_SIZE); nvram_size = SPC200_NVRAM_SIZE; } else if (nvram_type == NVRAM_TYPE_MSE500) { nvram_src = (unsigned char *) &nvram; nvram_size = sizeof (spidcom_nvram_t); } write (fileno(stdout), nvram_src, nvram_size); return 0; }