freemyipod r346 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r345‎ | r346 | r347 >
Date:02:23, 20 December 2010
Author:theseven
Status:new
Tags:
Comment:
emBIOS: Expose disk and file system access APIs to the USB interface
Modified paths:
  • /embios/trunk/SOURCES (modified) (history)
  • /embios/trunk/target/ipodclassic/target.h (modified) (history)
  • /embios/trunk/target/ipodclassic/usbtarget.c (added) (history)
  • /embios/trunk/tools/embios.py (modified) (history)
  • /embios/trunk/tools/libembios.py (modified) (history)
  • /embios/trunk/usb/usb.c (modified) (history)

Diff [purge]

Index: embios/trunk/tools/embios.py
@@ -27,6 +27,7 @@
2828 import re
2929 import time
3030 import struct
 31+import locale
3132
3233 from functools import wraps
3334
@@ -478,6 +479,8 @@
479480 self.logger.info(" Thread id: "+str(thread.id)+"\n")
480481 self.logger.info(" Thread type: "+thread.type+"\n")
481482 self.logger.info(" Thread state: "+thread.state+"\n")
 483+ self.logger.info(" Block type: "+thread.block_type+"\n")
 484+ self.logger.info(" Blocked by: "+self._hex(thread.blocked_by_ptr)+"\n")
482485 self.logger.info(" Priority: "+str(thread.priority)+"/256\n")
483486 self.logger.info(" Current CPU load: "+str((thread.cpuload*100)/255)+"%\n")
484487 self.logger.info(" CPU time (total): "+str(datetime.timedelta(microseconds=thread.cputime_total))+"\n")
@@ -803,6 +806,119 @@
804807 statusfile.close()
805808 self.logger.info("done\n")
806809
 810+ @command
 811+ def ipodclassic_writebbt(self, tempaddr, filename):
 812+ """
 813+ Target-specific function: ipodclassic
 814+ Uploads the bad block table <filename> to
 815+ memory at <tempaddr> and writes it to the hard disk
 816+ """
 817+ tempaddr = self._hexint(tempaddr)
 818+ try:
 819+ f = open(filename, 'rb')
 820+ except IOError:
 821+ raise ArgumentError("File not readable. Does it exist?")
 822+ self.embios.lib.dev.timeout = 30000
 823+ self.logger.info("Writing bad block table to disk...")
 824+ data = self.embios.ipodclassic_writebbt(f.read(), tempaddr)
 825+ f.close()
 826+ self.logger.info(" done\n")
 827+
 828+ @command
 829+ def mkdir(self, dirname):
 830+ """
 831+ Creates a directory
 832+ """
 833+ self.embios.lib.dev.timeout = 30000
 834+ self.logger.info("Creating directory " + dirname + "...")
 835+ self.embios.dir_create(dirname)
 836+ self.logger.info(" done\n")
 837+
 838+ @command
 839+ def rmdir(self, dirname):
 840+ """
 841+ Removes an empty directory
 842+ """
 843+ self.embios.lib.dev.timeout = 30000
 844+ self.logger.info("Removing directory " + dirname + "...")
 845+ self.embios.dir_remove(dirname)
 846+ self.logger.info(" done\n")
 847+
 848+ @command
 849+ def unlink(self, filename):
 850+ """
 851+ Removes a file
 852+ """
 853+ self.embios.lib.dev.timeout = 30000
 854+ self.logger.info("Removing file " + filename + "...")
 855+ self.embios.file_unlink(filename)
 856+ self.logger.info(" done\n")
 857+
 858+ @command
 859+ def get(self, buffer, buffsize, remotename, localname):
 860+ """
 861+ Downloads a file
 862+ """
 863+ buffer = self._hexint(buffer)
 864+ buffsize = self._hexint(buffsize)
 865+ try:
 866+ f = open(localname, 'wb')
 867+ except IOError:
 868+ raise ArgumentError("Could not open local file for writing.")
 869+ self.embios.lib.dev.timeout = 30000
 870+ self.logger.info("Downloading file " + remotename + " to " + localname + "...")
 871+ fd = self.embios.file_open(remotename, 0)
 872+ size = self.embios.file_size(fd)
 873+ while size > 0:
 874+ bytes = self.embios.file_read(fd, buffer, buffsize)
 875+ f.write(self.embios.read(buffer, bytes))
 876+ size = size - bytes
 877+ self.embios.file_close(fd)
 878+ f.close()
 879+ self.logger.info(" done\n")
 880+
 881+ @command
 882+ def put(self, buffer, buffsize, localname, remotename):
 883+ """
 884+ Uploads a file
 885+ """
 886+ buffer = self._hexint(buffer)
 887+ buffsize = self._hexint(buffsize)
 888+ try:
 889+ f = open(localname, 'rb')
 890+ except IOError:
 891+ raise ArgumentError("Could not open local file for reading.")
 892+ self.embios.lib.dev.timeout = 30000
 893+ self.logger.info("Uploading file " + localname + " to " + remotename + "...")
 894+ fd = self.embios.file_open(remotename, 0x15)
 895+ while True:
 896+ data = f.read(buffsize)
 897+ if len(data) == 0: break
 898+ self.embios.write(buffer, data)
 899+ bytes = 0
 900+ while bytes < len(data):
 901+ bytes = bytes + self.embios.file_write(fd, buffer + bytes, len(data) - bytes)
 902+ self.embios.file_close(fd)
 903+ f.close()
 904+ self.logger.info(" done\n")
 905+
 906+ @command
 907+ def ls(self, path):
 908+ """
 909+ Lists all files in the specified path
 910+ """
 911+ self.embios.lib.dev.timeout = 30000
 912+ handle = self.embios.dir_open(path)
 913+ self.logger.info("Directory listing of " + path + ":\n")
 914+ while True:
 915+ try:
 916+ entry = self.embios.dir_read(handle)
 917+ if entry.attributes & 0x10: size = "DIR"
 918+ else: size = locale.format("%d", entry.size, True).rjust(13)
 919+ self.logger.info(entry.name.ljust(50) + " - " + size + "\n")
 920+ except: break
 921+ self.embios.dir_close(handle)
 922+
