~ubuntu-branches/ubuntu/saucy/qemu/saucy

« back to all changes in this revision

Viewing changes to debian/patches/patches-arm-1.3.0/0042-add-hw-omap3_boot.c-file.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-02-22 13:34:07 UTC
  • mfrom: (2.1.36 raring)
  • Revision ID: package-import@ubuntu.com-20130222133407-ny5zhxn2lm3rr0r8
Tags: 1.4.0+dfsg-1expubuntu2
* substitute (apparently identical) patches from 1.4.0 qemu-linaro rebasing
  tree.
* add qemu-common to qemu-system-common B/R (was accidentally dropped from
  1.3.0 in 1.4.0 merge).
* debian/control: fix kvm P/C/B/R:
  - make all C/B/R against kvm versioned
  - don't have any qemu-system-* other than x86 Provides: kvm

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From a5208e422e33e9e86df6d7a2c11f917d6549371a Mon Sep 17 00:00:00 2001
2
 
From: Peter Maydell <peter.maydell@linaro.org>
3
 
Date: Tue, 4 Dec 2012 14:10:11 +0000
4
 
Subject: [PATCH 42/77] add hw/omap3_boot.c file
5
 
MIME-Version: 1.0
6
 
Content-Type: text/plain; charset=UTF-8
7
 
Content-Transfer-Encoding: 8bit
8
 
 
9
 
omap3 bootrom emulation
10
 
 
11
 
small changes in boot rom code
12
 
 
13
 
- update comments and include a note for r12=1 smc call
14
 
- leave the cpu in SYS mode when jumping to bootloader code
15
 
 
16
 
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
17
 
 
18
 
Changes by: Loïc Minier <loic.minier@linaro.org>
19
 
Fix use of p after free() in omap3_mmc_fat_boot()
20
 
Fix logic test to use && in omap3_mmc_fat_boot
21
 
 
22
 
Changes by: Peter Maydell <peter.maydell@linaro.org>
23
 
Remove code which was erroneously overriding the detection of a CHSETUP
24
 
header in an OMAP boot image loaded from an MMC card.
25
 
Fix raw mode boot (try sectors 0 and 256, use right offsets)
26
 
 
27
 
Changes by: Juha:
28
 
- do not map boot rom at address zero
29
 
- make use of the arm cp15 vector base address register
30
 
- run boot rom emulation from omap3 instead of board
31
 
 
32
 
Changes by: Peter Chubb <peter.chubb@nicta.com.au>
33
 
- bugfixes to make FAT12/FAT16 work
34
 
---
35
 
 hw/arm/Makefile.objs |   2 +-
36
 
 hw/omap.h            |   6 +
37
 
 hw/omap3_boot.c      | 960 +++++++++++++++++++++++++++++++++++++++++++++++++++
38
 
 3 files changed, 967 insertions(+), 1 deletion(-)
39
 
 create mode 100644 hw/omap3_boot.c
40
 
 
41
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
42
 
index bcf9de5..b94b6ae 100644
43
 
--- a/hw/arm/Makefile.objs
44
 
+++ b/hw/arm/Makefile.objs
45
 
@@ -19,7 +19,7 @@ obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
46
 
                 omap_gpio.o omap_intc.o omap_uart.o
47
 
 obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
48
 
                 omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
49
 
-obj-y += omap_usb.o
50
 
+obj-y += omap_usb.o omap3_boot.o
51
 
 obj-y += omap_sx1.o palm.o tsc210x.o
52
 
 obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
53
 
 obj-y += mst_fpga.o mainstone.o
54
 
diff --git a/hw/omap.h b/hw/omap.h
55
 
index adc67a7..de42447 100644
56
 
--- a/hw/omap.h
57
 
+++ b/hw/omap.h
58
 
@@ -1127,6 +1127,8 @@ struct omap_mpu_state_s {
59
 
     struct omap_dss_s *dss;
60
 
 
61
 
     struct omap_eac_s *eac;
62
 
+    MemoryRegion bootrom;
63
 
+    int bootrom_initialized;
64
 
 };
65
 
 
66
 
 /* omap1.c */
67
 
@@ -1139,6 +1141,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
68
 
                 unsigned long sdram_size,
69
 
                 const char *core);
70
 
 
71
 
+/* omap3_boot.c */
72
 
+void omap3_boot_rom_init(struct omap_mpu_state_s *s);
73
 
+void omap3_boot_rom_emu(struct omap_mpu_state_s *s);
74
 
+
75
 
 #define OMAP_FMT_plx "%#08" HWADDR_PRIx
76
 
 
77
 
 uint32_t omap_badwidth_read8(void *opaque, hwaddr addr);
78
 
diff --git a/hw/omap3_boot.c b/hw/omap3_boot.c
79
 
new file mode 100644
80
 
index 0000000..f9ce253
81
 
--- /dev/null
82
 
+++ b/hw/omap3_boot.c
83
 
@@ -0,0 +1,960 @@
84
 
+/*
85
 
+ * TI OMAP3 boot ROM emulation. Based on information in the OMAP34xx 3.1
86
 
+ * Technical Reference Manual from Texas Instruments.
87
 
+ *
88
 
+ * Copyright (C) 2009 Nokia Corporation
89
 
+ *
90
 
+ * The OMAP3 boot ROM service routines accessed via ARM SMC instruction
91
 
+ * are not available in this emulation due to the limited availability
92
 
+ * of public documentation on the ARM TrustZone functionality. However
93
 
+ * it seems executing the SMC instruction as a NOP causes no harm.
94
 
+ *
95
 
+ * This program is free software; you can redistribute it and/or
96
 
+ * modify it under the terms of the GNU General Public License as
97
 
+ * published by the Free Software Foundation; either version 2 or
98
 
+ * (at your option) any later version of the License.
99
 
+ *
100
 
+ * This program is distributed in the hope that it will be useful,
101
 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
102
 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
103
 
+ * GNU General Public License for more details.
104
 
+ *
105
 
+ * You should have received a copy of the GNU General Public License along
106
 
+ * with this program; if not, write to the Free Software Foundation, Inc.,
107
 
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
108
 
+ */
109
 
+#include "hw.h"
110
 
+#include "arm-misc.h"
111
 
+#include "omap.h"
112
 
+#include "sysemu/sysemu.h"
113
 
+#include "char/char.h"
114
 
+#include "flash.h"
115
 
+#include "sysemu/blockdev.h"
116
 
