void handle_dump(const char *name, unsigned offset) { ptentry *p; if(tmpbuf == 0) { tmpbuf = alloc(4096); } dprintf("dump '%s' partition\n", name); p = flash_find_ptn(name); if(p == 0) { jtag_fail("partition not found"); return; } if(flash_init()) { jtag_fail("flash_init() failed"); return; } #if 0 /* XXX reimpl */ if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)) { jtag_fail("flash_read() failed"); return; } #endif dprintf("page %d data:\n", p->start * 64); hexdump(tmpbuf, 256); dprintf("page %d extra:\n", p->start * 64); hexdump(tmpbuf, 16); jtag_okay("done"); }
int boot_linux_from_flash(void) { boot_img_hdr *hdr = (void*) raw_header; unsigned n; ptentry *p; unsigned offset = 0; const char *cmdline; if((p = flash_find_ptn("boot")) == 0) { cprintf("NO BOOT PARTITION\n"); return -1; } if(flash_read(p, offset, raw_header, 2048)) { cprintf("CANNOT READ BOOT IMAGE HEADER\n"); return -1; } offset += 2048; if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { cprintf("INVALID BOOT IMAGE HEADER\n"); return -1; } n = (hdr->kernel_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1)); if(flash_read(p, offset, (void*) hdr->kernel_addr, n)) { cprintf("CANNOT READ KERNEL IMAGE\n"); return -1; } offset += n; n = (hdr->ramdisk_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1)); if(flash_read(p, offset, (void*) hdr->ramdisk_addr, n)) { cprintf("CANNOT READ RAMDISK IMAGE\n"); return -1; } offset += n; dprintf("\nkernel @ %x (%d bytes)\n", hdr->kernel_addr, hdr->kernel_size); dprintf("ramdisk @ %x (%d bytes)\n\n\n", hdr->ramdisk_addr, hdr->ramdisk_size); if(hdr->cmdline[0]) { cmdline = (char*) hdr->cmdline; } else { cmdline = board_cmdline(); if(cmdline == 0) { cmdline = "mem=50M console=null"; } } cprintf("cmdline = '%s'\n", cmdline); cprintf("\nBooting Linux\n"); create_atags(ADDR_TAGS, cmdline, hdr->ramdisk_addr, hdr->ramdisk_size); boot_linux(hdr->kernel_addr); return 0; }
/***************************************************************************** * name : flash_erase_force * * description : Erase nand block force, even if it's bad. * * input : char *partition_name: partition to be erase * * other : No *****************************************************************************/ void flash_erase_force(char *partition_name) { unsigned i = 0; unsigned ret = ERROR; unsigned block_start = 0; unsigned block_end= 0; struct nand_spec spec; struct ptentry *ptn = NULL; ret = nand_get_spec(&spec); if(ret) { cprintf("ERROR: nand get spec failed!\n"); goto EXIT; } partition_name = bsp_nand_argument_check(partition_name); if(NULL == partition_name) { cprintf("ERROR: no partition name!\n"); goto EXIT; } ptn = flash_find_ptn(partition_name); if(!ptn) { cprintf("ERROR: wrong partition name: %s\n", partition_name); goto EXIT; } /* coverity[uninit_use] */ block_start = (ptn->start + spec.blocksize- 1) / spec.blocksize; block_end = (ptn->start + ptn->length + spec.blocksize - 1) / spec.blocksize; for (i = block_start; i < block_end; i++) { ret = nand_erase(i); if(ret) { cprintf("ERROR: nand erase error, block id = %d, ret = %d.\n", i, ret); } } cprintf("Erase %s force finished!\n", partition_name); return; EXIT: cprintf("ret = 0x%x!\n", ret); return; }
/***************************************************************************** * name : flash_scan_bad * * description : scan bad block, if partition_name is NULL, scan all partitions * * input : char *partition_name: partition to scan * * other : No *****************************************************************************/ void flash_scan_bad(char *partition_name) { struct ptentry *ptn = NULL; struct ST_PART_TBL *part = (struct ST_PART_TBL *)SHM_MEM_PTABLE_ADDR; struct nand_spec spec; struct ptentry tn; if(nand_get_spec(&spec)) { cprintf("ERROR: nand get spec failed!\n"); return; } partition_name = bsp_nand_argument_check(partition_name); /* scan all partitions */ if(!partition_name) { part++; while(0 != strcmp(PTABLE_END_STR, part->name)) { if(DATA_VALID == ptable_get_validity(part)) { /* coverity[buffer_size_warning] */ strncpy(tn.name, part->name, 16); tn.start = part->offset; tn.length = part->capacity; /* coverity[uninit_use_in_call] */ get_partition_badblock(&tn, &spec); } part++; } } else /* scan one partition */ { ptn = flash_find_ptn(partition_name); if(!ptn) { cprintf("ERROR: wrong partition name: %s\n", partition_name); return; } /* coverity[uninit_use_in_call] */ get_partition_badblock(ptn, &spec); } cprintf("\n\n"); return; }
void handle_flash(const char *name, unsigned addr, unsigned len) { int r; ptentry *p; dprintf("image @ 0x%x (0x%x bytes)\n", addr, len); dprintf("write to '%s' partition\n", name); p = flash_find_ptn(name); if(p == 0) { dprintf("ERROR: partition not found\n"); return; } else { if(flash_init()) { dprintf("ERROR: flash_init() failed\n"); return; } dprintf("erasing flash @ 0x%x (len=0x%x)\n", p->start, p->length); /* coverity[unchecked_value] */ flash_erase(p); if(len) { dprintf("writing flash at @ 0x%x\n", p->start); if(!strcmp(name, PTABLE_SYSTEM_NM) || !strcmp(name, PTABLE_USERDATA_NM)) { r = flash_write(p, 16, (void*) addr, len); } else { len = (len + FLASH_PAGE_SIZE - 1) & (~(FLASH_PAGE_SIZE-1)); r = flash_write(p, 0, (void*) addr, len); } if(r) { dprintf("ERROR: partition write failed, ret = %d\n", r); } else { dprintf("SUCCESS: %s written successful\n", name); } return; } else { dprintf("ERROR: file length is 0x0\n"); return; } } }
static void usb_rx_cmd_complete(struct usb_request *req, unsigned actual, int status) { if(status != 0) return; if(actual > 4095) actual = 4095; cmdbuf[actual] = 0; dprintf("\n> %s\n",cmdbuf); // dprintf("usb_rx_cmd_complete() '%s'\n", cmdbuf); if(memcmp(cmdbuf, "reboot", 6) == 0) { tx_status("OKAY"); rx_cmd(); mdelay(100); board_reboot(); } #if 0 if(memcmp(cmdbuf, "debug:", 6) == 0) { void debug(char *cmd, char *resp); memcpy(cmdbuf, "OKAY", 5); tx_status(cmdbuf); rx_cmd(); mdelay(5000); dprintf("NOW!\n"); debug(cmdbuf + 6, cmdbuf + 4); return; } #endif if(memcmp(cmdbuf, "getvar:", 7) == 0) { char response[64]; strcpy(response,"OKAY"); if(!strcmp(cmdbuf + 7, "version")) { strcpy(response + 4, VERSION); } else if(!strcmp(cmdbuf + 7, "product")) { strcpy(response + 4, PRODUCTNAME); } else if(!strcmp(cmdbuf + 7, "serialno")) { strcpy(response + 4, serialno); } else { board_getvar(cmdbuf + 7, response + 4); } tx_status(response); rx_cmd(); return; } if(memcmp(cmdbuf, "download:", 9) == 0) { char status[16]; rx_addr = kernel_addr; rx_length = hex2unsigned(cmdbuf + 9); if (rx_length > (64*1024*1024)) { tx_status("FAILdata too large"); rx_cmd(); return; } kernel_size = rx_length; dprintf("recv data addr=%x size=%x\n", rx_addr, rx_length); strcpy(status,"DATA"); num_to_hex8(rx_length, status + 4); tx_status(status); rx_data(); return; } if(memcmp(cmdbuf, "erase:", 6) == 0){ struct ptentry *ptn; ptn = flash_find_ptn(cmdbuf + 6); if(ptn == 0) { tx_status("FAILpartition does not exist"); rx_cmd(); return; } dprintf("erasing '%s'\n", ptn->name); cprintf("erasing '%s'", ptn->name); if(flash_erase(ptn)) { tx_status("FAILfailed to erase partition"); rx_cmd(); cprintf(" - FAIL\n"); return; } else { dprintf("partition '%s' erased\n", ptn->name); cprintf(" - OKAY\n"); } tx_status("OKAY"); rx_cmd(); return; } if(memcmp(cmdbuf, "flash:", 6) == 0){ struct ptentry *ptn; int extra = 0; ptn = flash_find_ptn(cmdbuf + 6); if(kernel_size == 0) { tx_status("FAILno image downloaded"); rx_cmd(); return; } if(ptn == 0) { tx_status("FAILpartition does not exist"); rx_cmd(); return; } if(!strcmp(ptn->name,"boot") || !strcmp(ptn->name,"recovery")) { if(memcmp((void*) kernel_addr, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { tx_status("FAILimage is not a boot image"); rx_cmd(); return; } } #if REQUIRE_SIGNATURE { unsigned char digest[DIGEST_SIZE]; compute_digest((void*) kernel_addr, kernel_size, digest); if (is_signature_okay(digest, signature, key_engineering)) { dprintf("verified by engineering key\n"); } else { tx_status("FAILsignature did not verify"); rx_cmd(); return; } } #endif if(!strcmp(ptn->name,"system") || !strcmp(ptn->name,"userdata")) { extra = 64; } else { kernel_size = (kernel_size + 2047) & (~2047); } dprintf("writing %d bytes to '%s'\n", kernel_size, ptn->name); cprintf("writing '%s' (%d bytes)", ptn->name, kernel_size); if(flash_write(ptn, extra, (void*) kernel_addr, kernel_size)) { tx_status("FAILflash write failure"); rx_cmd(); cprintf(" - FAIL\n"); return; } else { dprintf("partition '%s' updated\n", ptn->name); cprintf(" - OKAY\n"); } tx_status("OKAY"); rx_cmd(); return; } if(memcmp(cmdbuf, "boot", 4) == 0) { if(init_boot_linux()) { tx_status("FAILinvalid boot image"); rx_cmd(); return; } dprintf("booting linux...\n"); cprintf("\nbooting linux...\n"); tx_status("OKAY"); mdelay(10); usb_shutdown(); boot_linux(); return; } if(memcmp(cmdbuf, "signature", 9) == 0) { if (kernel_size != SIGNATURE_SIZE) { tx_status("FAILsignature not 256 bytes long"); rx_cmd(); return; } memcpy(signature, (void*)kernel_addr, SIGNATURE_SIZE); tx_status("OKAY"); rx_cmd(); return; } tx_status("FAILinvalid command"); rx_cmd(); }