807923 if __name__ == "__main__":
808924 if len(sys.argv) < 2:
809925 usage("No command specified")
Index: embios/trunk/tools/libembios.py
@@ -404,7 +404,7 @@
405405
406406 def execimage(self, addr):
407407 """ Runs the emBIOS app at 'addr' """
408 - return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None))
 408+ return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("rc", None, None))
409409
410410 def run(self, app):
411411 """ Uploads and runs the emBIOS app in the string 'app' """
@@ -471,6 +471,7 @@
472472 """ Target-specific function: ipodnano2g
473473 Gathers some information about the NAND chip used
474474 """
 475+ if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
475476 return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
476477
477478 def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
@@ -477,6 +478,7 @@
478479 """ Target-specific function: ipodnano2g
479480 Reads data from the NAND chip into memory
480481 """
 482+ if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
481483 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))
482484
483485 def ipodnano2g_nandwrite(self, addr, start, count, doecc):
@@ -483,6 +485,7 @@
484486 """ Target-specific function: ipodnano2g
485487 Writes data to the NAND chip
486488 """
 489+ if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
487490 return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
488491
489492 def ipodnano2g_nanderase(self, addr, start, count):
@@ -489,9 +492,230 @@
490493 """ Target-specific function: ipodnano2g
491494 Erases blocks on the NAND chip and stores the results to memory
492495 """
 496+ if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
