1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <aboot/aboot.h>
30#include <aboot/io.h>
31#include <omap4/mux.h>
32#include <omap4/hw.h>
33#include <omap4/omap4_rom.h>
34#include "protocol.h"
35
36#define min(a,b) ( ((a) < (b)) ? (a) : (b) )
37
38struct usb usb;
39
40unsigned cfg_machine_type = 2791;
41
42int load_from_usb(u32 *_len, u32 *_addr, u32 *_entry)
43{
44	u32 len, addr, entry, msg;
45
46	if (usb_open(&usb)) {
47		printf("failed to open usb\n");
48		return -1;
49	}
50
51	msg = ABOOT_IS_READY;
52	usb_write(&usb, &msg, sizeof(msg));
53
54	for (;;) {
55		len = addr = 0x0;
56
57		usb_read(&usb, &len, 4);
58		if (len == ABOOT_NO_MORE_DATA) {
59			printf("OK, no more data\n");
60			break;
61		}
62		usb_read(&usb, &addr, 4);
63		usb_read(&usb, &entry, 4);
64
65        printf("Entry point is %08X\n", entry);
66		printf("Reading %d bytes to %08X\n", len, addr);
67
68		*_addr = addr;
69		*_len = len;
70		*_entry = entry;
71
72        u32 to_read=    len;
73        void *read_ptr= (void *)addr;
74        size_t chunk= 0;
75        while(to_read > 0) {
76            /* Read a chunk. */
77            u32 this_chunk= min(to_read, CHUNK_SIZE);
78			if(usb_read(&usb, read_ptr, this_chunk)) {
79				printf("usb_read failed\n");
80				return -1;
81			}
82			to_read  -= this_chunk;
83			read_ptr += this_chunk;
84
85            /* Acknowledge reception. */
86            msg= chunk;
87            usb_write(&usb, &msg, sizeof(msg));
88            chunk++;
89		}
90	}
91
92	usb_close(&usb);
93	return 0;
94}
95
96static void __attribute__((noreturn))
97boot_image(u32 entry_point) {
98	void (*entry)(u32, u32, u32, u32)= (void *)entry_point;
99
100	printf("jumping to 0x%08X...\n", entry_point);
101	entry(0, 0, 0, 0);
102	for (;;);
103}
104
105void __attribute__((noreturn))
106aboot(unsigned *info) {
107    unsigned n;
108    u32 len, addr = CONFIG_ADDR_DOWNLOAD, entry;
109
110	board_mux_init();
111	sdelay(100);
112
113	scale_vcores();
114	prcm_init();
115	board_ddr_init();
116	gpmc_init();
117	board_late_init();
118
119	serial_init();
120
121	serial_puts("\n[ aboot second-stage loader ]\n\n");
122
123	n = load_from_usb(&len, &addr, &entry);
124	printf("load complete\n");
125	if (n) {
126		serial_puts("*** IO ERROR ***\n");
127	} else {
128		printf("starting!\n");
129		boot_image(entry);
130	}
131
132	for (;;) ;
133}
134
135