+#include "exec/address-spaces.h"
117
 
+
118
 
+//#define OMAP3_BOOT_DEBUG
119
 
+
120
 
+#ifdef OMAP3_BOOT_DEBUG
121
 
+#define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \
122
 
+                               __LINE__, ##__VA_ARGS__);
123
 
+#else
124
 
+#define TRACE(...)
125
 
+#endif
126
 
+
127
 
+/* list of supported NAND devices according to the OMAP34xx TRM */
128
 
+static const struct {
129
 
+    uint8_t id;
130
 
+    uint32_t pagesize;
131
 
+    uint32_t capacity_Mb;
132
 
+} omap3_boot_nand_devices[] = {
133
 
+    {0xe6,  512,    64}, {0x33,  512,   128}, {0x73,  512,   128},
134
 
+    {0x43,  512,   128}, {0x53,  512,   128}, {0x35,  512,   256},
135
 
+    {0x75,  512,   256}, {0x45,  512,   256}, {0x55,  512,   256},
136
 
+    {0x36,  512,   512}, {0x76,  512,   512}, {0x46,  512,   512},
137
 
+    {0x56,  512,   512}, {0xa2, 2048,   512}, {0xf2, 2048,   512},
138
 
+    {0xb2, 2048,   512}, {0xc2, 2048,   512}, {0x39,  512,  1024},
139
 
+    {0x79,  512,  1024}, {0x49,  512,  1024}, {0x59,  512,  1024},
140
 
+    {0x78,  512,  1024}, {0x72,  512,  1024}, {0x74,  512,  1024},
141
 
+    {0xa1, 2048,  1024}, {0xf1, 2048,  1024}, {0xb1, 2048,  1024},
142
 
+    {0xc1, 2048,  1024}, {0xaa, 2048,  2048}, {0xda, 2048,  2048},
143
 
+    {0xba, 2048,  2048}, {0xca, 2048,  2048}, {0x71,  512,  2048},
144
 
+    {0x51,  512,  2048}, {0x31,  512,  2048}, {0x41,  512,  2048},
145
 
+    {0xac, 2048,  4096}, {0xdc, 2048,  4096}, {0xbc, 2048,  4096},
146
 
+    {0xcc, 2048,  4096}, {0xa3, 2048,  8192}, {0xd3, 2048,  8192},
147
 
+    {0xb3, 2048,  8192}, {0xc3, 2048,  8192}, {0xa5, 2048, 16384},
148
 
+    {0xd5, 2048, 16384}, {0xb5, 2048, 16384}, {0xc5, 2048, 16384},
149
 
+    {0xa7, 2048, 32768}, {0xb7, 2048, 32768}, {0xae, 2048, 65536},
150
 
+    {0xbe, 2048, 65536},
151
 
+    {0, 0, 0}
152
 
+};
153
 
+
154
 
+struct omap3_nand_boot_desc_s {
155
 
+    uint32_t pagesize;
156
 
+    uint32_t capacity_Mb;
157
 
+    uint8_t bus16;
158
 
+};
159
 
+
160
 
