blob: d040ff600d5875d3f68c7df2bd4d981afba01e0f [file] [log] [blame]
Ajay Dudani168f6cb2009-12-07 19:04:02 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <app.h>
31#include <debug.h>
32#include <lib/ptable.h>
33#include <malloc.h>
34#include <dev/flash.h>
35#include <string.h>
36#include <jtag.h>
Chandan Uddaraju56228922009-12-11 21:48:48 -080037#include <kernel/thread.h>
David Ng6e1711f2010-01-19 15:27:00 -080038#include <smem.h>
Ajay Dudani168f6cb2009-12-07 19:04:02 -080039#include "bootimg.h"
40
41#define FLASH_PAGE_SIZE 2048
42#define FLASH_PAGE_BITS 11
43
44unsigned page_size = 0;
45unsigned page_mask = 0;
46
David Ng6e1711f2010-01-19 15:27:00 -080047static unsigned load_addr = 0xffffffff;
48
Ajay Dudani168f6cb2009-12-07 19:04:02 -080049#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
50
51void acpu_clock_init(void);
Chandan Uddaraju56228922009-12-11 21:48:48 -080052void platform_uninit_timer(void);
Ajay Dudani168f6cb2009-12-07 19:04:02 -080053
54int startswith(const char *str, const char *prefix)
55{
56 while(*prefix){
57 if(*prefix++ != *str++) return 0;
58 }
59 return 1;
60}
61
David Ng6e1711f2010-01-19 15:27:00 -080062unsigned set_load_address(unsigned addr)
63{
64 if (load_addr != 0xffffffff)
65 {
66 /* Already assigned */
67 return load_addr;
68 }
69
70 load_addr = addr;
71
72#ifdef PLATFORM_MSM7X30
73 /* For 7x30, override the destination RAM address based on memory type */
74 /* so the image is loaded to the larger memory segment. */
75 struct smem_board_info board_info;
76 unsigned int board_info_struct_len = sizeof(board_info);
77 unsigned smem_status;
78 char *build_type;
79
80 smem_status = smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
81 &board_info, board_info_struct_len );
82 if(!smem_status)
83 {
84 build_type = (char *)(board_info.build_id) + 8;
85 if (*build_type == 'A')
86 {
87 /* LPDDR2 configuration */
88 load_addr = 0x40000000;
89 }
90 else
91 {
92 /* LPDDR1 configuration */
93 load_addr = 0x08000000;
94 }
95 }
96#endif
97
98 return load_addr;
99}
100
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800101/* XXX */
102void verify_flash(struct ptentry *p, void *addr, unsigned len, int extra)
103{
104 uint32_t offset = 0;
105 void *buf = malloc(FLASH_PAGE_SIZE + extra);
106 int verify_extra = extra;
107 if(verify_extra > 4)
108 verify_extra = 16;
109 while(len > 0) {
110 flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE);
111 if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) {
112 dprintf(CRITICAL, "verify failed at 0x%08x\n", offset);
113 jtag_fail("verify failed");
114 return;
115 }
116 offset += FLASH_PAGE_SIZE;
117 addr += FLASH_PAGE_SIZE;
118 len -= FLASH_PAGE_SIZE;
119 if(extra) {
120 addr += extra;
121 len -= extra;
122 }
123 }
124 dprintf(INFO, "verify done %d extra bytes\n", verify_extra);
125 jtag_okay("verify done");
126}
127
128void handle_flash(const char *name, unsigned addr, unsigned sz)
129{
130 struct ptentry *ptn;
131 struct ptable *ptable;
132 void *data = (void *) addr;
133 unsigned extra = 0;
134
135 ptable = flash_get_ptable();
136 if (ptable == NULL) {
137 jtag_fail("partition table doesn't exist");
138 return;
139 }
140
141 ptn = ptable_find(ptable, name);
142 if (ptn == NULL) {
143 jtag_fail("unknown partition name");
144 return;
145 }
146
147 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
148 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
149 jtag_fail("image is not a boot image");
150 return;
151 }
152 }
153
154 if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata"))
155 extra = ((page_size >> 9) * 16);
156 else
157 sz = ROUND_TO_PAGE(sz, page_mask);
158
David Ng6e1711f2010-01-19 15:27:00 -0800159 /* Override load address if needed */
160 data = (void *)set_load_address(addr);
161
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800162 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
163 if (flash_write(ptn, extra, data, sz)) {
164 jtag_fail("flash write failure");
165 return;
166 }
167 dprintf(INFO, "partition '%s' updated\n", ptn->name);
168 jtag_okay("Done");
Chandan Uddaraju56228922009-12-11 21:48:48 -0800169 enter_critical_section();
170 platform_uninit_timer();
171 arch_disable_cache(UCACHE);
172 arch_disable_mmu();
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800173}
174
175static unsigned char *tmpbuf = 0;
176
177
178/*XXX*/
179void handle_dump(const char *name, unsigned offset)
180{
181 struct ptentry *p;
182 struct ptable *ptable;
183
184 if(tmpbuf == 0) {
185 tmpbuf = malloc(4096);
186 }
187
188 dprintf(INFO, "dump '%s' partition\n", name);
189
190 ptable = flash_get_ptable();
191
192 if (ptable == NULL) {
193 jtag_fail("partition table doesn't exist");
194 return;
195 }
196
197 p = ptable_find(ptable, name);
198
199 if(p == 0) {
200 jtag_fail("partition not found");
201 return;
202 } else {
203
204#if 0
205 /* XXX reimpl */
206 if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){
207 jtag_fail("flash_read() failed");
208 return;
209 }
210#endif
211 dprintf(INFO, "page %d data:\n", p->start * 64);
212 hexdump(tmpbuf, 256);
213 dprintf(INFO, "page %d extra:\n", p->start * 64);
214 hexdump(tmpbuf, 16);
215 jtag_okay("done");
Chandan Uddaraju56228922009-12-11 21:48:48 -0800216 enter_critical_section();
217 platform_uninit_timer();
218 arch_disable_cache(UCACHE);
219 arch_disable_mmu();
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800220 }
221}
222
David Ng6e1711f2010-01-19 15:27:00 -0800223void handle_query_load_address(unsigned addr)
224{
225 unsigned *return_addr = (unsigned *)addr;
226
227 if (return_addr)
228 *return_addr = set_load_address(addr);
229
230 jtag_okay("done");
231}
232
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800233void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2)
234{
235 if(startswith(cmd,"flash:")){
236 handle_flash(cmd + 6, a0, a1);
237 return;
238 }
239
240 if(startswith(cmd,"dump:")){
241 handle_dump(cmd + 5, a0);
242 return;
243 }
244
David Ng6e1711f2010-01-19 15:27:00 -0800245 if(startswith(cmd,"loadaddr:")){
246 handle_query_load_address(a0);
247 return;
248 }
249
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800250 jtag_fail("unknown command");
251}
252
Chandan Uddarajubbec2b02009-12-16 13:27:55 -0800253void nandwrite_init(void)
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800254{
255 page_size = flash_page_size();
256 page_mask = page_size - 1;
257 jtag_cmd_loop(handle_command);
258}
259
Ajay Dudani168f6cb2009-12-07 19:04:02 -0800260