OMAP3 DPLL5 clock fix and added the missing omap3_boot.c.
[qemu] / hw / omap3_boot.c
1 /*
2  * TI OMAP3 boot ROM emulation. Based on information in the OMAP34xx 3.1
3  * Technical Reference Manual from Texas Instruments.
4  *
5  * Copyright (C) 2009 Nokia Corporation
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 or
10  * (at your option) version 3 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 #include "hw.h"
22 #include "arm-misc.h"
23 #include "omap.h"
24 #include "sysemu.h"
25 #include "qemu-char.h"
26 #include "flash.h"
27 #include "block.h"
28
29 /* list of supported NAND devices according to the OMAP34xx TRM */
30 static const struct {
31     uint8_t id;
32     uint32_t pagesize;
33     uint32_t capacity_Mb;
34 } omap3_boot_nand_devices[] = {
35     {0xe6,  512,    64}, {0x33,  512,   128}, {0x73,  512,   128},
36     {0x43,  512,   128}, {0x53,  512,   128}, {0x35,  512,   256},
37     {0x75,  512,   256}, {0x45,  512,   256}, {0x55,  512,   256},
38     {0x36,  512,   512}, {0x76,  512,   512}, {0x46,  512,   512},
39     {0x56,  512,   512}, {0xa2, 2048,   512}, {0xf2, 2048,   512},
40     {0xb2, 2048,   512}, {0xc2, 2048,   512}, {0x39,  512,  1024},
41     {0x79,  512,  1024}, {0x49,  512,  1024}, {0x59,  512,  1024},
42     {0x78,  512,  1024}, {0x72,  512,  1024}, {0x74,  512,  1024},
43     {0xa1, 2048,  1024}, {0xf1, 2048,  1024}, {0xb1, 2048,  1024},
44     {0xc1, 2048,  1024}, {0xaa, 2048,  2048}, {0xda, 2048,  2048},
45     {0xba, 2048,  2048}, {0xca, 2048,  2048}, {0x71,  512,  2048},
46     {0x51,  512,  2048}, {0x31,  512,  2048}, {0x41,  512,  2048},
47     {0xac, 2048,  4096}, {0xdc, 2048,  4096}, {0xbc, 2048,  4096},
48     {0xcc, 2048,  4096}, {0xa3, 2048,  8192}, {0xd3, 2048,  8192},
49     {0xb3, 2048,  8192}, {0xc3, 2048,  8192}, {0xa5, 2048, 16384},
50     {0xd5, 2048, 16384}, {0xb5, 2048, 16384}, {0xc5, 2048, 16384},
51     {0xa7, 2048, 32768}, {0xb7, 2048, 32768}, {0xae, 2048, 65536},
52     {0xbe, 2048, 65536},
53     {0, 0, 0}
54 };
55
56 struct omap3_nand_boot_desc_s {
57     uint32_t pagesize;
58     uint32_t capacity_Mb;
59     uint8_t bus16;
60 };
61
62 /* first 80kB (reserved section) */
63 static const uint8_t omap3_boot_rom_block1[] = { /* 0x40000000-0x40013fff */
64     /* this gets mapped to zero at power-up so let's have a branch
65      * table to the upper block ROM exception vectors here */
66     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014000 */
67     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014004 */
68     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014008 */
69     0xfe, 0x4f, 0x00, 0xea, /* b 0x4001400c */
70     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014010 */
71     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014014 */
72     0xfe, 0x4f, 0x00, 0xea, /* b 0x40014018 */
73     0xfe, 0x4f, 0x00, 0xea, /* b 0x4001401c */
74 };
75
76 /* upper 32kB */
77 static const uint8_t omap3_boot_rom_block2[] = { /* 0x40014000-0x4001bfff */
78     /* 0x40014000: ROM Exception vectors */
79     0x3e, 0x00, 0x00, 0xea, /* b 0x40014100 */
80     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
81     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
82     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
83     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
84     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
85     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
86     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
87     /* 0x40014020: ROM CRC */
88     0xff, 0xff, 0xff, 0xff, 
89     /* 0x40014024: unused(?), we use it for some data */
90     0xc8, 0xff, 0x20, 0x40, /* 0x40014024: undef sram vector address */
91     0xcc, 0xff, 0x20, 0x40, /* 0x40014028: swi sram vector address */
92     0xd0, 0xff, 0x20, 0x40, /* 0x4001402c: pabt sram vector address */
93     0xd4, 0xff, 0x20, 0x40, /* 0x40014030: dabt sram vector address */
94     0xd8, 0xff, 0x20, 0x40, /* 0x40014034: unused sram vector address */
95     0xdc, 0xff, 0x20, 0x40, /* 0x40014038: irq sram vector address */
96     0xe0, 0xff, 0x20, 0x40, /* 0x4001403c: fiq sram vector address */
97     0xff, 0xff, 0xff, 0xff, /* 0x40014040: boot loader image start address */
98     0xff, 0xff, 0xff, 0xff, /* 0x40014044: booting parameter structure 0-3 */
99     0xff, 0xff, 0xff, 0xff, /* 0x40014048: booting parameter structure 4-7 */
100     0xff, 0xff, 0xff, 0xff, /* 0x4001404c: booting parameter structure 8-11 */
101     0x0e, 0xf0, 0xb0, 0xe1, /* 0x40014050: "movs pc, lr" */
102     0xff, 0xff, 0xff, 0xff,
103     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
104     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
105     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108     /* 0x40014080: Dead loops */
109     0xfe, 0xff, 0xff, 0xea, /* b 0x40014080 @ undefined exception */
110     0xfe, 0xff, 0xff, 0xea, /* b 0x40014084 @ swi exception */
111     0xfe, 0xff, 0xff, 0xea, /* b 0x40014088 @ prefetch abort exception */
112     0xfe, 0xff, 0xff, 0xea, /* b 0x4001408c @ data abort exception */
113     0xfe, 0xff, 0xff, 0xea, /* b 0x40014090 @ unused exception */
114     0xfe, 0xff, 0xff, 0xea, /* b 0x40014094 @ irq exception */
115     0xfe, 0xff, 0xff, 0xea, /* b 0x40014098 @ fiq exception */
116     0xfe, 0xff, 0xff, 0xea, /* b 0x4001409c @ validation tests pass */
117     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a0 @ validation tests fail */
118     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a4 @ boot failed: no more devices */
119     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a8 @ image not executed or returned */
120     0xfe, 0xff, 0xff, 0xea, /* b 0x400140ac @ reserved */
121     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b0 @ reserved */
122     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b4 @ reserved */
123     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b8 @ reserved */
124     0xfe, 0xff, 0xff, 0xea, /* b 0x400140bc @ reserved */
125     /* 0x400140c0: should perform a software reset & jump to r0 */
126     0x00, 0xf0, 0xa0, 0xe1, /* mov pc, r0 */
127     0xff, 0xff, 0xff, 0xff,
128     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135     /* 0x40014100: code, ROM emulation uses this to launch the
136      * boot loader after it has been read into memory */
137     0xc8, 0x10, 0x1f, 0xe5, /* ldr r1, [#0x40014040] @ boot loader start */
138     0xb0, 0x0c, 0x0f, 0xe3, /* movw r0, #0xfcb0 */
139     0x20, 0x00, 0x44, 0xe3, /* movt r0, #0x4020   @ stack top at 0x4020fcb0 */
140     0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf  @ enter SYS mode */
141     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
142     0x80, 0x0c, 0x40, 0xe2, /* sub r0, r0, #32768 @ 32kB SYS/USR stack */
143     0xd1, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd1  @ enter FIQ mode */
144     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
145     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB FIQ stack */
146     0xd2, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd2  @ enter IRQ mode */
147     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
148     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB IRQ stack */
149     0xd7, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd7  @ enter ABT mode */
150     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
151     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB ABT stack */
152     0xdb, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdb  @ enter UND mode */
153     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
154     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB UND stack */
155     0xd3, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd3  @ enter SVC mode */
156     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0         @ 23kB left for SVC stack */
157     0x44, 0x00, 0x04, 0xe3, /* movw r0, #0x4044 */
158     0x01, 0x00, 0x44, 0xe3, /* movt r0, #0x4001   @ r0 -> booting parameter struct */
159     0x01, 0xf0, 0xa0, 0xe1, /* mov pc, r1 */
160 };
161
162 /* SRAM exception vectors, to be placed at 0x4020ffc8 */
163 static const uint8_t omap3_sram_vectors[] = {
164     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe4] @ undefined */
165     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe8] @ swi */
166     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffec] @ prefetch abort */
167     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff0] @ data abort */
168     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff4] @ unused */
169     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff8] @ irq */
170     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fffc] @ fiq */
171     0x80, 0x40, 0x01, 0x00, /* 0x14080 */
172     0x50, 0x40, 0x01, 0x40, /* 0x40014050 (default is 0x14084) */
173     0x88, 0x40, 0x01, 0x00, /* 0x14088 */
174     0x8c, 0x40, 0x01, 0x00, /* 0x1408c */
175     0x90, 0x40, 0x01, 0x00, /* 0x14090 */
176     0x94, 0x40, 0x01, 0x00, /* 0x14094 */
177     0x98, 0x40, 0x01, 0x00, /* 0x14098 */
178 };
179
180 static inline uint32_t omap3_get_le32(const void *p)
181 {
182     const uint8_t *q = (const uint8_t *)p;
183     uint32_t v;
184     v = q[3]; v <<= 8;
185     v |= q[2]; v <<= 8;
186     v |= q[1]; v <<= 8;
187     v |= q[0];
188     return v;
189 }
190
191 static inline uint32_t omap3_get_le16(const void *p)
192 {
193     const uint8_t *q = (const uint8_t *)p;
194     uint32_t v;
195     v = q[1]; v <<= 8;
196     v |= q[0];
197     return v;
198 }
199
200 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
201 {
202     uint8_t x[4];
203     
204     cpu_physical_memory_read(addr, x, 4);
205     x[0] = lsb & 0xff;
206     x[1] = (lsb >> 8) & 0xff;
207     cpu_physical_memory_write(addr, x, 4);
208 }
209
210 typedef enum {
211     xip = 1,
212     nand,
213     onenand,
214     doc,
215     mmc2,
216     mmc1,
217     xipwait,
218     uart = 0x10,
219     hsusb,
220 }  omap3_boot_device_t;
221
222 struct omap3_boot_s {
223     struct omap_mpu_state_s *mpu;
224     omap3_boot_device_t devicetype;
225     enum {
226         undefined = 0,
227         confighdr,
228         chdone,
229         imagehdr,
230         copy,
231         done
232     } state;
233     uint8_t chflags;
234     target_phys_addr_t addr;
235     uint32_t count;
236 };
237
238 static struct omap3_boot_s *omap3_boot_init(struct omap_mpu_state_s *mpu,
239                                             omap3_boot_device_t dtype,
240                                             const uint8_t *data,
241                                             uint32_t data_len)
242 {
243     struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
244     s->mpu = mpu;
245     s->devicetype = dtype;
246     s->state = chdone;
247     if (data_len >= 512) {
248         if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
249             || !strncasecmp((char *)(data + 0x14), "chram", 5)
250             || !strncasecmp((char *)(data + 0x14), "chflash", 7)
251             || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
252             s->state = confighdr;
253     }
254     return s;
255 }
256
257 static void omap3_boot_chsettings(struct omap3_boot_s *boot,
258                                   const uint8_t *chtoc)
259 {
260     uint32_t flags, x;
261     
262     if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
263         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
264         return;
265     }
266     if (!chtoc[4]) { /* section disabled? */
267         return;
268     }
269     if (omap3_get_le16(chtoc + 5) != 0x0001) {
270         fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
271                 omap3_get_le16(chtoc));
272         return;
273     }
274     boot->chflags |= 0x01;
275     flags = omap3_get_le32(chtoc + 8);
276     chtoc += 12;
277     if (flags & 1) {
278         cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
279         cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
280         cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
281         if (flags & (1 << 2)) { /* clock configuration */
282             cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
283             cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
284         }
285         if (flags & (1 << 5)) { /* DPLL3 CORE */
286             if (flags & (1 << 8)) { /* enable DPLL3 bypass */
287                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
288                 x &= ~7; x |= 5; /* set DPLL3 bypass */
289                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
290             }
291             cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
292             cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
293             cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
294         }
295         if (flags & (1 << 3)) { /* DPLL4 PER */
296             if (flags & (1 << 6)) { /* enable DPLL4 bypass */
297                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
298                 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
299                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
300             }
301             cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
302             cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
303             cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
304             cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
305         }
306         if (flags & (1 << 3)) { /* DPLL1 MPU */
307             if (flags & (1 << 7)) { /* enable DPLL1 bypass */
308                 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
309                 x &= ~7; x |= 5; /* set DPLL1 bypass */
310                 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
311             }
312             cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
313             cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
314             cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
315             cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
316             cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
317         }
318         switch ((flags >> 24) & 0xff) {
319             case 0x01: x = 0; break; /* 12MHz */
320             case 0x02: x = 1; break; /* 13MHz */
321             case 0x03: x = 5; break; /* 16.8MHz */
322             case 0x04: x = 2; break; /* 19.2MHz */
323             case 0x05: x = 3; break; /* 26MHz */
324             case 0x06: x = 4; break; /* 38.4MHz */
325             default:
326                 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
327                 x = 1;
328                 break;
329         }
330         if (x != omap3_get_le32(chtoc + 0x04)) {
331             fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
332         }
333     }
334 }
335
336 static void omap3_boot_chram(struct omap3_boot_s *boot,
337                              const uint8_t *chtoc)
338 {
339     if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
340         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
341         return;
342     }
343     if (!chtoc[4]) { /* section disabled? */
344         return;
345     }
346     boot->chflags |= 0x02;
347     omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
348     omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
349     cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
350     
351     cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
352     omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
353     omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
354     omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
355     omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
356     cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
357     cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
358     cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
359     
360     cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
361     omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
362     omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
363     omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
364     omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
365     cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
366     cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
367     cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
368 }
369
370 static void omap3_boot_chflash(struct omap3_boot_s *boot,
371                                const uint8_t *chtoc)
372 {
373     if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
374         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
375         return;
376     }
377     if (!chtoc[4]) { /* section disabled? */
378         return;
379     }
380     boot->chflags |= 0x04;
381     omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
382     omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
383     omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
384     omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
385     cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
386     cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
387     cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
388     cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
389     cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
390     cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
391     cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
392     cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
393     omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
394     omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
395     /* TODO: ECC config registers. The TRM spec is not clear on these */
396 }
397
398 static void omap3_boot_chmmcsd(struct omap3_boot_s *boot,
399                                const uint8_t *chtoc)
400 {
401     if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
402         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
403         return;
404     }
405     if (!chtoc[4]) { /* section disabled? */
406         return;
407     }
408     boot->chflags |= 0x08;
409     /* TODO: MMCHS registers */
410 }
411
412 /* returns non-zero if more blocks are needed */
413 static uint32_t omap3_boot_block(const uint8_t *data,
414                                  uint32_t data_len,
415                                  struct omap3_boot_s *s)
416 {
417     const uint8_t *p = 0;
418     uint32_t i = 0;
419     
420     switch (s->state) {
421         case confighdr:
422             i = data_len;
423             for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
424                 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
425                     omap3_boot_chsettings(s, p + omap3_get_le32(p));
426                 else if (!strcasecmp((char *)(p + 0x14), "chram"))
427                     omap3_boot_chram(s, p + omap3_get_le32(p));
428                 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
429                     omap3_boot_chflash(s, p + omap3_get_le32(p));
430                 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
431                     omap3_boot_chmmcsd(s, p + omap3_get_le32(p));
432                 else
433                     fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
434                             __FUNCTION__, (char *)(p + 0x14));
435             }
436             data += 512;
437             data_len -= 512;
438             s->state = chdone;
439             /* fallthrough */
440         case chdone:
441             s->state = imagehdr;
442             /* fallthrough */
443         case imagehdr:
444             if (!data_len)
445                 return 1;
446             if (data_len < 8)
447                 break;
448             s->count = omap3_get_le32(data);
449             s->addr = omap3_get_le32(data + 4);
450             if (!s->count || (s->count >> 24) || !s->addr || s->addr == 0xffffffff)
451                 break;
452             /* patch image start address in boot ROM */
453             cpu_physical_memory_write_rom(0x40014040, data + 4, 4);
454             /* start copying image */
455             data += 8;
456             data_len -= 8;
457             s->state = copy;
458             /* fallthrough */
459         case copy:
460             i = (s->count >= data_len) ? data_len : s->count;
461             cpu_physical_memory_write(s->addr, data, i);
462             s->addr += i;
463             s->count -= i;
464             if (!s->count)
465                 s->state = done;
466             return s->count;
467         default:
468             break;
469     }
470     return 0;
471 }
472
473 /* returns non-zero if boot has finished succesfully */
474 static int omap3_boot_finish(struct omap3_boot_s *s)
475 {
476     uint8_t x[12] = {
477         0, 0, 0, 0, /* last received booting message */
478         (uint8_t)s->devicetype,
479         0,
480         1, /* POR */
481         s->chflags,
482         0, 0, 0, 0 /* device descriptor */
483     };
484     int result = (s->state == done);
485
486     if (result) {
487         /* fill in the booting parameter structure */
488         cpu_physical_memory_write_rom(0x40014044, x, 12);
489     }
490     free(s);
491     return result;
492 }
493
494 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
495 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
496 {
497     int i;
498     
499     /* there are 0x10 items with 0x20 bytes per item */
500     for (i = 0x10; i--; s += 0x20) {
501         if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
502         if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
503     }
504     return 0;
505 }
506
507 struct omap3_fat_drv_s {
508     BlockDriverState *bs;
509     uint8_t ptype; /* 12, 16, 32 */
510     uint64_t c0;   /* physical byte offset for data cluster 0 */
511     uint64_t fat;  /* physical byte offset for used FAT sector 0 */
512     uint32_t spc;  /* sectors per cluster */
513 };
514
515 /* returns cluster data in the buffer and next cluster chain number
516  or 0 if unsuccessful */
517 static uint32_t omap3_read_fat_cluster(uint8_t *data,
518                                        struct omap3_fat_drv_s *drv,
519                                        uint32_t cl)
520 {
521     uint8_t buf[ 4 ];
522     uint32_t len = drv->spc * 0x200; /* number of bytes to read */
523     
524     switch (drv->ptype) { /* check for EOF */
525         case 12: if (cl > 0xff0) return 0; break;
526         case 16: if (cl > 0xfff0) return 0; break;
527         case 32: if (cl > 0x0ffffff0) return 0; break;
528         default: return 0;
529     }
530     
531     if (bdrv_pread(drv->bs, 
532                    drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
533                    data, len) != len)
534         return 0;
535     
536     switch (drv->ptype) { /* determine next cluster # */
537         case 12:
538             fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
539                     __FUNCTION__);
540             break;
541         case 16:
542             return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
543             ? 0 : omap3_get_le16(buf);
544         case 32:
545             return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
546             ? 0 : omap3_get_le32(buf) & 0x0fffffff;
547         default:
548             break;
549     }
550     return 0;
551 }
552
553 static int omap3_mmc_fat_boot(BlockDriverState *bs,
554                               uint8_t *sector,
555                               uint32_t pstart,
556                               struct omap_mpu_state_s *mpu)
557 {
558     struct omap3_fat_drv_s drv;
559     struct omap3_boot_s *boot;
560     uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
561     const uint8_t *p, *q;
562     uint8_t *cluster;
563     int result = 0;
564     
565     /* determine FAT type */
566     
567     drv.bs = bs;
568     fatsize = omap3_get_le16(sector + 0x16);
569     if (!fatsize) 
570         fatsize = omap3_get_le32(sector + 0x24);
571     bootsize = omap3_get_le16(sector + 0x0e);
572     cluster0 = bootsize + fatsize * sector[0x10];
573     rootsize = omap3_get_le16(sector + 0x11);
574     if (rootsize & 0x0f)
575         rootsize += 0x10;
576     rootsize >>= 4;
577     drv.spc = sector[0x0d];
578     i = omap3_get_le16(sector + 0x13);
579     if (!i)
580         i = omap3_get_le32(sector + 0x20);
581     i = (i - (cluster0 + rootsize)) / drv.spc;
582     drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
583     
584     /* search for boot loader file */
585     
586     drv.fat = (bootsize + pstart) * 0x200;
587     drv.c0 = (cluster0 + pstart) * 0x200;
588     if (drv.ptype == 32) {
589         i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
590         j = omap3_get_le16(sector + 0x28);
591         if (j & 0x80)
592             drv.fat += (j & 0x0f) * fatsize * 0x200;
593         cluster = qemu_mallocz(drv.spc * 0x200);
594         for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
595             for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
596                 p = omap3_scan_fat_dir_sector(q);
597             if (p) 
598                 memcpy(sector, q - 0x200, 0x200); /* save the sector */
599         }
600         free(cluster);
601     } else { /* FAT12/16 */
602         for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
603             if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
604                 break;
605             p = omap3_scan_fat_dir_sector(sector);
606         }
607     }
608     
609     if (p && *p) { /* did we indeed find the file? */
610         i = omap3_get_le16(p + 0x14);
611         i <<= 16;
612         i |= omap3_get_le16(p + 0x1a);
613         j = drv.spc * 0x200;
614         uint8 *data = qemu_mallocz(j);
615         if ((i = omap3_read_fat_cluster(data, &drv, i))) {
616             boot = omap3_boot_init(mpu, mmc1, data, j);
617             boot->state = imagehdr; /* override CH detection */
618             while (omap3_boot_block(data, j, boot))
619                 i = omap3_read_fat_cluster(data, &drv, i);
620             result = omap3_boot_finish(boot);
621         } else
622             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
623                     __FUNCTION__);
624         free(data);
625     } else
626         fprintf(stderr, "%s: MLO file not found in the root directory\n",
627                 __FUNCTION__);
628     
629     return result;
630 }
631
632 static int omap3_mmc_raw_boot(BlockDriverState *bs,
633                               uint8_t *sector,
634                               struct omap_mpu_state_s *mpu)
635 {
636     struct omap3_boot_s *boot;
637     uint32_t i = 0;
638     int result = 0;
639     
640     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
641         boot = omap3_boot_init(mpu, mmc1, sector, 0x200);
642         if (boot->state == confighdr) { /* CH must be present for raw boot */
643             while (omap3_boot_block(sector, 0x200, boot)) {
644                 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
645                     fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
646                             __FUNCTION__, i);
647                     break;
648                 }
649             }
650         }
651         result = (boot->state == done);
652         free(boot);
653     }
654     return result;
655 }
656
657 /* returns non-zero if successful, zero if unsuccessful */
658 static int omap3_mmc_boot(struct omap_mpu_state_s *s)
659 {
660     BlockDriverState *bs;
661     int sdindex = drive_get_index(IF_SD, 0, 0);
662     uint8_t *sector, *p;
663     uint32_t pstart, i;
664     int result = 0;
665     
666     /* very simple implementation for GP device boot,
667      supports only two modes:
668      1. MBR partition table with an active FAT partition
669      and boot loader file (MLO) in its root directory, or
670      2. CH sector located on first sector, followed by boot loader image */
671     if (sdindex >= 0) {
672         bs = drives_table[sdindex].bdrv;
673         sector = qemu_mallocz(0x200);
674         if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
675             for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
676                 if (p[0] == 0x80) break;
677             if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
678                 && i < 4 /* active partition exists */
679                 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
680                     || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
681                 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
682                               sector, 0x200) == 0x200
683                 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
684                 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
685             else
686                 result = omap3_mmc_raw_boot(bs, sector, s);
687         }
688         free(sector);
689     }
690     return result;
691 }
692
693 static inline void omap3_nand_sendcmd(struct omap3_nand_boot_desc_s *nd,
694                                       uint8_t cmd)
695 {
696     uint8_t x[2] = { cmd, 0 };
697     
698     cpu_physical_memory_write(0x6e00007c, x, nd->bus16 ? 2 : 1);
699 }
700
701 static inline void omap3_nand_sendaddr_byte(struct omap3_nand_boot_desc_s *nd,
702                                             uint8_t a)
703 {
704     uint8_t x[2] = { a, 0 };
705     
706     cpu_physical_memory_write(0x6e000080, x, nd->bus16 ? 2 : 1);
707 }
708
709 static inline uint8_t omap3_nand_readbyte(struct omap3_nand_boot_desc_s *nd)
710 {
711     uint8_t x[2];
712     
713     cpu_physical_memory_read(0x6e000084, x, nd->bus16 ? 2 : 1);
714     return x[0];
715 }
716
717 static inline void omap3_nand_readpage(struct omap3_nand_boot_desc_s *nd,
718                                        uint32_t pageaddr,
719                                        uint8_t *data)
720 {
721     uint32_t i;
722     
723     omap3_nand_sendcmd(nd, 0x00); /* read page */
724     omap3_nand_sendaddr_byte(nd, 0x00);
725     if (nd->pagesize >= 2048) {
726         omap3_nand_sendaddr_byte(nd, 0x00);
727         omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
728         omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
729         if (nd->capacity_Mb >= 2048)
730             omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 16) & 0xff));
731         omap3_nand_sendcmd(nd, 0x30); /* confirm read */
732     } else {
733         omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
734         omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
735     }
736     if (nd->bus16) {
737         for (i = nd->pagesize / 2; i--; data += 2)
738             cpu_physical_memory_read(0x6e000084, data, 2);
739     } else {
740         for (i = nd->pagesize; i--; data++)
741             cpu_physical_memory_read(0x6e000084, data, 1);
742     }
743 }
744
745 /* returns non-zero if successful, zero if unsuccessful */
746 static int omap3_nand_boot(struct omap_mpu_state_s *mpu, int bus16)
747 {
748     struct omap3_nand_boot_desc_s *nd;
749     struct omap3_boot_s *boot;
750     uint8_t *data;
751     uint32_t page = 0;
752     int result = 0, i;
753     uint8_t id[4];
754     
755     /* TODO: support bad block marks */
756     nd = qemu_mallocz(sizeof(struct omap3_nand_boot_desc_s));
757     nd->bus16 = bus16;
758     omap3_nand_sendcmd(nd, 0xff); /* reset */
759     omap3_nand_sendcmd(nd, 0x90); /* read id */
760     omap3_nand_sendaddr_byte(nd, 0);
761     id[0] = omap3_nand_readbyte(nd); /* manufacturer id */
762     id[1] = omap3_nand_readbyte(nd); /* device id */
763     id[2] = omap3_nand_readbyte(nd); /* don't care */
764     id[3] = omap3_nand_readbyte(nd); /* attributes */
765     for (i = 0; omap3_boot_nand_devices[i].id; i++) {
766         if (omap3_boot_nand_devices[i].id == id[1]) {
767             nd->capacity_Mb = omap3_boot_nand_devices[i].capacity_Mb;
768             if (nd->capacity_Mb > 1024)
769                 nd->pagesize = 1024 * (1 << (id[3] & 3));
770             else
771                 nd->pagesize = omap3_boot_nand_devices[i].pagesize;
772             break;
773         }
774     }
775     /* TODO: if device is not recognized at this state, we should
776      * issue READ ID2 command to the device and get device parameters
777      * from there */
778     if (nd->pagesize) {
779         data = qemu_mallocz(nd->pagesize);
780         /* TODO: scan through 4 first blocks for image */
781         omap3_nand_readpage(nd, 0, data);
782         boot = omap3_boot_init(mpu, nand, data, nd->pagesize);
783         while (omap3_boot_block(data, nd->pagesize, boot))
784             omap3_nand_readpage(nd, ++page, data);
785         result = omap3_boot_finish(boot);
786         free(data);
787     }
788     free(nd);
789     return result;
790 }
791
792
793 void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
794 {
795     const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
796     uint8_t x[4] = {0, 0, 0, 0};
797     int result = 0;
798     
799     cpu_physical_memory_write_rom(OMAP3_Q1_BASE,
800                                   omap3_boot_rom_block1,
801                                   sizeof(omap3_boot_rom_block1));
802     cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x14000,
803                                   omap3_boot_rom_block2,
804                                   sizeof(omap3_boot_rom_block2));
805     cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x1bffc,
806                                   rom_version,
807                                   sizeof(rom_version));
808     cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
809                               omap3_sram_vectors,
810                               sizeof(omap3_sram_vectors));
811
812     /* if we have NAND in GPMC CS0, try to read boot loader from there.
813      * here we are relying on all memories to be attached and gpmc_attach
814      * to fill in DEVICETYPE field correctly for CS0 for us */
815     cpu_physical_memory_read(0x6e000060, x, 4); /* GPMC_CONFIG1_0 */
816     if (((x[1] >> 2) & 3) == 2) /* DEVICETYPE == NAND? */
817         result = omap3_nand_boot(s, ((x[1] >> 4) & 3) == 1);
818
819     /* TODO: support OneNAND and XIP */
820     
821     /* if no boot loader found yet, try the MMC/SD card... */
822     if (!result)
823         result = omap3_mmc_boot(s);
824     
825     if (!result) { /* no boot device found */
826         /* move PC to the appropriate ROM dead loop address */
827         s->env->regs[15] = 0x400140a4;
828         /* ...on second thought, let's just call it a day and quit */
829         cpu_abort(s->env, "no boot device found");
830     }
831 }