+static const uint8_t omap3_boot_rom[] = { /* 0x40014000-0x4001bfff */
161
 
+    /* 0x40014000: ROM Exception vectors */
162
 
+    0x3e, 0x00, 0x00, 0xea, /* b 0x40014100 */
163
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
164
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
165
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
166
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
167
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
168
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
169
 
+    0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
170
 
+    /* 0x40014020: ROM CRC */
171
 
+    0xff, 0xff, 0xff, 0xff, 
172
 
+    /* 0x40014024: unused(?), we use it for some data */
173
 
+    0xc8, 0xff, 0x20, 0x40, /* 0x40014024: undef sram vector address */
174
 
+    0xcc, 0xff, 0x20, 0x40, /* 0x40014028: swi sram vector address */
175
 
+    0xd0, 0xff, 0x20, 0x40, /* 0x4001402c: pabt sram vector address */
176
 
+    0xd4, 0xff, 0x20, 0x40, /* 0x40014030: dabt sram vector address */
177
 
+    0xd8, 0xff, 0x20, 0x40, /* 0x40014034: unused sram vector address */
178
 
+    0xdc, 0xff, 0x20, 0x40, /* 0x40014038: irq sram vector address */
179
 
+    0xe0, 0xff, 0x20, 0x40, /* 0x4001403c: fiq sram vector address */
180
 
+    0xff, 0xff, 0xff, 0xff, /* 0x40014040: boot loader image start address */
181
 
+    0xff, 0xff, 0xff, 0xff, /* 0x40014044: booting parameter structure 0-3 */
182
 
+    0xff, 0xff, 0xff, 0xff, /* 0x40014048: booting parameter structure 4-7 */
183
 
+    0xff, 0xff, 0xff, 0xff, /* 0x4001404c: booting parameter structure 8-11 */
184
 
+    0x0e, 0xf0, 0xb0, 0xe1, /* 0x40014050: "movs pc, lr" */
185
 
+    0xff, 0xff, 0xff, 0xff, /* 0x40014054 */
186
 
+    0xff, 0xff, 0xff, 0xff, /* 0x40014058 */
187
 
+    0xff, 0xff, 0xff, 0xff, /* 0x4001405c */
188
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x40014060: monitor vector 0 (unused) */
189
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x40014064: monitor vector 1 (unused) */
190
 
+    0x15, 0x00, 0x00, 0xea, /* 0x40014068: monitor vector 2 (smc) */
191
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x4001406c: monitor vector 3 (pabt) */
192
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x40014070: monitor vector 4 (dabt) */
193
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x40014074: monitor vector 5 (unused) */
194
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x40014078: monitor vector 6 (irq) */
195
 
+    0xfe, 0xff, 0xff, 0xea, /* 0x4001407c: monitor vector 7 (fiq) */
196
 
+    /* 0x40014080: Dead loops */
197
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014080 @ undefined exception */
198
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014084 @ swi exception */
199
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014088 @ prefetch abort exception */
200
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x4001408c @ data abort exception */
201
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014090 @ unused exception */
202
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014094 @ irq exception */
203
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x40014098 @ fiq exception */
204
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x4001409c @ validation tests pass */
205
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140a0 @ validation tests fail */
206
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140a4 @ boot failed: no more devices */
207
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140a8 @ image not executed or returned */
208
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140ac @ reserved */
209
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140b0 @ reserved */
210
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140b4 @ reserved */
211
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140b8 @ reserved */
212
 
+    0xfe, 0xff, 0xff, 0xea, /* b 0x400140bc @ reserved */
213
 
+    /* 0x400140c0: should perform a software reset & jump to r0 */
214
 
+    0x00, 0xf0, 0xa0, 0xe1, /* mov pc, r0 */
215
 
+    /* 0x400140c4: monitor mode smc vector handler */
216
 
+                            /* @ r12=1 is used to invalidate l2, we skip it */
217
 
+    0x02, 0x00, 0x5c, 0xe3, /* cmp r12, #2 @ write to l2 cache aux ctrl */
218
 
+    0x50, 0x0f, 0x29, 0xee, /* mcreq p15, 1, r0, c9, c0, 2 */
219
 
+    0x03, 0x00, 0x5c, 0xe3, /* cmp r12, #3 @ write to aux ctrl */
220
 
+    0x30, 0x0f, 0x01, 0xee, /* mcreq p15, 0, r0, c1, c0, 1 @ aux ctrl*/
221
 
+    0x0e, 0xf0, 0xb0, 0xe1, /* movs pc, r14 */
222
 
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
223
 
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
224
 
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
225
 
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
226
 
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
227
 
+    /* 0x40014100: code, ROM emulation uses this to launch the
228
 
+     * boot loader after it has been read into memory */
229
 
+    0xc8, 0x10, 0x1f, 0xe5, /* ldr r1, [#0x40014040] @ boot loader start */
230
 
+    0xb0, 0x0c, 0x0f, 0xe3, /* movw r0, #0xfcb0 */
231
 
+    0x20, 0x00, 0x44, 0xe3, /* movt r0, #0x4020    @ stack top at 0x4020fcb0 */
232
 
+    0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf   @ enter SYS mode */
233
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
234
 
+    0x80, 0x0c, 0x40, 0xe2, /* sub r0, r0, #32768  @ 32kB SYS/USR stack */
235
 
+    0xd1, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd1   @ enter FIQ mode */
236
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
237
 
+    0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048   @ 2kB FIQ stack */
238
 
+    0xd2, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd2   @ enter IRQ mode */
239
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
240
 
+    0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048   @ 2kB IRQ stack */
241
 
+    0xd7, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd7   @ enter ABT mode */
242
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
243
 
+    0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048   @ 2kB ABT stack */
244
 
+    0xdb, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdb   @ enter UND mode */
245
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
246
 
+    0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048   @ 2kB UND stack */
247
 
+    0xd3, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd3   @ enter SVC mode */
248
 
+    0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0          @ 23kB left for SVC stack */
249
 
+    0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf   @ enter SYS mode */
250
 
+    0x40, 0x04, 0xa0, 0xe3, /* mov r0, #0x40000000 @ r0 -> vba */
251
 
+    0x05, 0x09, 0x80, 0xe2, /* add r0, r0, #0x14000 */
252
 
+    0x10, 0x0f, 0x0c, 0xfe, /* mcr2 p15, 0, r0, c12, c0, 0 */
253
 
+    0x60, 0x00, 0x80, 0xe2, /* add r0, r0, #0x60  @ r0 -> monitor vba */
254
 
+    0x30, 0x0f, 0x0c, 0xfe, /* mcr2 p15, 0, r0, c12, c0, 1 */
255
 
+    0x1c, 0x00, 0x40, 0xe2, /* sub r0, r0, #1c    @ r0 -> booting parameter struct */
256
 
+    0x01, 0xf0, 0xa0, 0xe1, /* mov pc, r1 */
257
 
+};
258
 
+
259
 
+/* SRAM exception vectors, to be placed at 0x4020ffc8 */
260
 
+static const uint8_t omap3_sram_vectors[] = {
261
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe4] @ undefined */
262
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe8] @ swi */
263
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffec] @ prefetch abort */
264
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff0] @ data abort */
265
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff4] @ unused */
266
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff8] @ irq */
267
 
+    0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fffc] @ fiq */
268
 
+    0x80, 0x40, 0x01, 0x00, /* 0x14080 */
269
 
+    0x50, 0x40, 0x01, 0x40, /* 0x40014050 (default is 0x14084) */
270
 
+    0x88, 0x40, 0x01, 0x00, /* 0x14088 */
271
 
+    0x8c, 0x40, 0x01, 0x00, /* 0x1408c */
272
 
+    0x90, 0x40, 0x01, 0x00, /* 0x14090 */
273
 
+    0x94, 0x40, 0x01, 0x00, /* 0x14094 */
274
 
+    0x98, 0x40, 0x01, 0x00, /* 0x14098 */
275
 
+};
276
 
+
277
 
+static inline uint32_t omap3_get_le32(const void *p)
278
 
+{
279
 
+    const uint8_t *q = (const uint8_t *)p;
280
 
+    uint32_t v;
281
 
+    v = q[3]; v <<= 8;
282
 
+    v |= q[2]; v <<= 8;
283
 
+    v |= q[1]; v <<= 8;
284
 
+    v |= q[0];
285
 
+    return v;
286
 
+}
287
 
+
288
 
+static inline uint32_t omap3_get_le16(const void *p)
289
 
+{
290
 
+    const uint8_t *q = (const uint8_t *)p;
291
 
+    uint32_t v;
292
 
+    v = q[1]; v <<= 8;
293
 
+    v |= q[0];
294
 
+    return v;
295
 
+}
296
 
+
297
 
+static inline void omap3_boot_setlsb(hwaddr addr, uint16_t lsb)
298
 
+{
299
 
+    uint8_t x[4];
300
 
+    
301
 
+    cpu_physical_memory_read(addr, x, 4);
302
 
+    x[0] = lsb & 0xff;
303
 
+    x[1] = (lsb >> 8) & 0xff;
304
 
+    cpu_physical_memory_write(addr, x, 4);
305
 
+}
306
 
+
307
 
+typedef enum {
308
 
+    xip = 1,
309
 
+    nand,
310
 
+    onenand,
311
 
+    doc,
312
 
+    mmc2,
313
 
+    mmc1,
314
 
+    xipwait,
315
 
+    uart = 0x10,
316
 
+    hsusb,
317
 
+}  omap3_boot_device_t;
318
 
+
319
 
