Index: embios/trunk/tools/embios.py |
— | — | @@ -672,6 +672,64 @@ |
673 | 673 | hash = ord(data)
|
674 | 674 | self.logger.info("The generated hash is "+self._hex(hash))
|
675 | 675 |
|
| 676 | + @command
|
| 677 | + def ipodnano2g_getnandinfo(self):
|
| 678 | + """
|
| 679 | + Target-specific function: ipodnano2g
|
| 680 | + Gathers some information about the NAND chip used
|
| 681 | + """
|
| 682 | + data = self.embios.ipodnano2g_getnandinfo()
|
| 683 | + self.logger.info("NAND chip type: "+self._hex(data["type"])+"\n")
|
| 684 | + self.logger.info("Number of banks: "+str(data["banks"])+"\n")
|
| 685 | + self.logger.info("Number of blocks: "+str(data["blocks"])+"\n")
|
| 686 | + self.logger.info("Number of user blocks: "+str(data["userblocks"])+"\n")
|
| 687 | + self.logger.info("Pages per block: "+str(data["pagesperblock"]))
|
| 688 | +
|
| 689 | + @command
|
| 690 | + def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
|
| 691 | + """
|
| 692 | + Target-specific function: ipodnano2g
|
| 693 | + Reads data from the NAND chip into memory
|
| 694 | + """
|
| 695 | + addr = self._hexint(addr)
|
| 696 | + start = self._hexint(start)
|
| 697 | + count = self._hexint(count)
|
| 698 | + doecc = int(doecc)
|
| 699 | + checkempty = int(checkempty)
|
| 700 | + self.logger.info("Reading "+self._hex(count)+" NAND pages starting at "+self._hex(start)+" to "+self._hex(addr)+"...")
|
| 701 | + self.embios.lib.dev.timeout = 20000
|
| 702 | + self.embios.ipodnano2g_nandread(addr, start, count, doecc, checkempty)
|
| 703 | + self.logger.info("done\n")
|
| 704 | +
|
| 705 | + @command
|
| 706 | + def ipodnano2g_nandwrite(self, addr, start, count, doecc):
|
| 707 | + """
|
| 708 | + Target-specific function: ipodnano2g
|
| 709 | + Writes data to the NAND chip
|
| 710 | + """
|
| 711 | + addr = self._hexint(addr)
|
| 712 | + start = self._hexint(start)
|
| 713 | + count = self._hexint(count)
|
| 714 | + doecc = int(doecc)
|
| 715 | + self.logger.info("Writing "+self._hex(count)+" NAND pages starting at "+self._hex(start)+" from "+self._hex(addr)+"...")
|
| 716 | + self.embios.lib.dev.timeout = 20000
|
| 717 | + self.embios.ipodnano2g_nandwrite(addr, start, count, doecc)
|
| 718 | + self.logger.info("done\n")
|
| 719 | +
|
| 720 | + @command
|
| 721 | + def ipodnano2g_nanderase(self, addr, start, count):
|
| 722 | + """
|
| 723 | + Target-specific function: ipodnano2g
|
| 724 | + Erases blocks on the NAND chip and stores the results to memory
|
| 725 | + """
|
| 726 | + addr = self._hexint(addr)
|
| 727 | + start = self._hexint(start)
|
| 728 | + count = self._hexint(count)
|
| 729 | + self.logger.info("Erasing "+self._hex(count)+" NAND blocks starting at "+self._hex(start)+" and logging to "+self._hex(addr)+"...")
|
| 730 | + self.embios.lib.dev.timeout = 20000
|
| 731 | + self.embios.ipodnano2g_nanderase(addr, start, count)
|
| 732 | + self.logger.info("done\n")
|
| 733 | +
|
676 | 734 | if __name__ == "__main__":
|
677 | 735 | if len(sys.argv) < 2:
|
678 | 736 | usage("No command specified")
|
Index: embios/trunk/tools/libembios.py |
— | — | @@ -426,6 +426,30 @@ |
427 | 427 | """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
|
428 | 428 | return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
|
429 | 429 |
|
| 430 | + def ipodnano2g_getnandinfo(self):
|
| 431 | + """ Target-specific function: ipodnano2g
|
| 432 | + Gathers some information about the NAND chip used
|
| 433 | + """
|
| 434 | + return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
|
| 435 | +
|
| 436 | + def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
|
| 437 | + """ Target-specific function: ipodnano2g
|
| 438 | + Reads data from the NAND chip into memory
|
| 439 | + """
|
| 440 | + return self.lib.monitorcommand(struct.pack("IIII", 0xffff0002, addr | (0x80000000 if doecc != 0 else 0) | (0x40000000 if checkempty != 0 else 0), start, count), "III", (None, None, None))
|
| 441 | +
|
| 442 | + def ipodnano2g_nandwrite(self, addr, start, count, doecc):
|
| 443 | + """ Target-specific function: ipodnano2g
|
| 444 | + Writes data to the NAND chip
|
| 445 | + """
|
| 446 | + return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
|
| 447 | +
|
| 448 | + def ipodnano2g_nanderase(self, addr, start, count):
|
| 449 | + """ Target-specific function: ipodnano2g
|
| 450 | + Erases blocks on the NAND chip and stores the results to memory
|
| 451 | + """
|
| 452 | + return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
|
| 453 | +
|
430 | 454 |
|
431 | 455 | class Lib(object):
|
432 | 456 | def __init__(self):
|
Index: embios/trunk/target/ipodnano2g/usbtarget.c |
— | — | @@ -0,0 +1,121 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "usb/usbtarget.h"
|
| 27 | +#include "usb/usbdrv.h"
|
| 28 | +#include "nand.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +int usb_target_handle_request(uint32_t* buffer, int bufsize)
|
| 32 | +{
|
| 33 | + int size = 0;
|
| 34 | + switch (buffer[0])
|
| 35 | + {
|
| 36 | + case 0xffff0001: // GET NAND INFO
|
| 37 | + {
|
| 38 | + int banks = 1;
|
| 39 | + const struct nand_device_info_type* type = nand_get_device_type(0);
|
| 40 | + for (; banks < 4; banks++)
|
| 41 | + if (!nand_get_device_type(banks))
|
| 42 | + break;
|
| 43 | + buffer[0] = 1;
|
| 44 | + buffer[1] = type->id;
|
| 45 | + buffer[2] = (banks << 16) | type->pagesperblock;
|
| 46 | + buffer[3] = (type->blocks << 16) | type->userblocks;
|
| 47 | + size = 16;
|
| 48 | + break;
|
| 49 | + }
|
| 50 | + case 0xffff0002: // READ NAND PAGES
|
| 51 | + case 0xffff0003: // WRITE NAND PAGES
|
| 52 | + {
|
| 53 | + int banks = 1;
|
| 54 | + const struct nand_device_info_type* type = nand_get_device_type(0);
|
| 55 | + for (; banks < 4; banks++)
|
| 56 | + if (!nand_get_device_type(banks))
|
| 57 | + break;
|
| 58 | + uint32_t pagecount = banks * type->blocks * type->pagesperblock;
|
| 59 | + if (buffer[2] + buffer[3] > pagecount)
|
| 60 | + {
|
| 61 | + buffer[0] = 0xffff0001;
|
| 62 | + size = 16;
|
| 63 | + break;
|
| 64 | + }
|
| 65 | + int i;
|
| 66 | + uint32_t database = buffer[1] & ~0xc0000000;
|
| 67 | + uint32_t sparebase = database + buffer[3] * 2048;
|
| 68 | + uint32_t resultbase = sparebase + buffer[3] * 64;
|
| 69 | + int doecc = buffer[1] & 0x80000000;
|
| 70 | + int checkempty = buffer[1] & 0x40000000;
|
| 71 | + for (i = 0; i < buffer[3]; i++)
|
| 72 | + {
|
| 73 | + int lpage = buffer[2] + i;
|
| 74 | + int bank = lpage % banks;
|
| 75 | + int page = (lpage / banks) % type->pagesperblock;
|
| 76 | + int block = lpage / banks / type->pagesperblock;
|
| 77 | + int result;
|
| 78 | + if (buffer[0] == 0xffff0002)
|
| 79 | + result = nand_read_page(bank, page, (void*)(database + i * 2048),
|
| 80 | + (void*)(sparebase + i * 64), doecc, checkempty);
|
| 81 | + else if (buffer[0] == 0xffff0003)
|
| 82 | + result = nand_write_page(bank, page, (void*)(database + i * 2048),
|
| 83 | + (void*)(sparebase + i * 64), doecc);
|
| 84 | + *((int*)(resultbase + i * 4)) = result;
|
| 85 | + }
|
| 86 | + buffer[0] = 1;
|
| 87 | + size = 16;
|
| 88 | + break;
|
| 89 | + }
|
| 90 | + case 0xffff0004: // ERASE NAND PAGES
|
| 91 | + {
|
| 92 | + int banks = 1;
|
| 93 | + const struct nand_device_info_type* type = nand_get_device_type(0);
|
| 94 | + for (; banks < 4; banks++)
|
| 95 | + if (!nand_get_device_type(banks))
|
| 96 | + break;
|
| 97 | + uint32_t blockcount = banks * type->blocks;
|
| 98 | + if (buffer[2] + buffer[3] > blockcount)
|
| 99 | + {
|
| 100 | + buffer[0] = 0xffff0001;
|
| 101 | + size = 16;
|
| 102 | + break;
|
| 103 | + }
|
| 104 | + int i;
|
| 105 | + for (i = 0; i < buffer[3]; i++)
|
| 106 | + {
|
| 107 | + int lblock = buffer[2] + i;
|
| 108 | + int bank = lblock % banks;
|
| 109 | + int block = lblock / banks;
|
| 110 | + int result = nand_block_erase(bank, block * type->pagesperblock);
|
| 111 | + *((int*)(buffer[1] + i * 4)) = result;
|
| 112 | + }
|
| 113 | + buffer[0] = 1;
|
| 114 | + size = 16;
|
| 115 | + break;
|
| 116 | + }
|
| 117 | + default:
|
| 118 | + buffer[0] = 2;
|
| 119 | + size = 16;
|
| 120 | + }
|
| 121 | + return size;
|
| 122 | +} |
\ No newline at end of file |
Index: embios/trunk/target/ipodnano2g/ftl.c |
— | — | @@ -2282,7 +2282,7 @@ |
2283 | 2283 | else
|
2284 | 2284 | for (j = 0; j < ppb; j++)
|
2285 | 2285 | {
|
2286 | | - ret = ftl_vfl_read(i * ppb + j, 0, &ftl_sparebuffer[0], 1, 0);
|
| 2286 | + ret = ftl_vfl_read(i * ppb + j, ftl_buffer, &ftl_sparebuffer[0], 1, 0);
|
2287 | 2287 | if (ret & 2) break;
|
2288 | 2288 | if (ret & 0x11F)
|
2289 | 2289 | {
|
— | — | @@ -2315,6 +2315,26 @@ |
2316 | 2316 | {
|
2317 | 2317 | cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading vPage %d\n",
|
2318 | 2318 | ftl_sparebuffer[0].meta.type, i * ppb + j);
|
| 2319 | + for (i = 0; i < 64; i += 8)
|
| 2320 | + cprintf(CONSOLE_BOOT, "%02X %02X %02X %02X %02X %02X %02X %02X\n",
|
| 2321 | + ((uint8_t*)(ftl_sparebuffer))[i], ((uint8_t*)(ftl_sparebuffer))[i + 1], ((uint8_t*)(ftl_sparebuffer))[i + 2], ((uint8_t*)(ftl_sparebuffer))[i + 3],
|
| 2322 | + ((uint8_t*)(ftl_sparebuffer))[i + 4], ((uint8_t*)(ftl_sparebuffer))[i + 5], ((uint8_t*)(ftl_sparebuffer))[i + 6], ((uint8_t*)(ftl_sparebuffer))[i + 7]);
|
| 2323 | + for (i = 0; i < 2048; i += 16)
|
| 2324 | + cprintf(CONSOLE_BOOT, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
| 2325 | + ftl_buffer[i], ftl_buffer[i + 1], ftl_buffer[i + 2], ftl_buffer[i + 3], ftl_buffer[i + 4], ftl_buffer[i + 5], ftl_buffer[i + 6], ftl_buffer[i + 7],
|
| 2326 | + ftl_buffer[i + 8], ftl_buffer[i + 9], ftl_buffer[i + 10], ftl_buffer[i + 11], ftl_buffer[i + 12], ftl_buffer[i + 13], ftl_buffer[i + 14], ftl_buffer[i + 15]);
|
| 2327 | + cprintf(CONSOLE_BOOT, "Remaps:");
|
| 2328 | + for (j = 0; j < ftl_banks; j++)
|
| 2329 | + {
|
| 2330 | + cprintf(CONSOLE_BOOT, "\nBank %d", j);
|
| 2331 | + for (i = 0; i < ftl_vfl_cxt[j].spareused; i++)
|
| 2332 | + {
|
| 2333 | + cprintf(CONSOLE_BOOT, ": %d => %d ",
|
| 2334 | + ftl_vfl_cxt[j].remaptable[i], ftl_vfl_cxt[j].firstspare + i);
|
| 2335 | + if (ftl_vfl_is_good_block(j, i) != 1) cprintf(CONSOLE_BOOT, "(NOT IN BBT) ");
|
| 2336 | + }
|
| 2337 | + }
|
| 2338 | + cprintf(CONSOLE_BOOT, "\n");
|
2319 | 2339 | return 1;
|
2320 | 2340 | }
|
2321 | 2341 | }
|
Index: embios/trunk/target/ipodnano2g/target.h |
— | — | @@ -39,6 +39,7 @@ |
40 | 40 |
|
41 | 41 | #define HAVE_USB
|
42 | 42 | #define USB_NUM_ENDPOINTS 5
|
| 43 | +#define USB_HAVE_TARGET_SPECIFIC_REQUESTS
|
43 | 44 |
|
44 | 45 | #define HAVE_LCD
|
45 | 46 | #define HAVE_LCD_SHUTDOWN
|
Index: embios/trunk/SOURCES |
— | — | @@ -18,6 +18,7 @@ |
19 | 19 | target/ipodnano2g/clickwheel.c
|
20 | 20 | target/ipodnano2g/hwkeyaes.c
|
21 | 21 | target/ipodnano2g/hmacsha1.c
|
| 22 | +target/ipodnano2g/usbtarget.c
|
22 | 23 | usb/synopsysotg.c
|
23 | 24 | #endif
|
24 | 25 |
|