From 4a19dabdd4b7d8c44f9436051326ccaa60f91e52 Mon Sep 17 00:00:00 2001 From: Sergey Gridassov Date: Sat, 4 Dec 2010 12:35:49 +0300 Subject: [PATCH] Implemented nand configuration; increased command timeout; implemented stage2 configuration; implemented safe builtin; added boot.cfg --- boot.cfg | 5 +++++ ingenic.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ ingenic.h | 25 +++++++++++++++++++++- initial.cfg | 2 +- main.c | 5 +++++ shell.c | 15 +++++++++++++ spl_cmdset.c | 10 ++++++++- usbboot_cmdset.c | 14 ++++++++++++ usbdev.c | 2 +- 9 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 boot.cfg diff --git a/boot.cfg b/boot.cfg new file mode 100644 index 0000000..8b1e865 --- /dev/null +++ b/boot.cfg @@ -0,0 +1,5 @@ +source initial.cfg + +safe memtest +boot + diff --git a/ingenic.c b/ingenic.c index 670a397..394a20d 100644 --- a/ingenic.c +++ b/ingenic.c @@ -43,6 +43,7 @@ typedef struct { void *callbacks_data; firmware_config_t cfg; + nand_config_t nand; } ingenic_handle_t; static const struct { @@ -173,6 +174,8 @@ void ingenic_close(void *hndl) { #define CFGOPT(name, var, exp) { char *str = cfg_getenv(name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", name, #exp); return -1; }; handle->cfg.var = v; } +#define NOPT(name, var, exp) { char *str = cfg_getenv("NAND_" name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", "NAND_" name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", "NAND_" name, #exp); return -1; }; handle->nand.nand_##var = v; } + int ingenic_rebuild(void *hndl) { HANDLE; @@ -205,6 +208,27 @@ int ingenic_rebuild(void *hndl) { hexdump(&handle->cfg, sizeof(firmware_config_t)); + handle->nand.cpuid = CPUID(handle->type); + + NOPT("BUSWIDTH", bw, 1); + NOPT("ROWCYCLES", rc, 1); + NOPT("PAGESIZE", ps, 1); + NOPT("PAGEPERBLOCK", ppb, 1); + NOPT("FORCEERASE", force_erase, 1); +// FIXME: pn is not set by xburst-tools usbboot. Is this intended? + NOPT("OOBSIZE", os, 1); + NOPT("ECCPOS", eccpos, 1); + NOPT("BADBLOCKPOS", bbpos, 1); + NOPT("BADBLOCKPAGE", bbpage, 1); + NOPT("PLANENUM", plane, 1); + NOPT("BCHBIT", bchbit, 1); + NOPT("WPPIN", wppin, 1); + NOPT("BLOCKPERCHIP", bpc, 1); + + debug(LEVEL_DEBUG, "NAND configuration dump:\n"); + + hexdump(&handle->nand, sizeof(nand_config_t)); + return 0; } @@ -348,3 +372,34 @@ int ingenic_memtest(void *hndl, const char *filename, uint32_t base, uint32_t si return 0; } +int ingenic_configure_stage2(void *hndl) { + HANDLE; + +// DS_flash_info (nand_config_t only) is not implemented in stage2, so using DS_hand (nand_config_t + firmware_config_t) + uint8_t *hand = malloc(sizeof(nand_config_t) + sizeof(firmware_config_t)); + + memcpy(hand, &handle->nand, sizeof(nand_config_t)); + memcpy(hand + sizeof(nand_config_t), &handle->cfg, sizeof(firmware_config_t)); + + int ret = usbdev_sendbulk(handle->usb, hand, sizeof(nand_config_t) + sizeof(firmware_config_t)); + + free(hand); + + if(ret == -1) + return -1; + + if(usbdev_vendor(handle->usb, USBDEV_TODEV, VR_CONFIGRATION, DS_hand, 0, 0, 0) == -1) + return -1; + + uint32_t result[8]; + + ret = usbdev_recvbulk(handle->usb, result, sizeof(result)); + + if(ret == -1) + return -1; + + debug(LEVEL_DEBUG, "Stage2 configured\n"); + + return 0; +} + diff --git a/ingenic.h b/ingenic.h index aa3ea82..32c166c 100644 --- a/ingenic.h +++ b/ingenic.h @@ -35,6 +35,8 @@ int ingenic_loadstage(void *hndl, int id, const char *filename); int ingenic_stage1_debugop(void *device, const char *filename, uint32_t op, uint32_t pin, uint32_t base, uint32_t size); int ingenic_memtest(void *hndl, const char *filename, uint32_t base, uint32_t size, uint32_t *fail); +int ingenic_configure_stage2(void *hndl); + #define CMDSET_SPL 1 #define CMDSET_USBBOOT 2 @@ -50,13 +52,15 @@ int ingenic_memtest(void *hndl, const char *filename, uint32_t base, uint32_t si #define STAGE2_CODESIZE 0x400000 #define SDRAM_BASE 0x80000000 +#define DS_flash_info 0 +#define DS_hand 1 typedef struct { /* debug args */ uint8_t debug_ops; uint8_t pin_num; uint32_t start; uint32_t size; -} ingenic_stage1_debug_t; +} __attribute__((packed)) ingenic_stage1_debug_t; typedef struct { /* CPU ID */ @@ -80,4 +84,23 @@ typedef struct { ingenic_stage1_debug_t debug; } __attribute__((packed)) firmware_config_t; +typedef struct { + /* nand flash info */ + uint32_t cpuid; /* cpu type */ + uint32_t nand_bw; /* bus width */ + uint32_t nand_rc; /* row cycle */ + uint32_t nand_ps; /* page size */ + uint32_t nand_ppb; /* page number per block */ + uint32_t nand_force_erase; + uint32_t nand_pn; /* page number in total */ + uint32_t nand_os; /* oob size */ + uint32_t nand_eccpos; + uint32_t nand_bbpage; + uint32_t nand_bbpos; + uint32_t nand_plane; + uint32_t nand_bchbit; + uint32_t nand_wppin; + uint32_t nand_bpc; /* block number per chip */ +} nand_config_t; + #endif diff --git a/initial.cfg b/initial.cfg index 15c1c53..924d485 100644 --- a/initial.cfg +++ b/initial.cfg @@ -24,7 +24,7 @@ set NAND_PAGEPERBLOCK 128 # The page number per block set NAND_FORCEERASE 1 # The force to erase flag (0|1) set NAND_OOBSIZE 64 # OOB size in byte set NAND_ECCPOS 8 # Specify the ECC offset inside the oob data (0-[oobsize-1]) -set NAND_BADBLACKPOS 0 # Specify the badblock flag offset inside the oob (0-[oobsize-1]) +set NAND_BADBLOCKPOS 0 # Specify the badblock flag offset inside the oob (0-[oobsize-1]) set NAND_BADBLOCKPAGE 0 # Specify the page number of badblock flag inside a block(0-[PAGEPERBLOCK-1]) set NAND_PLANENUM 1 # The planes number of target nand flash set NAND_BCHBIT 8 # Specify the hardware BCH algorithm for 4750 (4|8) diff --git a/main.c b/main.c index 916abeb..663ab08 100644 --- a/main.c +++ b/main.c @@ -157,6 +157,10 @@ int main(int argc, char *argv[]) { if(config) if(shell_source(config) == -1) { perror("shell_source"); + + ret = 1; + + goto exit_shell; } if(cmd != NULL) { @@ -175,6 +179,7 @@ int main(int argc, char *argv[]) { } else shell_interactive(); +exit_shell: shell_fini(); exit_ingenic: diff --git a/shell.c b/shell.c index 80fe6ec..913e6e3 100644 --- a/shell.c +++ b/shell.c @@ -47,6 +47,7 @@ static int builtin_sleep(int argc, char *argv[]); static int builtin_redetect(int argc, char *argv[]); static int builtin_rebuildcfg(int argc, char *argv[]); static int builtin_set(int argc, char *argv[]); +static int builtin_safe(int argc, char *argv[]); static const shell_command_t commands[] = { { "help", "- Display this message", builtin_help }, @@ -55,6 +56,7 @@ static const shell_command_t commands[] = { { "echo", " - output specified string", builtin_echo }, { "sleep", " - sleep a specified amount of time", builtin_sleep }, { "set", "[VARIABLE] [VALUE] - print or set configuraton variables", builtin_set }, + { "safe", " [ARG]... - run command ignoring errors", builtin_safe }, { "redetect", " - Redetect CPU", builtin_redetect }, { "rebuildcfg", " - Rebuild firmware configuration data", builtin_rebuildcfg }, @@ -389,6 +391,19 @@ static int builtin_rebuildcfg(int argc, char *argv[]) { return ingenic_rebuild(device); } +static int builtin_safe(int argc, char *argv[]) { + if(argc < 2) { + printf("Usage: %s [ARG]...\n", argv[0]); + + return -1; + } + + if(shell_run(argc - 1, argv + 1) == -1) + perror("shell_run"); + + return 0; +} + static const struct { int set; const char *name; diff --git a/spl_cmdset.c b/spl_cmdset.c index 5782f64..86503e5 100644 --- a/spl_cmdset.c +++ b/spl_cmdset.c @@ -122,9 +122,17 @@ static int spl_boot(int argc, char *argv[]) { ret = ingenic_loadstage(shell_device(), INGENIC_STAGE2, cfg_getenv("STAGE2_FILE")); - if(ret == -1) + if(ret == -1) { perror("ingenic_loadstage"); + return -1; + } + + ret = ingenic_configure_stage2(shell_device()); + + if(ret == -1) + perror("ingenic_configure_stage2"); + return ret; } diff --git a/usbboot_cmdset.c b/usbboot_cmdset.c index 221c73c..298a86f 100644 --- a/usbboot_cmdset.c +++ b/usbboot_cmdset.c @@ -23,6 +23,20 @@ #include "config.h" #include "ingenic.h" +static int usbboot_boot(int argc, char *argv[]); + const shell_command_t usbboot_cmdset[] = { + { "boot", "- Reconfigure stage2", usbboot_boot }, + { NULL, NULL, NULL } }; + +static int usbboot_boot(int argc, char *argv[]) { + int ret = ingenic_configure_stage2(shell_device()); + + if(ret == -1) + perror("ingenic_configure_stage2"); + + return ret; +} + diff --git a/usbdev.c b/usbdev.c index ab2b95f..e2731c0 100644 --- a/usbdev.c +++ b/usbdev.c @@ -24,7 +24,7 @@ #include "debug.h" #include "devmgr.h" -#define CONTROL_TIMEOUT 1000 +#define CONTROL_TIMEOUT 5000 static libusb_context *ctx = NULL;