+struct omap3_boot_s {
320
 
+    struct omap_mpu_state_s *mpu;
321
 
+    omap3_boot_device_t devicetype;
322
 
+    enum {
323
 
+        undefined = 0,
324
 
+        confighdr,
325
 
+        chdone,
326
 
+        imagehdr,
327
 
+        copy,
328
 
+        done
329
 
+    } state;
330
 
+    uint8_t chflags;
331
 
+    hwaddr addr;
332
 
+    uint32_t count;
333
 
+};
334
 
+
335
 
+static struct omap3_boot_s *omap3_boot_init(struct omap_mpu_state_s *mpu,
336
 
+                                            omap3_boot_device_t dtype,
337
 
+                                            const uint8_t *data,
338
 
+                                            uint32_t data_len)
339
 
+{
340
 
+    struct omap3_boot_s *s = g_malloc0(sizeof(struct omap3_boot_s));
341
 
+    s->mpu = mpu;
342
 
+    s->devicetype = dtype;
343
 
+    s->state = chdone;
344
 
+    if (data_len >= 512) {
345
 
+        if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
346
 
+            || !strncasecmp((char *)(data + 0x14), "chram", 5)
347
 
+            || !strncasecmp((char *)(data + 0x14), "chflash", 7)
348
 
+            || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
349
 
+            s->state = confighdr;
350
 
+    }
351
 
+    return s;
352
 
+}
353
 
+
354
 
+static void omap3_boot_chsettings(struct omap3_boot_s *boot,
355
 
+                                  const uint8_t *chtoc)
356
 
+{
357
 
+    uint32_t flags, x;
358
 
+    
359
 
+    if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
360
 
+        TRACE("invalid section verification key");
361
 
+        return;
362
 
+    }
363
 
+    if (!chtoc[4]) { /* section disabled? */
364
 
+        return;
365
 
+    }
366
 
+    if (omap3_get_le16(chtoc + 5) != 0x0001) {
367
 
+        TRACE("unsupported CH version (0x%04x)", omap3_get_le16(chtoc));
368
 
+        return;
369
 
+    }
370
 
+    boot->chflags |= 0x01;
371
 
+    flags = omap3_get_le32(chtoc + 8);
372
 
+    chtoc += 12;
373
 
+    if (flags & 1) {
374
 
+        cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
375
 
+        cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
376
 
+        cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
377
 
+        if (flags & (1 << 2)) { /* clock configuration */
378
 
+            cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
379
 
+            cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
380
 
+        }
381
 
+        if (flags & (1 << 5)) { /* DPLL3 CORE */
382
 
+            if (flags & (1 << 8)) { /* enable DPLL3 bypass */
383
 
+                cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
384
 
+                x &= ~7; x |= 5; /* set DPLL3 bypass */
385
 
+                cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
386
 
+            }
387
 
+            cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
388
 
+            cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
389
 
+            cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
390
 
+        }
391
 
+        if (flags & (1 << 3)) { /* DPLL4 PER */
392
 
+            if (flags & (1 << 6)) { /* enable DPLL4 bypass */
393
 
+                cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
394
 
+                x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
395
 
+                cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
396
 
+            }
397
 
+            cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
398
 
+            cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
399
 
+            cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
400
 
+            cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
401
 
+        }
402
 
+        if (flags & (1 << 3)) { /* DPLL1 MPU */
403
 
+            if (flags & (1 << 7)) { /* enable DPLL1 bypass */
404
 
+                cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
405
 
+                x &= ~7; x |= 5; /* set DPLL1 bypass */
406
 
+                cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
407
 
+            }
408
 
+            cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
409
 
+            cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
410
 
+            cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
411
 
+            cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
412
 
+            cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
413
 
+        }
414
 
+        switch ((flags >> 24) & 0xff) {
415
 
+            case 0x01: x = 0; break; /* 12MHz */
416
 
+            case 0x02: x = 1; break; /* 13MHz */
417
 
+            case 0x03: x = 5; break; /* 16.8MHz */
418
 
+            case 0x04: x = 2; break; /* 19.2MHz */
419
 
+            case 0x05: x = 3; break; /* 26MHz */
420
 
+            case 0x06: x = 4; break; /* 38.4MHz */
421
 
+            default:
422
 
+                TRACE("unsupported SYS.CLK setting (0x%02x)", (flags >> 24) & 0xff);
423
 
+                x = 1;
424
 
+                break;
425
 
+        }
426
 
+        if (x != omap3_get_le32(chtoc + 0x04)) {
427
 
+            TRACE("mismatch in SYS.CLK id and PRM_CLKSEL value");
428
 
+        }
429
 
+    }
430
 
+}
431
 
+
432
 
+static void omap3_boot_chram(struct omap3_boot_s *boot,
433
 
+                             const uint8_t *chtoc)
434
 
+{
435
 
+    if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
436
 
+        TRACE("invalid section verification key");
437
 
+        return;
438
 
+    }
439
 
+    if (!chtoc[4]) { /* section disabled? */
440
 
+        return;
441
 
+    }
442
 
+    boot->chflags |= 0x02;
443
 
+    omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
444
 
+    omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
445
 
+    cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
446
 
+    
447
 
+    cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
448
 
+    omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
449
 
+    omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
450
 
+    omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
451
 
+    omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
452
 
+    cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
453
 
+    cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
454
 
+    cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
455
 
+    
456
 
+    cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
457
 
+    omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
458
 
+    omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
459
 
+    omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
460
 
+    omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
461
 
+    cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
462
 
+    cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
463
 
+    cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
464
 
+}
465
 
+
466
 
+static void omap3_boot_chflash(struct omap3_boot_s *boot,
467
 
+                               const uint8_t *chtoc)
468
 
+{
469
 
+    if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
470
 
+        TRACE("invalid section verification key");
471
 
+        return;
472
 
+    }
473
 
+    if (!chtoc[4]) { /* section disabled? */
474
 
+        return;
475
 
+    }
476
 
+    boot->chflags |= 0x04;
477
 
+    omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
478
 
+    omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
479
 
+    omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
480
 
+    omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
481
 
+    cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
482
 
+    cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
483
 
+    cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
484
 
+    cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
485
 
+    cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
486
 
+    cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
487
 
+    cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
488
 
+    cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
489
 
+    omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
490
 
+    omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
491
 
+    /* TODO: ECC config registers. The TRM spec is not clear on these */
492
 
+}
493
 
+
494
 
+static void omap3_boot_chmmcsd(struct omap3_boot_s *boot,
495
 
+                               const uint8_t *chtoc)
496
 