493497 return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
494498
 499+ def ipodclassic_gethddinfo(self):
 500+ """ Target-specific function: ipodclassic
 501+ Gather information about the hard disk drive
 502+ """
 503+ if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
 504+ return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IQQII", ("identifyptr", "totalsectors", "virtualsectors", "bbtptr", "bbtsize"))
 505+
 506+ def ipodclassic_hddaccess(self, type, sector, count, addr):
 507+ """ Target-specific function: ipodclassic
 508+ Access the hard disk, type = 0 (read) / 1 (write)
 509+ """
 510+ if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
 511+ rc = self.lib.monitorcommand(struct.pack("IIQIIII", 0xffff0002, type, sector, count, addr, 0, 0), "III", ("rc", None, None))
 512+ if (rc > 0x80000000):
 513+ raise DeviceError("HDD access (type=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (type, sector, count, addr, rc))
 514+
 515+ def ipodclassic_writebbt(self, bbt, tempaddr):
 516+ """ Target-specific function: ipodclassic
 517+ Write hard drive bad block table
 518+ """
 519+ if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
 520+ try:
 521+ bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
 522+ except struct.error:
 523+ raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
 524+ if bbtheader[0] != "emBIbbth":
 525+ raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
 526+ virtualsectors = bbtheader[2]
 527+ bbtsectors = bbtheader[3]
 528+ self.write(tempaddr, bbt)
 529+ sector = 0
 530+ count = 1
 531+ offset = 0
 532+ for i in range(bbtsectors):
 533+ if bbtheader[4][i] == sector + count:
 534+ count = count + 1
 535+ else:
 536+ self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
 537+ offset = offset + count * 4096
 538+ sector = bbtheader[4][i]
 539+ count = 1
 540+ self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
 541+
 542+ def storage_get_info(self):
 543+ """ Get information about a storage device """
 544+ result = self.lib.monitorcommand(struct.pack("IIII", 27, 0, 0, 0), "IIIIIIII", ("version", None, None, "sectorsize", "numsectors", "vendorptr", "productptr", "revisionptr"))
 545+ if result.version != 1:
 546+ raise ValueError("Unknown version of storage_info struct: %d" % result.version)
 547+ return result
 548+
 549+ def storage_read_sectors_md(self, volume, sector, count, addr):
 550+ """ Read sectors from as storage device """
 551+ result = self.lib.monitorcommand(struct.pack("IIQIIII", 28, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
 552+ if result.rc > 0x80000000:
 553+ raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
495554
 555+ def storage_write_sectors_md(self, volume, sector, count, addr):
 556+ """ Read sectors from as storage device """
 557+ result = self.lib.monitorcommand(struct.pack("IIQIIII", 29, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
 558+ if result.rc > 0x80000000:
 559+ raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
 560+
 561+ def file_open(self, filename, mode):
 562+ """ Opens a file and returns the handle """
 563+ result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 30, mode, 0, 0, filename, 0), "III", ("fd", None, None))
 564+ if result.fd > 0x80000000:
 565+ raise DeviceError("file_open(filename=\"%s\", mode=0x%X) failed with RC=0x%08X, errno=%d" % (filename, mode, result.fd, self.errno()))
 566+ return result.fd
 567+
 568+ def file_size(self, fd):
 569+ """ Gets the size of a file referenced by a handle """
 570+ result = self.lib.monitorcommand(struct.pack("IIII", 31, fd, 0, 0), "III", ("size", None, None))
 571+ if result.size > 0x80000000:
 572+ raise DeviceError("file_size(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.size, self.errno()))
 573+ return result.size
 574+
 575+ def file_read(self, fd, addr, size):
 576+ """ Reads data from a file referenced by a handle """
 577+ result = self.lib.monitorcommand(struct.pack("IIII", 32, fd, addr, size), "III", ("rc", None, None))
 578+ if result.rc > 0x80000000:
 579+ raise DeviceError("file_read(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
 580+ return result.rc
 581+
 582+ def file_write(self, fd, addr, size):
 583+ """ Writes data from a file referenced by a handle """
 584+ result = self.lib.monitorcommand(struct.pack("IIII", 33, fd, addr, size), "III", ("rc", None, None))
 585+ if result.rc > 0x80000000:
 586+ raise DeviceError("file_write(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
 587+ return result.rc
 588+
 589+ def file_seek(self, fd, offset, whence):
 590+ """ Seeks the file handle to the specified position in the file """
 591+ result = self.lib.monitorcommand(struct.pack("IIII", 34, fd, offset, whence), "III", ("rc", None, None))
 592+ if result.rc > 0x80000000:
 593+ raise DeviceError("file_seek(fd=%d, offset=0x%08X, whence=%d) failed with RC=0x%08X, errno=%d" % (fd, offset, whence, result.rc, self.errno()))
 594+ return result.rc
 595+
 596+ def file_truncate(self, fd, length):
 597+ """ Truncates a file referenced by a handle to a specified length """
 598+ result = self.lib.monitorcommand(struct.pack("IIII", 35, fd, offset, 0), "III", ("rc", None, None))
 599+ if result.rc > 0x80000000:
 600+ raise DeviceError("file_truncate(fd=%d, length=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, length, result.rc, self.errno()))
 601+ return result.rc
 602+
 603+ def file_sync(self, fd):
 604+ """ Flushes a file handles' buffers """
 605+ result = self.lib.monitorcommand(struct.pack("IIII", 36, fd, 0, 0), "III", ("rc", None, None))
 606+ if result.rc > 0x80000000:
 607+ raise DeviceError("file_sync(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
 608+ return result.rc
 609+
 610+ def file_close(self, fd):
 611+ """ Closes a file handle """
 612+ result = self.lib.monitorcommand(struct.pack("IIII", 37, fd, 0, 0), "III", ("rc", None, None))
 613+ if result.rc > 0x80000000:
 614+ raise DeviceError("file_close(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
 615+ return result.rc
 616+
 617+ def file_close_all(self):
 618+ """ Closes all file handles opened through the debugger """
 619+ result = self.lib.monitorcommand(struct.pack("IIII", 38, 0, 0, 0), "III", ("rc", None, None))
 620+ if result.rc > 0x80000000:
 621+ raise DeviceError("file_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
 622+ return result.rc
 623+
 624+ def file_kill_all(self):
 625+ """ Kills all file handles (in the whole system) """
 626+ result = self.lib.monitorcommand(struct.pack("IIII", 39, 0, 0, 0), "III", ("rc", None, None))
 627+ if result.rc > 0x80000000:
 628+ raise DeviceError("file_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
 629+ return result.rc
 630+
 631+ def file_unlink(self, filename):
 632+ """ Removes a file """
 633+ result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 40, 0, 0, 0, filename, 0), "III", ("rc", None, None))
 634+ if result.rc > 0x80000000:
 635+ raise DeviceError("file_unlink(filename=\"%s\") failed with RC=0x%08X, errno=%d" % (filename, result.rc, self.errno()))
 636+ return result.rc
 637+
 638+ def file_rename(self, oldname, newname):
 639+ """ Renames a file """
 640+ result = self.lib.monitorcommand(struct.pack("IIII248s%dsB" % min(247, len(newname)), 41, 0, 0, 0, oldname, newname, 0), "III", ("rc", None, None))
 641+ if result.rc > 0x80000000:
 642+ raise DeviceError("file_rename(oldname=\"%s\", newname=\"%s\") failed with RC=0x%08X, errno=%d" % (oldname, newname, result.rc, self.errno()))
 643+ return result.rc
 644+
 645+ def dir_open(self, dirname):
 646+ """ Opens a directory and returns the handle """
 647+ result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 42, 0, 0, 0, dirname, 0), "III", ("handle", None, None))
 648+ if result.handle == 0:
 649+ raise DeviceError("dir_open(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.handle, self.errno()))
 650+ return result.handle
 651+
 652+ def dir_read(self, handle):
 653+ """ Reads the next entry from a directory """
 654+ result = self.lib.monitorcommand(struct.pack("IIII", 43, handle, 0, 0), "III", ("version", "maxpath", "ptr"))
 655+ if result.ptr == 0:
 656+ raise DeviceError("dir_read(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.ptr, self.errno()))
 657+ if result.version != 1:
 658+ raise ValueError("Unknown version of dirent struct: %d" % result.version)
 659+ dirent = self.read(result.ptr, result.maxpath + 16)
 660+ ret = Bunch()
 661+ (ret.name, ret.attributes, ret.size, ret.startcluster, ret.wrtdate, ret.wrttime) = struct.unpack("%dsIIIHH" % result.maxpath, dirent)
 662+ ret.name = ret.name[:ret.name.index('\x00')]
 663+ return ret
 664+
 665+ def dir_close(self, handle):
 666+ """ Closes a directory handle """
 667+ result = self.lib.monitorcommand(struct.pack("IIII", 44, handle, 0, 0), "III", ("rc", None, None))
 668+ if result.rc > 0x80000000:
 669+ raise DeviceError("dir_close(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.rc, self.errno()))
 670+ return result.rc
 671+
 672+ def dir_close_all(self):
 673+ """ Closes all directory handles opened through the debugger """
 674+ result = self.lib.monitorcommand(struct.pack("IIII", 45, 0, 0, 0), "III", ("rc", None, None))
 675+ if result.rc > 0x80000000:
 676+ raise DeviceError("dir_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
 677+ return result.rc
 678+
 679+ def dir_kill_all(self):
 680+ """ Kills all directory handles (in the whole system) """
 681+ result = self.lib.monitorcommand(struct.pack("IIII", 46, 0, 0, 0), "III", ("rc", None, None))
 682+ if result.rc > 0x80000000:
 683+ raise DeviceError("dir_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
 684+ return result.rc
 685+
 686+ def dir_create(self, dirname):
 687+ """ Creates a directory """
 688+ result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 47, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
 689+ if result.rc > 0x80000000:
 690+ raise DeviceError("dir_create(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
 691+ return result.rc
 692+
 693+ def dir_remove(self, dirname):
 694+ """ Removes an (empty) directory """
 695+ result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 48, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
 696+ if result.rc > 0x80000000:
 697+ raise DeviceError("dir_remove(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
 698+ return result.rc
 699+
 700+ def errno(self):
 701+ """ Returns the number of the last error that happened """
 702+ result = self.lib.monitorcommand(struct.pack("IIII", 49, 0, 0, 0), "III", ("errno", None, None))
 703+ return result.errno
 704+
 705+ def disk_mount(self, volume):
 706+ """ Mounts a volume """
 707+ result = self.lib.monitorcommand(struct.pack("IIII", 50, volume, 0, 0), "III", ("rc", None, None))
 708+ if result.rc > 0x80000000:
 709+ raise DeviceError("disk_mount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
 710+ return result.rc
 711+
 712+ def disk_unmount(self, volume):
 713+ """ Unmounts a volume """
 714+ result = self.lib.monitorcommand(struct.pack("IIII", 51, volume, 0, 0), "III", ("rc", None, None))
 715+ if result.rc > 0x80000000:
 716+ raise DeviceError("disk_unmount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
 717+ return result.rc
 718+
 719+
496720 class Lib(object):
497721 def __init__(self):
498722 self.idVendor = 0xFFFF
@@ -655,4 +879,4 @@
656880 if readdata == datastr:
657881 sys.stdout.write("Data matches!")
658882 else:
659 - sys.stdout.write("Data does NOT match. Something got wrong")
\ No newline at end of file
 883+ sys.stdout.write("Data does NOT match. Something went wrong")
\ No newline at end of file
Index: embios/trunk/target/ipodclassic/usbtarget.c
@@ -0,0 +1,69 @@
 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 "storage_ata-target.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 DISK INFO
 37+ {
 38+ buffer[0] = 1;
 39+ buffer[1] = (uint32_t)ata_identify_data;
 40+ buffer[2] = ata_total_sectors;
 41+ buffer[3] = ata_total_sectors >> 32;
 42+#ifdef ATA_HAVE_BBT
 43+ buffer[4] = ata_virtual_sectors;
 44+ buffer[5] = ata_virtual_sectors >> 32;
 45+ buffer[6] = (uint32_t)ata_bbt;
 46+ buffer[7] = ATA_BBT_PAGES << 6;
 47+#else
 48+ buffer[4] = ata_total_sectors;
 49+ buffer[5] = ata_total_sectors >> 32;
 50+ buffer[6] = 0;
 51+ buffer[7] = 0;
 52+#endif
 53+ size = 32;
 54+ break;
 55+ }
 56+ case 0xffff0002: // LOWLEVEL DISK ACCESS
 57+ {
 58+ int rc = ata_rw_sectors_internal((((uint64_t)(buffer[3])) << 32) | buffer[2],
 59+ buffer[4], (void*)(buffer[5]), (bool)(buffer[1]));
 60+ buffer[0] = 1;
 61+ buffer[1] = (uint32_t)rc;
 62+ size = 16;
 63+ break;
 64+ }
 65+ default:
 66+ buffer[0] = 2;
 67+ size = 16;
 68+ }
 69+ return size;
 70+}
\ No newline at end of file
Index: embios/trunk/target/ipodclassic/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
@@ -55,6 +55,7 @@
5656
5757 #ifdef TARGET_ipodclassic
5858 target/ipodclassic/storage_ata.c
 59+target/ipodclassic/usbtarget.c
5960 #endif
6061
6162 #ifdef ARM_ARCH
Index: embios/trunk/usb/usb.c
@@ -49,6 +49,13 @@
5050 #ifdef USB_HAVE_TARGET_SPECIFIC_REQUESTS
5151 #include "usbtarget.h"
5252 #endif
 53+#ifdef HAVE_STORAGE
 54+#include "storage.h"
 55+#include "disk.h"
 56+#include "file.h"
 57+#include "dir.h"
 58+#include "errno.h"
 59+#endif
5360
5461
5562 static uint8_t ctrlresp[2] CACHEALIGN_ATTR;
@@ -73,12 +80,14 @@
7481 DBGACTION_WRITEBOOTFLASH,
7582 DBGACTION_HWKEYAES,
7683 DBGACTION_HMACSHA1,
77 - DBGACTION_TARGETSPECIFIC
 84+ DBGACTION_TARGETSPECIFIC,
 85+ DBGACTION_STORAGE
7886 };
7987
80 -static uint32_t dbgstack[0x100] STACK_ATTR;
 88+static uint32_t dbgstack[0x200] STACK_ATTR;
8189 struct wakeup dbgwakeup IBSS_ATTR;
8290 extern struct scheduler_thread* scheduler_threads;
 91+extern struct scheduler_thread* current_thread;
8392 static enum dbgaction_t dbgaction IBSS_ATTR;
8493 static int dbgi2cbus;
8594 static int dbgi2cslave;
@@ -580,6 +589,38 @@
581590 dbgactionoffset = dbgrecvbuf[3];
582591 break;
583592 #endif
 593+#ifdef HAVE_STORAGE
 594+ case 27: // STORAGE_GET_INFO
 595+ case 28: // STORAGE_READ_SECTORS_MD
 596+ case 29: // STORAGE_WRITE_SECTORS_MD
 597+ case 30: // FILE_OPEN
 598+ case 31: // FILESIZE
 599+ case 32: // READ
 600+ case 33: // WRITE
 601+ case 34: // LSEEK
 602+ case 35: // FTRUNCATE
 603+ case 36: // FSYNC
 604+ case 37: // CLOSE
 605+ case 38: // CLOSE_MONITOR_FILES
 606+ case 39: // RELEASE_FILES
 607+ case 40: // REMOVE
 608+ case 41: // RENAME
 609+ case 42: // OPENDIR
 610+ case 43: // READDIR
 611+ case 44: // CLOSEDIR
 612+ case 45: // CLOSE_MONITOR_DIRS
 613+ case 46: // RELEASE_DIRS
 614+ case 47: // MKDIR
 615+ case 48: // RMDIR
 616+ case 49: // ERRNO
 617+#ifdef HAVE_HOTSWAP
 618+ case 50: // DISK_MOUNT
 619+ case 51: // DISK_UNMOUNT
 620+#endif
 621+ if (!set_dbgaction(DBGACTION_STORAGE, 0))
 622+ memcpy(dbgasyncsendbuf, dbgrecvbuf, sizeof(dbgasyncsendbuf));
 623+ break;
 624+#endif
584625 default:
585626 dbgsendbuf[0] = 2;
586627 size = 16;
@@ -708,6 +749,170 @@
709750 break;
710751 }
711752 #endif
 753+#ifdef HAVE_STORAGE
 754+ case DBGACTION_STORAGE:
 755+ switch(dbgasyncsendbuf[0])
 756+ {
 757+ case 27: // STORAGE_GET_INFO
 758+ dbgasyncsendbuf[0] = 1;
 759+ storage_get_info(dbgasyncsendbuf[1],
 760+ (struct storage_info*)&dbgasyncsendbuf[4]);
 761+ dbgasyncsendbuf[1] = 1;
 762+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf,
 763+ 16 + sizeof(struct storage_info));
 764+ break;
 765+ case 28: // STORAGE_READ_SECTORS_MD
 766+ {
 767+ dbgasyncsendbuf[0] = 1;
 768+ int rc = storage_read_sectors_md(dbgasyncsendbuf[1],
 769+ dbgasyncsendbuf[2]
 770+ | (((uint64_t)(dbgasyncsendbuf[3]) << 32)),
 771+ dbgasyncsendbuf[4],
 772+ (void*)(dbgasyncsendbuf[5]));
 773+ dbgasyncsendbuf[1] = (uint32_t)rc;
 774+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 775+ break;
 776+ }
 777+ case 29: // STORAGE_WRITE_SECTORS_MD
 778+ {
 779+ dbgasyncsendbuf[0] = 1;
 780+ int rc = storage_write_sectors_md(dbgasyncsendbuf[1],
 781+ dbgasyncsendbuf[2]
 782+ | (((uint64_t)(dbgasyncsendbuf[3]) << 32)),
 783+ dbgasyncsendbuf[4],
 784+ (void*)(dbgasyncsendbuf[5]));
 785+ dbgasyncsendbuf[1] = (uint32_t)rc;
 786+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 787+ break;
 788+ }
 789+ case 30: // FILE_OPEN
 790+ {
 791+ dbgasyncsendbuf[0] = 1;
 792+ int fd = file_open((char*)(&dbgasyncsendbuf[4]), (int)(dbgasyncsendbuf[1]));
 793+ dbgasyncsendbuf[1] = (uint32_t)fd;
 794+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 795+ break;
 796+ }
 797+ case 31: // FILESIZE
 798+ dbgasyncsendbuf[0] = 1;
 799+ dbgasyncsendbuf[1] = (uint32_t)filesize((int)(dbgasyncsendbuf[1]));
 800+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 801+ break;
 802+ case 32: // READ
 803+ dbgasyncsendbuf[0] = 1;
 804+ dbgasyncsendbuf[1] = (uint32_t)read((int)(dbgasyncsendbuf[1]),
 805+ (void*)(dbgasyncsendbuf[2]),
 806+ (size_t)(dbgasyncsendbuf[3]));
 807+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 808+ break;
 809+ case 33: // WRITE
 810+ dbgasyncsendbuf[0] = 1;
 811+ dbgasyncsendbuf[1] = (uint32_t)write((int)(dbgasyncsendbuf[1]),
 812+ (void*)(dbgasyncsendbuf[2]),
 813+ (size_t)(dbgasyncsendbuf[3]));
 814+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 815+ break;
 816+ case 34: // LSEEK
 817+ dbgasyncsendbuf[0] = 1;
 818+ dbgasyncsendbuf[1] = (uint32_t)lseek((int)(dbgasyncsendbuf[1]),
 819+ (off_t)(dbgasyncsendbuf[2]),
 820+ (int)(dbgasyncsendbuf[3]));
 821+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 822+ break;
 823+ case 35: // FTRUNCATE
 824+ dbgasyncsendbuf[0] = 1;
 825+ dbgasyncsendbuf[1] = (uint32_t)ftruncate((int)(dbgasyncsendbuf[1]),
 826+ (off_t)(dbgasyncsendbuf[2]));
 827+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 828+ break;
 829+ case 36: // FSYNC
 830+ dbgasyncsendbuf[0] = 1;
 831+ dbgasyncsendbuf[1] = (uint32_t)fsync((int)(dbgasyncsendbuf[1]));
 832+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 833+ break;
 834+ case 37: // CLOSE
 835+ dbgasyncsendbuf[0] = 1;
 836+ dbgasyncsendbuf[1] = (uint32_t)close((int)(dbgasyncsendbuf[1]));
 837+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 838+ break;
 839+ case 38: // CLOSE_MONITOR_FILES
 840+ dbgasyncsendbuf[0] = 1;
 841+ dbgasyncsendbuf[1] = (uint32_t)close_all_of_process(current_thread);
 842+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 843+ break;
 844+ case 39: // RELEASE_FILES
 845+ dbgasyncsendbuf[0] = 1;
 846+ dbgasyncsendbuf[1] = (uint32_t)release_files((int)(dbgasyncsendbuf[1]));
 847+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 848+ break;
 849+ case 40: // REMOVE
 850+ dbgasyncsendbuf[0] = 1;
 851+ dbgasyncsendbuf[1] = (uint32_t)remove((char*)(&dbgasyncsendbuf[4]));
 852+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 853+ break;
 854+ case 41: // RENAME
 855+ dbgasyncsendbuf[0] = 1;
 856+ dbgasyncsendbuf[1] = (uint32_t)rename((char*)(&dbgasyncsendbuf[4]),
 857+ (char*)(&dbgasyncsendbuf[66]));
 858+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 859+ break;
 860+ case 42: // OPENDIR
 861+ dbgasyncsendbuf[0] = 1;
 862+ dbgasyncsendbuf[1] = (uint32_t)opendir((char*)(&dbgasyncsendbuf[4]));
 863+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 864+ break;
 865+ case 43: // READDIR
 866+ dbgasyncsendbuf[0] = 1;
 867+ dbgasyncsendbuf[3] = (uint32_t)readdir((DIR*)(dbgasyncsendbuf[1]));
 868+ dbgasyncsendbuf[1] = 1;
 869+ dbgasyncsendbuf[2] = MAX_PATH;
 870+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 871+ break;
 872+ case 44: // CLOSEDIR
 873+ dbgasyncsendbuf[0] = 1;
 874+ dbgasyncsendbuf[1] = (uint32_t)closedir((DIR*)(dbgasyncsendbuf[1]));
 875+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 876+ break;
 877+ case 45: // CLOSE_MONITOR_DIRS
 878+ dbgasyncsendbuf[0] = 1;
 879+ dbgasyncsendbuf[1] = (uint32_t)closedir_all_of_process(current_thread);
 880+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 881+ break;
 882+ case 46: // RELEASE_DIRS
 883+ dbgasyncsendbuf[0] = 1;
 884+ dbgasyncsendbuf[1] = (uint32_t)release_dirs((int)(dbgasyncsendbuf[1]));
 885+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 886+ break;
 887+ case 47: // MKDIR
 888+ dbgasyncsendbuf[0] = 1;
 889+ dbgasyncsendbuf[1] = (uint32_t)mkdir((char*)(&dbgasyncsendbuf[4]));
 890+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 891+ break;
 892+ case 48: // RMDIR
 893+ dbgasyncsendbuf[0] = 1;
 894+ dbgasyncsendbuf[1] = (uint32_t)rmdir((char*)(&dbgasyncsendbuf[4]));
 895+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 896+ break;
 897+ case 49: // ERRNO
 898+ dbgasyncsendbuf[0] = 1;
 899+ dbgasyncsendbuf[1] = (uint32_t)errno;
 900+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 901+ break;
 902+#ifdef HAVE_HOTSWAP
 903+ case 50: // DISK_MOUNT
 904+ dbgasyncsendbuf[0] = 1;
 905+ dbgasyncsendbuf[1] = (uint32_t)disk_mount((int)(dbgasyncsendbuf[1]));
 906+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 907+ break;
 908+ case 51: // DISK_UNMOUNT
 909+ dbgasyncsendbuf[0] = 1;
 910+ dbgasyncsendbuf[1] = (uint32_t)disk_unmount((int)(dbgasyncsendbuf[1]));
 911+ usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
 912+ break;
 913+#endif
 914+ }
 915+ break;
 916+#endif
712917 }
713918 dbgaction = DBGACTION_IDLE;
714919 }