2 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
3 * Sanghee Kim <sh0130.kim@samsung.com>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 #include <asm/errno.h>
27 #include <mobile/header.h>
28 #include <mobile/pit.h>
29 #include <mobile/fota.h>
30 #include <mobile/secure.h>
34 #ifndef CONFIG_CMD_PIT
35 #error "mobile misc need to define the CONFIG_CMD_PIT"
38 #ifndef CONFIG_SECURE_BOOTING
39 #define SECURE_KEY_SIZE 0
48 extern struct pitpart_data pitparts[];
50 #ifdef CONFIG_CMD_ONENAND
51 extern int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc,
53 static int nand_cmd(int ops, u32 addr, u32 ofs, u32 len)
56 char cmd[8], arg1[12], arg2[12], arg3[12];
57 char *const argv[] = { "onenand", cmd, arg1, arg2, arg3 };
60 sprintf(arg1, "%x", addr);
61 sprintf(arg2, "%x", ofs);
62 sprintf(arg3, "%x", len);
66 sprintf(cmd, "erase");
74 sprintf(cmd, "write");
78 printf("Error: wrong cmd on OneNAND\n");
82 ret = do_onenand(NULL, 0, argc, argv);
84 printf("Error: NAND Command\n");
90 #ifdef CONFIG_GENERIC_MMC
93 static struct mmc *mmc;
95 static int mmc_cmd(int ops, u64 start, u64 cnt, void *addr)
98 int dev_num = CONFIG_MMC_DEFAULT_DEV;
100 mmc = find_mmc_device(dev_num);
102 printf("error: mmc isn't exist\n");
106 start /= mmc->read_bl_len;
107 cnt /= mmc->read_bl_len;
109 /*printf("mmc %s 0x%llx 0x%llx\n", ops ? "write" : "read", start, cnt); */
113 mmc->block_dev.block_write(dev_num, (u32) start, (u32) cnt,
117 mmc->block_dev.block_read(dev_num, (u32) start, (u32) cnt,
129 int set_valid_flag(int index, u32 addr, int valid)
132 struct boot_header *bh;
135 printf("flag %s on %s\n", valid ? "set" : "clear",
136 pitparts[index].name);
138 switch (pitparts[index].dev_type) {
139 case PIT_DEVTYPE_ONENAND:
140 bh = (struct boot_header *)addr;
141 if (bh->magic == HDR_BOOT_MAGIC)
143 else if (bh->magic == HDR_KERNEL_MAGIC)
148 case PIT_DEVTYPE_MMC:
149 case PIT_DEVTYPE_FILE:
150 if (!strncmp(pitparts[index].name, PARTS_BOOTLOADER, 6)) {
151 bh = (struct boot_header *)
152 (addr + (u32) pitparts[index].size - HDR_SIZE);
153 } else if (!strncmp(pitparts[index].name, PARTS_KERNEL, 6)) {
154 hdr = (image_header_t *)addr;
155 bh = (struct boot_header *)(addr +
156 ALIGN(image_get_data_size(hdr) + image_get_header_size(), FS_BLOCK_SIZE) +
160 if (bh->magic == HDR_BOOT_MAGIC)
162 else if (bh->magic == HDR_KERNEL_MAGIC)
172 printf("error: can't found magic code(0x%08x) at 0x%x for %s",
173 bh->magic, (u32) bh, pitparts[index].name);
178 static int check_valid_flag(int index, char *opt)
184 u32 ramaddr = CONFIG_SYS_DOWN_ADDR;
185 u8 buf[FS_BLOCK_SIZE];
186 struct boot_header *bh = (struct boot_header *)buf;
187 image_header_t *hdr = (image_header_t *)buf;
189 /* caution! support only mmc */
190 if (pitparts[index].dev_type == PIT_DEVTYPE_MMC) {
191 offset = pitparts[index].offset;
193 if (!strncmp(pitparts[index].name, PARTS_BOOTLOADER, 6))
194 length = ((u32) pitparts[index].size) - FS_BLOCK_SIZE;
195 else if (!strncmp(pitparts[index].name, PARTS_KERNEL, 6)) {
196 mmc_cmd(OPS_READ, offset , sizeof(image_header_t),
198 length = ALIGN(image_get_data_size(hdr) +
199 image_get_header_size(), FS_BLOCK_SIZE);
200 length = ALIGN(length + SECURE_KEY_SIZE, FS_BLOCK_SIZE);
203 mmc_cmd(OPS_READ, offset + length, FS_BLOCK_SIZE, (void *)buf);
205 if ((bh->magic == HDR_BOOT_MAGIC) && bh->valid) {
206 debug("found header: ");
207 debug("board (%s) version (%s) date (%s)\n",
208 bh->boardname, bh->version, bh->date);
213 if (pitparts[index].dev_type == PIT_DEVTYPE_FILE) {
214 sprintf(cmd, "ext4load mmc %d:%s %x /%s%s",
215 CONFIG_MMC_DEFAULT_DEV, getenv("mmcbootpart"),
216 ramaddr, pitparts[index].file_name, opt);
218 ret = run_command(cmd, 0);
220 printf("cmd: %s\n", cmd);
224 length = (u32)simple_strtoul(getenv("filesize"), NULL, 16);
225 bh = (struct boot_header *)(ramaddr + length - FS_BLOCK_SIZE);
227 if ((bh->magic == HDR_KERNEL_MAGIC) && bh->valid) {
228 debug("found header: ");
229 debug("board (%s) version (%s) date (%s)\n",
230 bh->boardname, bh->version, bh->date);
235 printf("Error: can't found bootable partition for %s%s\n",
236 pitparts[index].file_name, opt);
241 int backup_bootable_part(void)
244 int index, index_bak;
247 u32 ramaddr = CONFIG_SYS_DOWN_ADDR;
248 u8 buf[FS_BLOCK_SIZE];
249 image_header_t *hdr = (image_header_t *)buf;
251 printf("\nbackup start\n");
254 index = get_pitpart_id(PARTS_BOOTLOADER "-mmc");
255 index_bak = get_pitpart_id(PARTS_BOOTLOADER "-mmc-bak");
256 if (!check_valid_flag(index, "")) {
257 printf("bootloader backup from 1st to 2nd\n");
259 pitparts[index].offset, pitparts[index].size,
263 pitparts[index_bak].offset, pitparts[index_bak].size,
266 /* clear the valid flag for origin */
267 set_valid_flag(index, ramaddr, 0);
269 pitparts[index].offset, pitparts[index].size,
271 } else if (!check_valid_flag(index_bak, "-bak")) {
272 printf("bootloader restore from 2nd to 1st\n");
274 pitparts[index_bak].offset, pitparts[index_bak].size,
277 /* clear the valid flag for origin */
278 set_valid_flag(index, ramaddr, 0);
280 pitparts[index].offset, pitparts[index].size,
283 printf("bootloader fail..\n");
287 index = get_pitpart_id(PARTS_KERNEL);
288 if (!check_valid_flag(index, "")) {
289 printf("kernel backup from 1st to 2nd\n");
293 length = (u32)simple_strtoul(getenv("filesize"), NULL, 16);
295 sprintf(cmd, "ext4write mmc %d:%s /%s-bak 0x%x %d",
296 CONFIG_MMC_DEFAULT_DEV, getenv("mmcbootpart"),
297 pitparts[index].file_name, ramaddr, length);
299 ret = run_command(cmd, 0);
301 printf("cmd: %s\n", cmd);
305 /* clear the valid flag for origin */
306 set_valid_flag(index, ramaddr, 0);
307 sprintf(cmd, "ext4write mmc %d:%s /%s 0x%x %d",
308 CONFIG_MMC_DEFAULT_DEV, getenv("mmcbootpart"),
309 pitparts[index].file_name, ramaddr, length);
311 ret = run_command(cmd, 0);
313 printf("cmd: %s\n", cmd);
316 } else if (!check_valid_flag(index, "-bak")) {
317 printf("kernel restore from 2nd to 1st\n");
321 length = (u32)simple_strtoul(getenv("filesize"), NULL, 16);
323 /* clear the valid flag for origin */
324 set_valid_flag(index, ramaddr, 0);
325 sprintf(cmd, "fatwrite mmc %d:%s 0x%x %s 0x%x",
326 CONFIG_MMC_DEFAULT_DEV, getenv("mmcbootpart"), ramaddr,
327 pitparts[index].file_name, length);
329 ret = run_command(cmd, 0);
331 printf("cmd: %s\n", cmd);
335 printf("kernel fail..\n");
338 printf("\nbackup done\n");
342 int check_kernel_part(void)
344 int index = get_pitpart_id(PARTS_KERNEL);
347 if (!check_valid_flag(index, "")) {
349 } else if (!check_valid_flag(index, "-bak")) {
350 sprintf(buf, "%s%s", pitparts[index].file_name, "-bak");
351 setenv("kernelname", buf);
353 printf("Can't found bootable kernel\n");
354 /* XXX: this will be enabled on May 2011 */
355 /* setenv("loaduimage", NULL);