+{
497
 
+    if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
498
 
+        TRACE("invalid section verification key");
499
 
+        return;
500
 
+    }
501
 
+    if (!chtoc[4]) { /* section disabled? */
502
 
+        return;
503
 
+    }
504
 
+    boot->chflags |= 0x08;
505
 
+    /* TODO: MMCHS registers */
506
 
+}
507
 
+
508
 
+/* returns non-zero if more blocks are needed */
509
 
+static uint32_t omap3_boot_block(const uint8_t *data,
510
 
+                                 uint32_t data_len,
511
 
+                                 struct omap3_boot_s *s)
512
 
+{
513
 
+    const uint8_t *p = 0;
514
 
+    uint32_t i = 0;
515
 
+    
516
 
+    switch (s->state) {
517
 
+        case confighdr:
518
 
+            i = data_len;
519
 
+            for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
520
 
+                if (!strcasecmp((char *)(p + 0x14), "chsettings"))
521
 
+                    omap3_boot_chsettings(s, p + omap3_get_le32(p));
522
 
+                else if (!strcasecmp((char *)(p + 0x14), "chram"))
523
 
+                    omap3_boot_chram(s, p + omap3_get_le32(p));
524
 
+                else if (!strcasecmp((char *)(p + 0x14), "chflash"))
525
 
+                    omap3_boot_chflash(s, p + omap3_get_le32(p));
526
 
+                else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
527
 
+                    omap3_boot_chmmcsd(s, p + omap3_get_le32(p));
528
 
+                else {
529
 
+                    TRACE("unknown CHTOC item \"%s\"", (char *)(p + 0x14));
530
 
+                }
531
 
+            }
532
 
+            data += 512;
533
 
+            data_len -= 512;
534
 
+            s->state = chdone;
535
 
+            /* fallthrough */
536
 
+        case chdone:
537
 
+            s->state = imagehdr;
538
 
+            /* fallthrough */
539
 
+        case imagehdr:
540
 
+            if (!data_len)
541
 
+                return 1;
542
 
+            if (data_len < 8)
543
 
+                break;
544
 
+            s->count = omap3_get_le32(data);
545
 
+            s->addr = omap3_get_le32(data + 4);
546
 
+            if (!s->count || (s->count >> 24) || !s->addr || s->addr == 0xffffffff)
547
 
+                break;
548
 
+            /* patch image start address in boot ROM */
549
 
+            cpu_physical_memory_write_rom(0x40014040, data + 4, 4);
550
 
+            /* start copying image */
551
 
+            data += 8;
552
 
+            data_len -= 8;
553
 
+            s->state = copy;
554
 
+            /* fallthrough */
555
 
+        case copy:
556
 
+            i = (s->count >= data_len) ? data_len : s->count;
557
 
+            cpu_physical_memory_write(s->addr, data, i);
558
 
+            s->addr += i;
559
 
+            s->count -= i;
560
 
+            if (!s->count)
561
 
+                s->state = done;
562
 
+            return s->count;
563
 
+        default:
564
 
+            break;
565
 
+    }
566
 
+    return 0;
567
 
+}
568
 
+
569
 
+/* returns non-zero if boot has finished succesfully */
570
 
+static int omap3_boot_finish(struct omap3_boot_s *s)
571
 
+{
572
 
+    uint8_t x[12] = {
573
 
+        0, 0, 0, 0, /* last received booting message */
574
 
+        (uint8_t)s->devicetype,
575
 
+        0,
576
 
+        1, /* POR */
577
 
+        s->chflags,
578
 
+        0, 0, 0, 0 /* device descriptor */
579
 
+    };
580
 
+    int result = (s->state == done);
581
 
+
582
 
+    if (result) {
583
 
+        /* fill in the booting parameter structure */
584
 
+        cpu_physical_memory_write_rom(0x40014044, x, 12);
585
 
+    }
586
 
+    free(s);
587
 
+    return result;
588
 
+}
589
 
+
590
 
+/* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
591
 
+static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
592
 
+{
593
 
+    int i;
594
 
+    
595
 
+    /* there are 0x10 items with 0x20 bytes per item */
596
 
+    for (i = 0x10; i--; s += 0x20) {
597
 
+        if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
598
 
+        if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
599
 
+    }
600
 
+    return 0;
601
 
+}
602
 
+
603
 
+struct omap3_fat_drv_s {
604
 
+    BlockDriverState *bs;
605
 
+    uint8_t ptype; /* 12, 16, 32 */
606
 
+    uint64_t c0;   /* physical byte offset for data cluster 0 */
607
 
+    uint64_t fat;  /* physical byte offset for used FAT sector 0 */
608
 
+    uint32_t spc;  /* sectors per cluster */
609
 
+};
610
 
+
611
 
+/* returns cluster data in the buffer and next cluster chain number
612
 
+ or 0 if unsuccessful */
613
 
+static uint32_t omap3_read_fat_cluster(uint8_t *data,
614
 
+                                       struct omap3_fat_drv_s *drv,
615
 
+                                       uint32_t cl)
616
 
+{
617
 
+    uint8_t buf[ 4 ];
618
 
+    uint32_t len = drv->spc * 0x200; /* number of bytes to read */
619
 
+    
620
 
+    switch (drv->ptype) { /* check for EOF */
621
 
+        case 12: if (cl > 0xff0) return 0; break;
622
 
+        case 16: if (cl > 0xfff0) return 0; break;
623
 
+        case 32: if (cl > 0x0ffffff0) return 0; break;
624
 
+        default: return 0;
625
 
+    }
626
 
+    
627
 
+    if (bdrv_pread(drv->bs, 
628
 
+                   drv->c0 + (cl - 2) * len,
629
 
+                   data, len) != len)
630
 
+        return 0;
631
 
+    
632
 
+    switch (drv->ptype) { /* determine next cluster # */
633
 
+        case 12:
634
 
+            hw_error("%s: FAT12 parsing not implemented!", __FUNCTION__);
635
 
+            break;
636
 
+        case 16:
637
 
+            return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
638
 
+            ? 0 : omap3_get_le16(buf);
639
 
+        case 32:
640
 
+            return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
641
 
+            ? 0 : omap3_get_le32(buf) & 0x0fffffff;
642
 
+        default:
643
 
+            break;
644
 
+    }
645
 
+    return 0;
646
 
+}
647
 
+
648
 
+static int omap3_mmc_fat_boot(BlockDriverState *bs,
649
 
+                              uint8_t *sector,
650
 
+                              uint32_t pstart,
651
 
+                              struct omap_mpu_state_s *mpu)
652
 
