#pypp 0 // Iris: micro-kernel for a capability-based operating system. // mips/nanonote/unbrick.ccp: Host-side helper for USB boot. // Copyright 2009-2010 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include #include #include #include #include #include #include #define STAGE1_FILE "stage1.raw" static usb_dev_handle *handle static int const boot_vendor = 0x601a static int const boot_product = 0x4740 static int const run_vendor = 0xfffe static int const run_product = 0x0002 static unsigned const timeout = 10000 void boot (std::string const &filename, unsigned load, unsigned entry) static unsigned const STAGE1_LOAD = 0x80002000 static unsigned const STAGE1_ENTRY = STAGE1_LOAD enum requests: VR_GET_CPU_INFO = 0 VR_SET_DATA_ADDRESS = 1 VR_SET_DATA_LENGTH = 2 VR_FLUSH_CACHES = 3 VR_PROGRAM_START1 = 4 VR_PROGRAM_START2 = 5 void request (requests num, unsigned data = 0) void get_device (unsigned vendor, unsigned product, unsigned tries) void request (requests r, unsigned data): if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0: std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n" usb_release_interface (handle, 0) usb_close (handle) handle = NULL void send_file (unsigned address, int size, char const *data): request (VR_SET_DATA_ADDRESS, address) char const *ptr = data while ptr - data < size: int ret = usb_bulk_write (handle, 1, ptr, size - (ptr - data), timeout) if ret <= 0: std::cerr << "failed to write to NanoNote.\n" usb_release_interface (handle, 0) usb_close (handle) handle = NULL return ptr += ret void get_device (unsigned vendor, unsigned product, unsigned tries): for unsigned i = 0; i < tries; ++i: usb_find_busses () usb_find_devices () for struct usb_bus *bus = usb_busses; bus; bus = bus->next: for struct usb_device *dev = bus->devices; dev; dev = dev->next: if dev->descriptor.idProduct != product || dev->descriptor.idVendor != vendor: //std::cerr << shevek::ostring ("Not using %04x:%04x when looking for %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product) continue handle = usb_open (dev) if usb_claim_interface (handle, 0) < 0: std::cerr << "unable to claim interface: " << usb_strerror () << "\n" usb_close (handle) handle = NULL continue return if i + 1 < tries: //std::cerr << "failed to find device, still trying...\n" sleep (1) std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product) void boot (std::string const &filename, unsigned load, unsigned entry): std::cerr << "booting " << shevek::ostring ("%s from %x@%x", Glib::ustring (filename), load, entry) << "\n" get_device (boot_vendor, boot_product, 1) if !handle: std::cerr << "unable to find device\n" return std::ifstream file (STAGE1_FILE) std::ostringstream stage1 stage1 << file.rdbuf () std::cerr << shevek::ostring ("sending stage 1 (size %x) @%x\n", stage1.str ().size (), STAGE1_LOAD) send_file (STAGE1_LOAD, stage1.str ().size (), stage1.str ().data ()) std::cerr << shevek::ostring ("running stage 1 @%x\n", STAGE1_ENTRY) request (VR_PROGRAM_START1, STAGE1_ENTRY) usleep (100) std::ostringstream stage2 usb_release_interface (handle, 0) file.close () file.open (filename.c_str ()) stage2 << file.rdbuf () std::cerr << shevek::ostring ("sending Iris (size 0x%x) @%x\n", stage2.str ().size (), load) send_file (load, stage2.str ().size (), stage2.str ().data ()) std::cerr << "flushing caches\n" request (VR_FLUSH_CACHES) std::cerr << shevek::ostring ("running Iris @%x\n", entry) request (VR_PROGRAM_START2, entry) usb_release_interface (handle, 0) usb_close (handle) handle = NULL std::cerr << "done\n" int main (int argc, char **argv): std::string filename ("iris.raw") unsigned load (0x80000000), entry (0) handle = NULL usb_init () shevek::args::option opts[] = { shevek::args::option ('f', "file", "image file", true, filename), shevek::args::option ('l', "load", "load address", true, load), shevek::args::option ('e', "entry", "entry point address", false, entry) } shevek::args args (argc, argv, opts, 0, 0, "unbrick program for NanoNote", "2009-2010") if !entry: shevek_error ("You must specify the entry point") boot (filename, load, entry) return 0