Root/mips/nanonote/unbrick.ccp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// mips/nanonote/unbrick.ccp: Host-side helper for USB boot.
4// Copyright 2009-2010 Bas Wijnen <wijnen@debian.org>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#include <unistd.h>
20#include <usb.h>
21#include <fstream>
22#include <sstream>
23#include <iostream>
24#include <iomanip>
25#include <cstring>
26#include <shevek/args.hh>
27#include <shevek/error.hh>
28
29#define STAGE1_FILE "stage1.raw"
30
31static usb_dev_handle *handle
32static int const boot_vendor = 0x601a
33static int const boot_product = 0x4740
34static int const run_vendor = 0xfffe
35static int const run_product = 0x0002
36static unsigned const timeout = 10000
37void boot (std::string const &filename, unsigned load, unsigned entry)
38static unsigned const STAGE1_LOAD = 0x80003000
39static unsigned const STAGE1_ENTRY = STAGE1_LOAD
40enum requests:
41    VR_GET_CPU_INFO = 0
42    VR_SET_DATA_ADDRESS = 1
43    VR_SET_DATA_LENGTH = 2
44    VR_FLUSH_CACHES = 3
45    VR_PROGRAM_START1 = 4
46    VR_PROGRAM_START2 = 5
47void request (requests num, unsigned data = 0)
48void get_device (unsigned vendor, unsigned product, unsigned tries)
49
50void request (requests r, unsigned data):
51    if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
52        std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
53        usb_release_interface (handle, 0)
54        usb_close (handle)
55        handle = NULL
56
57void send_file (unsigned address, int size, char const *data):
58    request (VR_SET_DATA_ADDRESS, address)
59    char const *ptr = data
60    while ptr - data < size:
61        int ret = usb_bulk_write (handle, 1, ptr, size - (ptr - data), timeout)
62        if ret <= 0:
63            std::cerr << "failed to write to NanoNote.\n"
64            usb_release_interface (handle, 0)
65            usb_close (handle)
66            handle = NULL
67            return
68        ptr += ret
69
70void get_device (unsigned vendor, unsigned product, unsigned tries):
71    for unsigned i = 0; i < tries; ++i:
72        usb_find_busses ()
73        usb_find_devices ()
74        for struct usb_bus *bus = usb_busses; bus; bus = bus->next:
75            for struct usb_device *dev = bus->devices; dev; dev = dev->next:
76                if dev->descriptor.idProduct != product || dev->descriptor.idVendor != vendor:
77                    //std::cerr << shevek::ostring ("Not using %04x:%04x when looking for %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product)
78                    continue
79                handle = usb_open (dev)
80                if usb_claim_interface (handle, 0) < 0:
81                    std::cerr << "unable to claim interface: " << usb_strerror () << "\n"
82                    usb_close (handle)
83                    handle = NULL
84                    continue
85                return
86        if i + 1 < tries:
87            //std::cerr << "failed to find device, still trying...\n"
88            sleep (1)
89    std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product)
90
91void boot (std::string const &filename, unsigned load, unsigned entry):
92    std::cerr << "booting " << shevek::ostring ("%s from %x@%x", Glib::ustring (filename), load, entry) << "\n"
93    get_device (boot_vendor, boot_product, 1)
94    if !handle:
95        std::cerr << "unable to find device\n"
96        return
97    std::ifstream file (STAGE1_FILE)
98    std::ostringstream stage1
99    stage1 << file.rdbuf ()
100    std::cerr << shevek::ostring ("sending stage 1 (size %x) @%x\n", stage1.str ().size (), STAGE1_LOAD)
101    send_file (STAGE1_LOAD, stage1.str ().size (), stage1.str ().data ())
102    std::cerr << shevek::ostring ("running stage 1 @%x\n", STAGE1_ENTRY)
103    request (VR_PROGRAM_START1, STAGE1_ENTRY)
104    usleep (100)
105    std::ostringstream stage2
106    usb_release_interface (handle, 0)
107    file.close ()
108    file.open (filename.c_str ())
109    stage2 << file.rdbuf ()
110    std::cerr << shevek::ostring ("sending Iris (size 0x%x) @%x\n", stage2.str ().size (), load)
111    send_file (load, stage2.str ().size (), stage2.str ().data ())
112    std::cerr << "flushing caches\n"
113    request (VR_FLUSH_CACHES)
114    std::cerr << shevek::ostring ("running Iris @%x\n", entry)
115    request (VR_PROGRAM_START2, entry)
116    usb_release_interface (handle, 0)
117    usb_close (handle)
118    handle = NULL
119    std::cerr << "done\n"
120
121int main (int argc, char **argv):
122    std::string filename ("iris.raw")
123    unsigned load (0x80000000), entry (0)
124    handle = NULL
125    usb_init ()
126    shevek::args::option opts[] = {
127        shevek::args::option ('f', "file", "image file", true, filename),
128        shevek::args::option ('l', "load", "load address", true, load),
129        shevek::args::option ('e', "entry", "entry point address", false, entry)
130     }
131    shevek::args args (argc, argv, opts, 0, 0, "unbrick program for NanoNote", "2009-2010")
132    if !entry:
133        shevek_error ("You must specify the entry point")
134    boot (filename, load, entry)
135    return 0
136

Archive Download this file

Branches:
master



interactive