+{
653
 
+    struct omap3_fat_drv_s drv;
654
 
+    struct omap3_boot_s *boot;
655
 
+    uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
656
 
+    const uint8_t *p, *q;
657
 
+    uint8_t *cluster;
658
 
+    int result = 0;
659
 
+    
660
 
+    /* determine FAT type */
661
 
+    
662
 
+    drv.bs = bs;
663
 
+    fatsize = omap3_get_le16(sector + 0x16);
664
 
+    if (!fatsize) 
665
 
+        fatsize = omap3_get_le32(sector + 0x24);
666
 
+    bootsize = omap3_get_le16(sector + 0x0e);
667
 
+    cluster0 = bootsize + fatsize * sector[0x10];
668
 
+    rootsize = omap3_get_le16(sector + 0x11);
669
 
+    if (rootsize & 0x0f)
670
 
+        rootsize += 0x10;
671
 
+    rootsize >>= 4;
672
 
+    drv.spc = sector[0x0d];
673
 
+    i = omap3_get_le16(sector + 0x13);
674
 
+    if (!i)
675
 
+        i = omap3_get_le32(sector + 0x20);
676
 
+    i = (i - (cluster0 + rootsize)) / drv.spc;
677
 
+    drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
678
 
+    
679
 
+    /* search for boot loader file */
680
 
+    
681
 
+    drv.fat = (bootsize + pstart) * 0x200;
682
 
+    drv.c0 = (cluster0 + pstart) * 0x200;
683
 
+    if (drv.ptype == 32) {
684
 
+        i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
685
 
+        j = omap3_get_le16(sector + 0x28);
686
 
+        if (j & 0x80)
687
 
+            drv.fat += (j & 0x0f) * fatsize * 0x200;
688
 
+        cluster = g_malloc0(drv.spc * 0x200);
689
 
+        for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
690
 
+            for (j = drv.spc, q=cluster; j-- && !p; q += 0x200)
691
 
+                p = omap3_scan_fat_dir_sector(q);
692
 
+            if (p) {
693
 
+                memcpy(sector, p, 0x200); /* save the sector */
694
 
+                /* allows referring to p after freeing cluster */
695
 
+                p = sector;
696
 
+            }
697
 
+        }
698
 
+        free(cluster);
699
 
+    } else { /* FAT12/16 */
700
 
+        /*
701
 
+         * drv.c0 points to start of root directory
702
 
+         */
703
 
+        for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
704
 
+            if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
705
 
+                break;
706
 
+            p = omap3_scan_fat_dir_sector(sector);
707
 
+        }
708
 
+        /*
709
 
+         * Adjust start of clusters to point after the root directory.
710
 
+         */
711
 
+        drv.c0 += 0x200 * rootsize;
712
 
+    }
713
 
+    
714
 
+    if (p && *p) { /* did we indeed find the file? */
715
 
+        /*
716
 
+         * FAT16 Spec says to ignore bytes at offset 0x14 (the FAT32
717
 
+         * high-order cylinder number bytes); but the omap3 bootrom
718
 
+         * seems always to use them.
719
 
+         */
720
 
+        i = omap3_get_le16(p + 0x14);
721
 
+        i <<= 16;
722
 
+        i |= omap3_get_le16(p + 0x1a);
723
 
+        j = drv.spc * 0x200;
724
 
+        uint8 *data = g_malloc0(j);
725
 
+        if ((i = omap3_read_fat_cluster(data, &drv, i))) {
726
 
+            boot = omap3_boot_init(mpu, mmc1, data, j);
727
 
+            while (omap3_boot_block(data, j, boot))
728
 
+                i = omap3_read_fat_cluster(data, &drv, i);
729
 
+            result = omap3_boot_finish(boot);
730
 
+        } else {
731
 
+            TRACE("unable to read MLO file contents from SD card");
732
 
+        }
733
 
+        free(data);
734
 
+    } else {
735
 
+        TRACE("MLO file not found in the root directory");
736
 
+    }
737
 
+    return result;
738
 
+}
739
 
+
740
 
+static int omap3_mmc_raw_boot(BlockDriverState *bs,
741
 
+                              uint8_t *sector,
742
 
+                              struct omap_mpu_state_s *mpu)
743
 
+{
744
 
+    struct omap3_boot_s *boot;
745
 
+    uint32_t i = 0;
746
 
+    int result = 0;
747
 
+    /* We try to load an image from sectors 0 and 256 */
748
 
+    uint32_t boot_sectors[] = { 0, 256 };
749
 
+    int idx;
750
 
+
751
 
+    for (idx = 0; !result && idx < ARRAY_SIZE(boot_sectors); idx++) {
752
 
+        i = boot_sectors[idx];
753
 
+        if (bdrv_pread(bs, i * 0x200, sector, 0x200) != 0x200) {
754
 
+            TRACE("error trying to read sector %u on boot device", i);
755
 
+            continue;
756
 
+        }
757
 
+
758
 
+        boot = omap3_boot_init(mpu, mmc1, sector, 0x200);
759
 
+        if (boot->state == confighdr) {
760
 
+            /* CH must be present for raw boot */
761
 
+            while (omap3_boot_block(sector, 0x200, boot)) {
762
 
+                i++;
763
 
+                if (bdrv_pread(bs, i * 0x200, sector, 0x200) != 0x200) {
764
 
+                    TRACE("error trying to read sector %u on boot device", i);
765
 
+                    break;
766
 
+                }
767
 
+            }
768
 
+        }
769
 
+
770
 
+        result = (boot->state == done);
771
 
+        free(boot);
772
 
+    }
773
 
+    return result;
774
 
+}
775
 
+
776
 
+/* returns non-zero if successful, zero if unsuccessful */
777
 
+static int omap3_mmc_boot(struct omap_mpu_state_s *s)
778
 
