freemyipod r227 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r226‎ | r227 | r228 >
Date:02:06, 26 October 2010
Author:theseven
Status:new
Tags:
Comment:
Add USB commands to access raw NAND on iPod Nano 2G
Modified paths:
  • /embios/trunk/SOURCES (modified) (history)
  • /embios/trunk/target/ipodnano2g/ftl.c (modified) (history)
  • /embios/trunk/target/ipodnano2g/target.h (modified) (history)
  • /embios/trunk/target/ipodnano2g/usbtarget.c (added) (history)
  • /embios/trunk/tools/embios.py (modified) (history)
  • /embios/trunk/tools/libembios.py (modified) (history)

Diff [purge]

Index: embios/trunk/tools/embios.py
@@ -672,6 +672,64 @@
673673 hash = ord(data)
674674 self.logger.info("The generated hash is "+self._hex(hash))
675675
 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+
676734 if __name__ == "__main__":
677735 if len(sys.argv) < 2:
678736 usage("No command specified")
Index: embios/trunk/tools/libembios.py
@@ -426,6 +426,30 @@
427427 """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
428428 return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
429429
 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+
430454
431455 class Lib(object):
432456 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 @@
22832283 else
22842284 for (j = 0; j < ppb; j++)
22852285 {
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);
22872287 if (ret & 2) break;
22882288 if (ret & 0x11F)
22892289 {
@@ -2315,6 +2315,26 @@
23162316 {
23172317 cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading vPage %d\n",
23182318 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");
23192339 return 1;
23202340 }
23212341 }
Index: embios/trunk/target/ipodnano2g/target.h
@@ -39,6 +39,7 @@
4040
4141 #define HAVE_USB
4242 #define USB_NUM_ENDPOINTS 5
 43+#define USB_HAVE_TARGET_SPECIFIC_REQUESTS
4344
4445 #define HAVE_LCD
4546 #define HAVE_LCD_SHUTDOWN
Index: embios/trunk/SOURCES
@@ -18,6 +18,7 @@
1919 target/ipodnano2g/clickwheel.c
2020 target/ipodnano2g/hwkeyaes.c
2121 target/ipodnano2g/hmacsha1.c
 22+target/ipodnano2g/usbtarget.c
2223 usb/synopsysotg.c
2324 #endif
2425

Follow-up revisions

RevisionCommit summaryAuthorDate
r229Fix a really silly bug from r227theseven02:45, 26 October 2010