2 * TI OMAP3 boot ROM emulation. Based on information in the OMAP34xx 3.1
3 * Technical Reference Manual from Texas Instruments.
5 * Copyright (C) 2009 Nokia Corporation
7 * The OMAP3 boot ROM service routines accessed via ARM SMC instruction
8 * are not available in this emulation due to the limited availability
9 * of public documentation on the ARM TrustZone functionality. However
10 * it seems executing the SMC instruction as a NOP causes no harm.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 or
15 * (at your option) version 3 of the License.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "qemu-char.h"
34 /* list of supported NAND devices according to the OMAP34xx TRM */
39 } omap3_boot_nand_devices[] = {
40 {0xe6, 512, 64}, {0x33, 512, 128}, {0x73, 512, 128},
41 {0x43, 512, 128}, {0x53, 512, 128}, {0x35, 512, 256},
42 {0x75, 512, 256}, {0x45, 512, 256}, {0x55, 512, 256},
43 {0x36, 512, 512}, {0x76, 512, 512}, {0x46, 512, 512},
44 {0x56, 512, 512}, {0xa2, 2048, 512}, {0xf2, 2048, 512},
45 {0xb2, 2048, 512}, {0xc2, 2048, 512}, {0x39, 512, 1024},
46 {0x79, 512, 1024}, {0x49, 512, 1024}, {0x59, 512, 1024},
47 {0x78, 512, 1024}, {0x72, 512, 1024}, {0x74, 512, 1024},
48 {0xa1, 2048, 1024}, {0xf1, 2048, 1024}, {0xb1, 2048, 1024},
49 {0xc1, 2048, 1024}, {0xaa, 2048, 2048}, {0xda, 2048, 2048},
50 {0xba, 2048, 2048}, {0xca, 2048, 2048}, {0x71, 512, 2048},
51 {0x51, 512, 2048}, {0x31, 512, 2048}, {0x41, 512, 2048},
52 {0xac, 2048, 4096}, {0xdc, 2048, 4096}, {0xbc, 2048, 4096},
53 {0xcc, 2048, 4096}, {0xa3, 2048, 8192}, {0xd3, 2048, 8192},
54 {0xb3, 2048, 8192}, {0xc3, 2048, 8192}, {0xa5, 2048, 16384},
55 {0xd5, 2048, 16384}, {0xb5, 2048, 16384}, {0xc5, 2048, 16384},
56 {0xa7, 2048, 32768}, {0xb7, 2048, 32768}, {0xae, 2048, 65536},
61 struct omap3_nand_boot_desc_s {
67 static const uint8_t omap3_boot_rom[] = { /* 0x40014000-0x4001bfff */
68 /* 0x40014000: ROM Exception vectors */
69 0x3e, 0x00, 0x00, 0xea, /* b 0x40014100 */
70 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
71 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
72 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
73 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
74 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
75 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
76 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
77 /* 0x40014020: ROM CRC */
78 0xff, 0xff, 0xff, 0xff,
79 /* 0x40014024: unused(?), we use it for some data */
80 0xc8, 0xff, 0x20, 0x40, /* 0x40014024: undef sram vector address */
81 0xcc, 0xff, 0x20, 0x40, /* 0x40014028: swi sram vector address */
82 0xd0, 0xff, 0x20, 0x40, /* 0x4001402c: pabt sram vector address */
83 0xd4, 0xff, 0x20, 0x40, /* 0x40014030: dabt sram vector address */
84 0xd8, 0xff, 0x20, 0x40, /* 0x40014034: unused sram vector address */
85 0xdc, 0xff, 0x20, 0x40, /* 0x40014038: irq sram vector address */
86 0xe0, 0xff, 0x20, 0x40, /* 0x4001403c: fiq sram vector address */
87 0xff, 0xff, 0xff, 0xff, /* 0x40014040: boot loader image start address */
88 0xff, 0xff, 0xff, 0xff, /* 0x40014044: booting parameter structure 0-3 */
89 0xff, 0xff, 0xff, 0xff, /* 0x40014048: booting parameter structure 4-7 */
90 0xff, 0xff, 0xff, 0xff, /* 0x4001404c: booting parameter structure 8-11 */
91 0x0e, 0xf0, 0xb0, 0xe1, /* 0x40014050: "movs pc, lr" */
92 0xff, 0xff, 0xff, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
96 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
98 /* 0x40014080: Dead loops */
99 0xfe, 0xff, 0xff, 0xea, /* b 0x40014080 @ undefined exception */
100 0xfe, 0xff, 0xff, 0xea, /* b 0x40014084 @ swi exception */
101 0xfe, 0xff, 0xff, 0xea, /* b 0x40014088 @ prefetch abort exception */
102 0xfe, 0xff, 0xff, 0xea, /* b 0x4001408c @ data abort exception */
103 0xfe, 0xff, 0xff, 0xea, /* b 0x40014090 @ unused exception */
104 0xfe, 0xff, 0xff, 0xea, /* b 0x40014094 @ irq exception */
105 0xfe, 0xff, 0xff, 0xea, /* b 0x40014098 @ fiq exception */
106 0xfe, 0xff, 0xff, 0xea, /* b 0x4001409c @ validation tests pass */
107 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a0 @ validation tests fail */
108 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a4 @ boot failed: no more devices */
109 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a8 @ image not executed or returned */
110 0xfe, 0xff, 0xff, 0xea, /* b 0x400140ac @ reserved */
111 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b0 @ reserved */
112 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b4 @ reserved */
113 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b8 @ reserved */
114 0xfe, 0xff, 0xff, 0xea, /* b 0x400140bc @ reserved */
115 /* 0x400140c0: should perform a software reset & jump to r0 */
116 0x00, 0xf0, 0xa0, 0xe1, /* mov pc, r0 */
117 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
125 /* 0x40014100: code, ROM emulation uses this to launch the
126 * boot loader after it has been read into memory */
127 0xc8, 0x10, 0x1f, 0xe5, /* ldr r1, [#0x40014040] @ boot loader start */
128 0xb0, 0x0c, 0x0f, 0xe3, /* movw r0, #0xfcb0 */
129 0x20, 0x00, 0x44, 0xe3, /* movt r0, #0x4020 @ stack top at 0x4020fcb0 */
130 0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf @ enter SYS mode */
131 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
132 0x80, 0x0c, 0x40, 0xe2, /* sub r0, r0, #32768 @ 32kB SYS/USR stack */
133 0xd1, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd1 @ enter FIQ mode */
134 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
135 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB FIQ stack */
136 0xd2, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd2 @ enter IRQ mode */
137 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
138 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB IRQ stack */
139 0xd7, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd7 @ enter ABT mode */
140 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
141 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB ABT stack */
142 0xdb, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdb @ enter UND mode */
143 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
144 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB UND stack */
145 0xd3, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd3 @ enter SVC mode */
146 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 @ 23kB left for SVC stack */
147 0x44, 0x00, 0x04, 0xe3, /* movw r0, #0x4044 */
148 0x01, 0x00, 0x44, 0xe3, /* movt r0, #0x4001 @ r0 -> booting parameter struct */
149 0x01, 0xf0, 0xa0, 0xe1, /* mov pc, r1 */
152 /* SRAM exception vectors, to be placed at 0x4020ffc8 */
153 static const uint8_t omap3_sram_vectors[] = {
154 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe4] @ undefined */
155 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe8] @ swi */
156 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffec] @ prefetch abort */
157 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff0] @ data abort */
158 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff4] @ unused */
159 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff8] @ irq */
160 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fffc] @ fiq */
161 0x80, 0x40, 0x01, 0x00, /* 0x14080 */
162 0x50, 0x40, 0x01, 0x40, /* 0x40014050 (default is 0x14084) */
163 0x88, 0x40, 0x01, 0x00, /* 0x14088 */
164 0x8c, 0x40, 0x01, 0x00, /* 0x1408c */
165 0x90, 0x40, 0x01, 0x00, /* 0x14090 */
166 0x94, 0x40, 0x01, 0x00, /* 0x14094 */
167 0x98, 0x40, 0x01, 0x00, /* 0x14098 */
170 static inline uint32_t omap3_get_le32(const void *p)
172 const uint8_t *q = (const uint8_t *)p;
181 static inline uint32_t omap3_get_le16(const void *p)
183 const uint8_t *q = (const uint8_t *)p;
190 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
194 cpu_physical_memory_read(addr, x, 4);
196 x[1] = (lsb >> 8) & 0xff;
197 cpu_physical_memory_write(addr, x, 4);
210 } omap3_boot_device_t;
212 struct omap3_boot_s {
213 struct omap_mpu_state_s *mpu;
214 omap3_boot_device_t devicetype;
224 target_phys_addr_t addr;
228 static struct omap3_boot_s *omap3_boot_init(struct omap_mpu_state_s *mpu,
229 omap3_boot_device_t dtype,
233 struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
235 s->devicetype = dtype;
237 if (data_len >= 512) {
238 if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
239 || !strncasecmp((char *)(data + 0x14), "chram", 5)
240 || !strncasecmp((char *)(data + 0x14), "chflash", 7)
241 || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
242 s->state = confighdr;
247 static void omap3_boot_chsettings(struct omap3_boot_s *boot,
248 const uint8_t *chtoc)
252 if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
253 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
256 if (!chtoc[4]) { /* section disabled? */
259 if (omap3_get_le16(chtoc + 5) != 0x0001) {
260 fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
261 omap3_get_le16(chtoc));
264 boot->chflags |= 0x01;
265 flags = omap3_get_le32(chtoc + 8);
268 cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
269 cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
270 cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
271 if (flags & (1 << 2)) { /* clock configuration */
272 cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
273 cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
275 if (flags & (1 << 5)) { /* DPLL3 CORE */
276 if (flags & (1 << 8)) { /* enable DPLL3 bypass */
277 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
278 x &= ~7; x |= 5; /* set DPLL3 bypass */
279 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
281 cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
282 cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
283 cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
285 if (flags & (1 << 3)) { /* DPLL4 PER */
286 if (flags & (1 << 6)) { /* enable DPLL4 bypass */
287 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
288 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
289 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
291 cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
292 cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
293 cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
294 cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
296 if (flags & (1 << 3)) { /* DPLL1 MPU */
297 if (flags & (1 << 7)) { /* enable DPLL1 bypass */
298 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
299 x &= ~7; x |= 5; /* set DPLL1 bypass */
300 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
302 cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
303 cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
304 cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
305 cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
306 cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
308 switch ((flags >> 24) & 0xff) {
309 case 0x01: x = 0; break; /* 12MHz */
310 case 0x02: x = 1; break; /* 13MHz */
311 case 0x03: x = 5; break; /* 16.8MHz */
312 case 0x04: x = 2; break; /* 19.2MHz */
313 case 0x05: x = 3; break; /* 26MHz */
314 case 0x06: x = 4; break; /* 38.4MHz */
316 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
320 if (x != omap3_get_le32(chtoc + 0x04)) {
321 fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
326 static void omap3_boot_chram(struct omap3_boot_s *boot,
327 const uint8_t *chtoc)
329 if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
330 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
333 if (!chtoc[4]) { /* section disabled? */
336 boot->chflags |= 0x02;
337 omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
338 omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
339 cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4); /* SDRC_DLLA_CTRL */
341 cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4); /* SDRC_MCFG_0 */
342 omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
343 omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
344 omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
345 omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
346 cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_0 */
347 cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_0 */
348 cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_0 */
350 cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4); /* SDRC_MCFG_1 */
351 omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
352 omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
353 omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
354 omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
355 cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_1 */
356 cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_1 */
357 cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_1 */
360 static void omap3_boot_chflash(struct omap3_boot_s *boot,
361 const uint8_t *chtoc)
363 if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
364 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
367 if (!chtoc[4]) { /* section disabled? */
370 boot->chflags |= 0x04;
371 omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
372 omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
373 omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
374 omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
375 cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4); /* GPMC_CONFIG1_0 */
376 cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4); /* GPMC_CONFIG2_0 */
377 cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4); /* GPMC_CONFIG3_0 */
378 cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4); /* GPMC_CONFIG4_0 */
379 cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4); /* GPMC_CONFIG5_0 */
380 cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4); /* GPMC_CONFIG6_0 */
381 cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4); /* GPMC_CONFIG7_0 */
382 cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4); /* GPMC_PREFETCH_CONFIG1 */
383 omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
384 omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
385 /* TODO: ECC config registers. The TRM spec is not clear on these */
388 static void omap3_boot_chmmcsd(struct omap3_boot_s *boot,
389 const uint8_t *chtoc)
391 if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
392 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
395 if (!chtoc[4]) { /* section disabled? */
398 boot->chflags |= 0x08;
399 /* TODO: MMCHS registers */
402 /* returns non-zero if more blocks are needed */
403 static uint32_t omap3_boot_block(const uint8_t *data,
405 struct omap3_boot_s *s)
407 const uint8_t *p = 0;
413 for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
414 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
415 omap3_boot_chsettings(s, p + omap3_get_le32(p));
416 else if (!strcasecmp((char *)(p + 0x14), "chram"))
417 omap3_boot_chram(s, p + omap3_get_le32(p));
418 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
419 omap3_boot_chflash(s, p + omap3_get_le32(p));
420 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
421 omap3_boot_chmmcsd(s, p + omap3_get_le32(p));
423 fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
424 __FUNCTION__, (char *)(p + 0x14));
438 s->count = omap3_get_le32(data);
439 s->addr = omap3_get_le32(data + 4);
440 if (!s->count || (s->count >> 24) || !s->addr || s->addr == 0xffffffff)
442 /* patch image start address in boot ROM */
443 cpu_physical_memory_write_rom(0x40014040, data + 4, 4);
444 /* start copying image */
450 i = (s->count >= data_len) ? data_len : s->count;
451 cpu_physical_memory_write(s->addr, data, i);
463 /* returns non-zero if boot has finished succesfully */
464 static int omap3_boot_finish(struct omap3_boot_s *s)
467 0, 0, 0, 0, /* last received booting message */
468 (uint8_t)s->devicetype,
472 0, 0, 0, 0 /* device descriptor */
474 int result = (s->state == done);
477 /* fill in the booting parameter structure */
478 cpu_physical_memory_write_rom(0x40014044, x, 12);
484 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
485 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
489 /* there are 0x10 items with 0x20 bytes per item */
490 for (i = 0x10; i--; s += 0x20) {
491 if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
492 if (!*s || !strncasecmp((void *)s, "mlo ", 8+3)) return s;
497 struct omap3_fat_drv_s {
498 BlockDriverState *bs;
499 uint8_t ptype; /* 12, 16, 32 */
500 uint64_t c0; /* physical byte offset for data cluster 0 */
501 uint64_t fat; /* physical byte offset for used FAT sector 0 */
502 uint32_t spc; /* sectors per cluster */
505 /* returns cluster data in the buffer and next cluster chain number
506 or 0 if unsuccessful */
507 static uint32_t omap3_read_fat_cluster(uint8_t *data,
508 struct omap3_fat_drv_s *drv,
512 uint32_t len = drv->spc * 0x200; /* number of bytes to read */
514 switch (drv->ptype) { /* check for EOF */
515 case 12: if (cl > 0xff0) return 0; break;
516 case 16: if (cl > 0xfff0) return 0; break;
517 case 32: if (cl > 0x0ffffff0) return 0; break;
521 if (bdrv_pread(drv->bs,
522 drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
526 switch (drv->ptype) { /* determine next cluster # */
528 fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
532 return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
533 ? 0 : omap3_get_le16(buf);
535 return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
536 ? 0 : omap3_get_le32(buf) & 0x0fffffff;
543 static int omap3_mmc_fat_boot(BlockDriverState *bs,
546 struct omap_mpu_state_s *mpu)
548 struct omap3_fat_drv_s drv;
549 struct omap3_boot_s *boot;
550 uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
551 const uint8_t *p, *q;
555 /* determine FAT type */
558 fatsize = omap3_get_le16(sector + 0x16);
560 fatsize = omap3_get_le32(sector + 0x24);
561 bootsize = omap3_get_le16(sector + 0x0e);
562 cluster0 = bootsize + fatsize * sector[0x10];
563 rootsize = omap3_get_le16(sector + 0x11);
567 drv.spc = sector[0x0d];
568 i = omap3_get_le16(sector + 0x13);
570 i = omap3_get_le32(sector + 0x20);
571 i = (i - (cluster0 + rootsize)) / drv.spc;
572 drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
574 /* search for boot loader file */
576 drv.fat = (bootsize + pstart) * 0x200;
577 drv.c0 = (cluster0 + pstart) * 0x200;
578 if (drv.ptype == 32) {
579 i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
580 j = omap3_get_le16(sector + 0x28);
582 drv.fat += (j & 0x0f) * fatsize * 0x200;
583 cluster = qemu_mallocz(drv.spc * 0x200);
584 for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
585 for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
586 p = omap3_scan_fat_dir_sector(q);
588 memcpy(sector, q - 0x200, 0x200); /* save the sector */
591 } else { /* FAT12/16 */
592 for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
593 if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
595 p = omap3_scan_fat_dir_sector(sector);
599 if (p && *p) { /* did we indeed find the file? */
600 i = omap3_get_le16(p + 0x14);
602 i |= omap3_get_le16(p + 0x1a);
604 uint8 *data = qemu_mallocz(j);
605 if ((i = omap3_read_fat_cluster(data, &drv, i))) {
606 boot = omap3_boot_init(mpu, mmc1, data, j);
607 boot->state = imagehdr; /* override CH detection */
608 while (omap3_boot_block(data, j, boot))
609 i = omap3_read_fat_cluster(data, &drv, i);
610 result = omap3_boot_finish(boot);
612 fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
616 fprintf(stderr, "%s: MLO file not found in the root directory\n",
622 static int omap3_mmc_raw_boot(BlockDriverState *bs,
624 struct omap_mpu_state_s *mpu)
626 struct omap3_boot_s *boot;
630 if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
631 boot = omap3_boot_init(mpu, mmc1, sector, 0x200);
632 if (boot->state == confighdr) { /* CH must be present for raw boot */
633 while (omap3_boot_block(sector, 0x200, boot)) {
634 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
635 fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
641 result = (boot->state == done);
647 /* returns non-zero if successful, zero if unsuccessful */
648 static int omap3_mmc_boot(struct omap_mpu_state_s *s)
650 BlockDriverState *bs;
651 int sdindex = drive_get_index(IF_SD, 0, 0);
656 /* very simple implementation for GP device boot,
657 supports only two modes:
658 1. MBR partition table with an active FAT partition
659 and boot loader file (MLO) in its root directory, or
660 2. CH sector located on first sector, followed by boot loader image */
662 bs = drives_table[sdindex].bdrv;
663 sector = qemu_mallocz(0x200);
664 if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
665 for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10)
666 if (p[0] == 0x80) break;
667 if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
668 && i < 4 /* active partition exists */
669 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
670 || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
671 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
672 sector, 0x200) == 0x200
673 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
674 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
676 result = omap3_mmc_raw_boot(bs, sector, s);
683 static inline void omap3_nand_sendcmd(struct omap3_nand_boot_desc_s *nd,
686 uint8_t x[2] = { cmd, 0 };
688 cpu_physical_memory_write(0x6e00007c, x, nd->bus16 ? 2 : 1);
691 static inline void omap3_nand_sendaddr_byte(struct omap3_nand_boot_desc_s *nd,
694 uint8_t x[2] = { a, 0 };
696 cpu_physical_memory_write(0x6e000080, x, nd->bus16 ? 2 : 1);
699 static inline uint8_t omap3_nand_readbyte(struct omap3_nand_boot_desc_s *nd)
703 cpu_physical_memory_read(0x6e000084, x, nd->bus16 ? 2 : 1);
707 static inline void omap3_nand_readpage(struct omap3_nand_boot_desc_s *nd,
713 omap3_nand_sendcmd(nd, 0x00); /* read page */
714 omap3_nand_sendaddr_byte(nd, 0x00);
715 if (nd->pagesize >= 2048) {
716 omap3_nand_sendaddr_byte(nd, 0x00);
717 omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
718 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
719 if (nd->capacity_Mb >= 2048)
720 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 16) & 0xff));
721 omap3_nand_sendcmd(nd, 0x30); /* confirm read */
723 omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
724 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
727 for (i = nd->pagesize / 2; i--; data += 2)
728 cpu_physical_memory_read(0x6e000084, data, 2);
730 for (i = nd->pagesize; i--; data++)
731 cpu_physical_memory_read(0x6e000084, data, 1);
735 /* returns non-zero if successful, zero if unsuccessful */
736 static int omap3_nand_boot(struct omap_mpu_state_s *mpu, int bus16)
738 struct omap3_nand_boot_desc_s *nd;
739 struct omap3_boot_s *boot;
745 /* TODO: support bad block marks */
746 nd = qemu_mallocz(sizeof(struct omap3_nand_boot_desc_s));
748 omap3_nand_sendcmd(nd, 0xff); /* reset */
749 omap3_nand_sendcmd(nd, 0x90); /* read id */
750 omap3_nand_sendaddr_byte(nd, 0);
751 id[0] = omap3_nand_readbyte(nd); /* manufacturer id */
752 id[1] = omap3_nand_readbyte(nd); /* device id */
753 id[2] = omap3_nand_readbyte(nd); /* don't care */
754 id[3] = omap3_nand_readbyte(nd); /* attributes */
755 for (i = 0; omap3_boot_nand_devices[i].id; i++) {
756 if (omap3_boot_nand_devices[i].id == id[1]) {
757 nd->capacity_Mb = omap3_boot_nand_devices[i].capacity_Mb;
758 if (nd->capacity_Mb > 1024)
759 nd->pagesize = 1024 * (1 << (id[3] & 3));
761 nd->pagesize = omap3_boot_nand_devices[i].pagesize;
765 /* TODO: if device is not recognized at this state, we should
766 * issue READ ID2 command to the device and get device parameters
769 data = qemu_mallocz(nd->pagesize);
770 /* TODO: scan through 4 first blocks for image */
771 omap3_nand_readpage(nd, 0, data);
772 boot = omap3_boot_init(mpu, nand, data, nd->pagesize);
773 while (omap3_boot_block(data, nd->pagesize, boot))
774 omap3_nand_readpage(nd, ++page, data);
775 result = omap3_boot_finish(boot);
782 static inline void omap3_onenand_writereg(uint16_t reg, uint16_t value)
784 cpu_to_le16s(&value);
785 cpu_physical_memory_write(0x08000000 + (reg << 1), (void *)&value, 2);
788 static inline uint16_t omap3_onenand_readreg(uint16_t reg)
791 cpu_physical_memory_read(0x08000000 + (reg << 1), (void *)&value, 2);
792 return le16_to_cpu(value);
795 static int omap3_onenand_readpage(uint16_t pagesize,
800 omap3_onenand_writereg(0xf100, b);
801 omap3_onenand_writereg(0xf107, (p & 0x3f) << 2);
802 omap3_onenand_writereg(0xf200, 0x0800);
803 omap3_onenand_writereg(0xf101, 0);
804 omap3_onenand_writereg(0xf241, 0);
805 omap3_onenand_writereg(0xf220, 0);
806 if (!(omap3_onenand_readreg(0xf241) & 0x8000) ||
807 (omap3_onenand_readreg(0xf240) & 0x0400))
809 cpu_physical_memory_read(0x08000400, (void *)d, pagesize);
813 static int omap3_onenand_boot(struct omap_mpu_state_s *s)
816 uint16_t i, j, pagesize;
818 struct omap3_boot_s *boot;
821 /* reset device type at cs0: 16bit NOR, no wait monitoring */
822 cpu_to_le32wu(&x, 0x79001000);
823 cpu_physical_memory_write(0x6e000060, (void *)&x, 4); /* GPMC_CONFIG1_0 */
824 /* map cs0 at 0x08000000 */
825 cpu_to_le32wu(&x, 0x00000848);
826 cpu_physical_memory_write(0x6e000078, (void *)&x, 4); /* GPMC_CONFIG7_0 */
827 /* try to read onenand registers */
828 if (omap3_onenand_readreg(0xf000) != 0x00ec) /* manufacturer id */
830 pagesize = omap3_onenand_readreg(0xf003);
831 if (pagesize != 2048 && pagesize != 1024) {
832 fprintf(stderr, "%s: OneNAND page size %d not supported\n",
833 __FUNCTION__, pagesize);
836 /* search for boot loader */
837 page = qemu_mallocz(pagesize);
838 for (i = 0; i < 4; i++) { /* search 4 blocks */
839 if (omap3_onenand_readpage(pagesize, i, 0, page)) {
840 boot = omap3_boot_init(s, onenand, page, pagesize);
841 for (j = 1; omap3_boot_block(page, pagesize, boot); j++)
842 if (!omap3_onenand_readpage(pagesize, i, j, page))
844 result = omap3_boot_finish(boot);
854 void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
856 const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
857 uint8_t x[4] = {0, 0, 0, 0};
859 ram_addr_t bootrom_base;
861 bootrom_base = qemu_ram_alloc(OMAP3XXX_BOOTROM_SIZE);
862 cpu_register_physical_memory(OMAP3_Q1_BASE + 0x14000,
863 OMAP3XXX_BOOTROM_SIZE,
864 bootrom_base | IO_MEM_ROM);
865 cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x14000,
867 sizeof(omap3_boot_rom));
868 cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x1bffc,
870 sizeof(rom_version));
871 cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
873 sizeof(omap3_sram_vectors));
875 /* here we are relying on all memories to be attached and gpmc_attach
876 * to fill in DEVICETYPE field correctly for CS0 for us */
877 cpu_physical_memory_read(0x6e000060, x, 4); /* GPMC_CONFIG1_0 */
878 switch (((x[1] >> 2) & 3)) {
880 result = omap3_onenand_boot(s);
883 result = omap3_nand_boot(s, ((x[1] >> 4) & 3) == 1);
889 /* if no boot loader found yet, try the MMC/SD card... */
891 result = omap3_mmc_boot(s);
893 /* ensure boot ROM is mapped at zero address */
894 cpu_register_physical_memory(0, OMAP3XXX_BOOTROM_SIZE,
895 bootrom_base | IO_MEM_ROM);
897 if (!result) { /* no boot device found */
898 /* move PC to the appropriate ROM dead loop address */
899 s->env->regs[15] = 0x400140a4;
900 /* ...on second thought, let's just call it a day and quit */
901 cpu_abort(s->env, "no boot device found");