+{
779
 
+    DriveInfo *di = drive_get(IF_SD, 0, 0);
780
 
+    uint8_t *sector, *p;
781
 
+    uint32_t pstart, i;
782
 
+    int result = 0;
783
 
+    
784
 
+    /* very simple implementation for GP device boot,
785
 
+     supports only two modes:
786
 
+     1. MBR partition table with an active FAT partition
787
 
+     and boot loader file (MLO) in its root directory, or
788
 
+     2. CH sector located on first sector, followed by boot loader image */
789
 
+    if (di) {
790
 
+        sector = g_malloc0(0x200);
791
 
+        if (bdrv_pread(di->bdrv, 0, sector, 0x200) == 0x200) {
792
 
+            for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
793
 
+                if (p[0] == 0x80) break;
794
 
+            if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
795
 
+                && i < 4 /* active partition exists */
796
 
+                && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
797
 
+                    || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
798
 
+                && bdrv_pread(di->bdrv,
799
 
+                              (pstart = omap3_get_le32(p + 8)) * 0x200,
800
 
+                              sector, 0x200) == 0x200
801
 
+                && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
802
 
+                result = omap3_mmc_fat_boot(di->bdrv, sector, pstart, s);
803
 
+            else
804
 
+                result = omap3_mmc_raw_boot(di->bdrv, sector, s);
805
 
+        }
806
 
+        free(sector);
807
 
+    }
808
 
+    return result;
809
 
+}
810
 
+
811
 
+static inline void omap3_nand_sendcmd(struct omap3_nand_boot_desc_s *nd,
812
 
+                                      uint8_t cmd)
813
 
+{
814
 
+    uint8_t x[2] = {cmd, 0};
815
 
+    cpu_physical_memory_write(0x6e00007c, x, nd->bus16 ? 2 : 1);
816
 
+}
817
 
+
818
 
+static inline void omap3_nand_sendaddr_byte(struct omap3_nand_boot_desc_s *nd,
819
 
+                                            uint8_t a)
820
 
+{
821
 
+    uint8_t x[2] = { a, 0 };
822
 
+    
823
 
+    cpu_physical_memory_write(0x6e000080, x, nd->bus16 ? 2 : 1);
824
 
+}
825
 
+
826
 
+static inline uint8_t omap3_nand_readbyte(struct omap3_nand_boot_desc_s *nd)
827
 
+{
828
 
+    uint8_t x[2];
829
 
+    
830
 
+    cpu_physical_memory_read(0x6e000084, x, nd->bus16 ? 2 : 1);
831
 
+    return x[0];
832
 
+}
833
 
+
834
 
+static inline void omap3_nand_readpage(struct omap3_nand_boot_desc_s *nd,
835
 
+                                       uint32_t pageaddr,
836
 
+                                       uint8_t *data)
837
 
+{
838
 
+    uint32_t i;
839
 
+    
840
 
+    omap3_nand_sendcmd(nd, 0x00); /* read page */
841
 
+    omap3_nand_sendaddr_byte(nd, 0x00);
842
 
+    if (nd->pagesize >= 2048) {
843
 
+        omap3_nand_sendaddr_byte(nd, 0x00);
844
 
+        omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
845
 
+        omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
846
 
+        if (nd->capacity_Mb >= 2048)
847
 
+            omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 16) & 0xff));
848
 
+        omap3_nand_sendcmd(nd, 0x30); /* confirm read */
849
 
+    } else {
850
 
+        omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
851
 
+        omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
852
 
+    }
853
 
+    if (nd->bus16) {
854
 
+        for (i = nd->pagesize / 2; i--; data += 2)
855
 
+            cpu_physical_memory_read(0x6e000084, data, 2);
856
 
+    } else {
857
 
+        for (i = nd->pagesize; i--; data++)
858
 
+            cpu_physical_memory_read(0x6e000084, data, 1);
859
 
+    }
860
 
+}
861
 
+
862
 
+/* returns non-zero if successful, zero if unsuccessful */
863
 
+static int omap3_nand_boot(struct omap_mpu_state_s *mpu, int bus16)
864
 
+{
865
 
+    struct omap3_nand_boot_desc_s *nd;
866
 
+    struct omap3_boot_s *boot;
867
 
+    uint8_t *data;
868
 
+    uint32_t page = 0;
869
 
+    int result = 0, i;
870
 
+    uint8_t id[4];
871
 
+    
872
 
+    /* TODO: support bad block marks */
873
 
+    nd = g_malloc0(sizeof(struct omap3_nand_boot_desc_s));
874
 
+    nd->bus16 = bus16;
875
 
+    omap3_nand_sendcmd(nd, 0xff); /* reset */
876
 
+    omap3_nand_sendcmd(nd, 0x90); /* read id */
877
 
+    omap3_nand_sendaddr_byte(nd, 0);
878
 
+    id[0] = omap3_nand_readbyte(nd); /* manufacturer id */
879
 
+    id[1] = omap3_nand_readbyte(nd); /* device id */
880
 
+    id[2] = omap3_nand_readbyte(nd); /* don't care */
881
 
+    id[3] = omap3_nand_readbyte(nd); /* attributes */
882
 
+    for (i = 0; omap3_boot_nand_devices[i].id; i++) {
883
 
+        if (omap3_boot_nand_devices[i].id == id[1]) {
884
 
+            nd->capacity_Mb = omap3_boot_nand_devices[i].capacity_Mb;
885
 
+            if (nd->capacity_Mb > 1024)
886
 
+                nd->pagesize = 1024 * (1 << (id[3] & 3));
887
 
+            else
888
 
+                nd->pagesize = omap3_boot_nand_devices[i].pagesize;
889
 
+            break;
890
 
+        }
891
 
+    }
892
 
+    /* TODO: if device is not recognized at this state, we should
893
 
+     * issue READ ID2 command to the device and get device parameters
894
 
+     * from there */
895
 
+    if (nd->pagesize) {
896
 
+        data = g_malloc0(nd->pagesize);
897
 
+        /* TODO: scan through 4 first blocks for image */
898
 
+        omap3_nand_readpage(nd, 0, data);
899
 
+        boot = omap3_boot_init(mpu, nand, data, nd->pagesize);
900
 
+        while (omap3_boot_block(data, nd->pagesize, boot))
901
 
+            omap3_nand_readpage(nd, ++page, data);
902
 
+        result = omap3_boot_finish(boot);
903
 
+        free(data);
904
 
+    }
905
 
+    free(nd);
906
 
+    return result;
907
 
+}
908
 
+
909
 
+static inline void omap3_onenand_writereg(uint16_t reg, uint16_t value)
910
 
+{
911
 
+    cpu_to_le16s(&value);
912
 
+    cpu_physical_memory_write(0x08000000 + (reg << 1), (void *)&value, 2);
913
 
+}
914
 
+
915
 
+static inline uint16_t omap3_onenand_readreg(uint16_t reg)
916
 
