| 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 |  |