+{
917
 
+    uint16_t value;
918
 
+    cpu_physical_memory_read(0x08000000 + (reg << 1), (void *)&value, 2);
919
 
+    return le16_to_cpu(value);
920
 
+}
921
 
+
922
 
+static int omap3_onenand_readpage(uint16_t pagesize,
923
 
+                                  uint16_t b,
924
 
+                                  uint16_t p,
925
 
+                                  uint8_t *d)
926
 
+{
927
 
+    omap3_onenand_writereg(0xf100, b);
928
 
+    omap3_onenand_writereg(0xf107, (p & 0x3f) << 2);
929
 
+    omap3_onenand_writereg(0xf200, 0x0800);
930
 
+    omap3_onenand_writereg(0xf101, 0);
931
 
+    omap3_onenand_writereg(0xf241, 0);
932
 
+    omap3_onenand_writereg(0xf220, 0);
933
 
+    if (!(omap3_onenand_readreg(0xf241) & 0x8000) ||
934
 
+        (omap3_onenand_readreg(0xf240) & 0x0400))
935
 
+        return 0;
936
 
+    cpu_physical_memory_read(0x08000400, (void *)d, pagesize);
937
 
+    return 1;
938
 
+}
939
 
+
940
 
+static int omap3_onenand_boot(struct omap_mpu_state_s *s)
941
 
+{
942
 
+    uint32_t x;
943
 
+    uint16_t i, j, pagesize;
944
 
+    uint8_t *page;
945
 
+    struct omap3_boot_s *boot;
946
 
+    int result = 0;
947
 
+
948
 
+    /* reset device type at cs0: 16bit NOR, no wait monitoring */
949
 
+    cpu_to_le32wu(&x, 0x79001000);
950
 
+    cpu_physical_memory_write(0x6e000060, (void *)&x, 4); /* GPMC_CONFIG1_0 */
951
 
+    /* map cs0 at 0x08000000 */
952
 
+    cpu_to_le32wu(&x, 0x00000848);
953
 
+    cpu_physical_memory_write(0x6e000078, (void *)&x, 4); /* GPMC_CONFIG7_0 */
954
 
+    /* try to read onenand registers */
955
 
+    x = omap3_onenand_readreg(0xf000);                    /* manufacturer id */
956
 
+    if (!x || (x >> 8)) { /* we accept any non-zero 8bit id */
957
 
+        return 0;
958
 
+    }
959
 
+    pagesize = omap3_onenand_readreg(0xf003);
960
 
+    if (pagesize != 2048 && pagesize != 1024) {
961
 
+        hw_error("%s: OneNAND page size %d not supported",
962
 
+                __FUNCTION__, pagesize);
963
 
+        return 0;
964
 
+    }
965
 
+    /* search for boot loader */
966
 
+    page = g_malloc0(pagesize);
967
 
+    for (i = 0; i < 4; i++) { /* search 4 blocks */
968
 
+        if (omap3_onenand_readpage(pagesize, i, 0, page)) {
969
 
+            boot = omap3_boot_init(s, onenand, page, pagesize);
970
 
+            for (j = 1; omap3_boot_block(page, pagesize, boot); j++)
971
 
+                if (!omap3_onenand_readpage(pagesize, i, j, page))
972
 
+                    break;
973
 
+            result = omap3_boot_finish(boot);
974
 
+            if (result)
975
 
+                break;
976
 
+        }
977
 
+    }
978
 
+    free(page);
979
 
+    return result;
980
 
+}
981
 
+
982
 
+void omap3_boot_rom_init(struct omap_mpu_state_s *s)
983
 
+{
984
 
+    const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
985
 
+
986
 
+    if (!s->bootrom_initialized) {
987
 
+        s->bootrom_initialized = 1;
988
 
+        memory_region_init_ram(&s->bootrom, "omap3_boot_rom",
989
 
+                               OMAP3XXX_BOOTROM_SIZE);
990
 
+        memory_region_set_readonly(&s->bootrom, true);
991
 
+        memory_region_add_subregion(get_system_memory(),
992
 
+                                    OMAP3_Q1_BASE + 0x14000,
993
 
+                                    &s->bootrom);
994
 
+        cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x14000,
995
 
+                                      omap3_boot_rom,
996
 
+                                      sizeof(omap3_boot_rom));
997
 
+        cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x1bffc,
998
 
+                                      rom_version,
999
 
+                                      sizeof(rom_version));
1000
 
+        cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
1001
 
+                                  omap3_sram_vectors,
1002
 
+                                  sizeof(omap3_sram_vectors));
1003
 
+    }
1004
 
+}
1005
 
+
1006
 
+void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
1007
 
+{
1008
 
+    uint8_t x[4] = {0, 0, 0, 0};
1009
 
+    int result = 0;
1010
 
+    
1011
 
+    /* only emulate the boot rom if it was initialized earlier */
1012
 
+    if (!s->bootrom_initialized) {
1013
 
+        return;
1014
 
+    }
1015
 
+    
1016
 
+    /* here we are relying on all memories to be attached and gpmc_attach
1017
 
+     * to fill in DEVICETYPE field correctly for CS0 for us */
1018
 
+    cpu_physical_memory_read(0x6e000060, x, 4); /* GPMC_CONFIG1_0 */
1019
 
+    switch (((x[1] >> 2) & 3)) {
1020
 
+        case 0: /* NOR */
1021
 
+            result = omap3_onenand_boot(s);
1022
 
+            break;
1023
 
+        case 2: /* NAND */
1024
 
+            result = omap3_nand_boot(s, ((x[1] >> 4) & 3) == 1);
1025
 
+            break;
1026
 
+        default:
1027
 
+            break;
1028
 
+    }
1029
 
+
1030
 
+    /* if no boot loader found yet, try the MMC/SD card... */
1031
 
+    if (!result)
1032
 
+        result = omap3_mmc_boot(s);
1033
 
+
1034
 
+    /* move PC to the boot ROM reset vector */
1035
 
+    s->cpu->env.regs[15] = 0x40014000;
1036
 
+
1037
 
+    if (!result) { /* no boot device found */
1038
 
+        /* move PC to the appropriate ROM dead loop address */
1039
 
+        s->cpu->env.regs[15] = 0x400140a4;
1040
 
+        /* ...on second thought, let's just call it a day and quit */
1041
 
+        hw_error("no boot device found");
1042
 
+    }
1043
 
+}
1044
 
1.8.1.2
1045