Index: u-boot-1.1.4/common/Makefile =================================================================== --- u-boot-1.1.4.orig/common/Makefile +++ u-boot-1.1.4/common/Makefile @@ -29,7 +29,7 @@ AOBJS = COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \ cmd_ace.o cmd_autoscript.o \ - cmd_bdinfo.o cmd_bedbug.o cmd_bmp.o cmd_boot.o cmd_bootm.o \ + cmd_bdinfo.o cmd_bedbug.o cmd_bmp.o cmd_boot.o cmd_bootm.o cmd_bootss.o \ cmd_cache.o cmd_console.o \ cmd_date.o cmd_dcr.o cmd_diag.o cmd_display.o cmd_doc.o cmd_dtt.o \ cmd_eeprom.o cmd_elf.o cmd_ext2.o \ Index: u-boot-1.1.4/common/cmd_bootss.c =================================================================== --- /dev/null +++ u-boot-1.1.4/common/cmd_bootss.c @@ -0,0 +1,203 @@ +/* + * (C) Copyright 2006 + * Sony Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * snapshot boot support + */ +#include +#include +#include + +#define CFG_CMD_BOOTSS +#if defined(CONFIG_COMMANDS) + +/* + * The swsusp image layout is as below, given the address of image, + * and +(number) is offset from that address (base address): + * (this image is as of linux-2.6.11, and might change in future) + * |<--- 1 page (0x1000 byte) --->| + * + * +0 |--------------------------------|: swsusp_header + * |<----- reserved ------>| + * |--|: swp_entry_t swsusp_info + * |--|: char orig_sig[10] + * |--|: char sig[10] + * + * swp_entry_t points to swsusp_info. Address is swp entry * page + base. + * + * |--------------------------------|: swsusp_info + * |----|: struct new_utsname (390 (0x186) byte) + * |-|: u32 version code + * |-|: ulong num_physpages + * |-|: int cpus + * |-|: ulong image_pages + * |-|: ulong pagedir_pages + * |-|: suspend_pagedir_t * + * |----|: swp_entry_t pagedir[768] + * +*/ + +/* linux kernel specific definitions for snapshot boot */ +#include "cmd_bootss.h" +static struct swsusp_header *swsusp_header; +static struct swsusp_info *swsusp_info; + +int do_bootss(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +static void show_args(cmd_tbl_t *cmdtp, int argc, char *argv[]) +{ + int i; + printf("\tcmd: %s, argc: %d, at: 0x%08p\n", + cmdtp->name, argc, do_bootss); + for (i = 0; i < argc; i++) + printf("argv[%d]: %s\n", i, argv[i]); + printf("\tsizeof(swsusp_header): %d (0x%08lx)\n", + sizeof(struct swsusp_header), + sizeof(struct swsusp_header)); + printf("\tsizeof(swsusp_info): %d (0x%08lx)\n", + sizeof(struct swsusp_info), + sizeof(struct swsusp_info)); +} + +static inline int check_sig(void) +{ + return !memcmp(SWSUSP_SIG, swsusp_header->sig, 10); +} + +extern unsigned long _start; +extern unsigned long _end; +static inline int __check_area(unsigned long *dst, unsigned long *src) +{ + if ((ulong*)_start <=dst && dst <= (ulong*)_end) + { + printf("overlap!\n"); + return 1; + } + if (dst < (ulong*)CFG_MEMTEST_START || (ulong*)CFG_MEMTEST_END < dst) + { + printf("not in mem space!\n"); + return 1; + } + return 0; +} + +static inline void __copy_page(unsigned long *dst, unsigned long *src) +{ +/* + * FIXME: This needs optimization for faster startup. + * If there is burst transfer mechanizm, it should be used. + */ +#define WHILE_COPY_WORD + +#ifdef USE_ASM_LDMIA_STMIA +/* + * This is ARM specific, thinking of using load/store multiple + */ +#endif +#ifdef USE_CFI_FLASH_READ_PAGE +#error "not yet implemented" +#endif +#ifdef USE_BCOPY + bcopy(src, dst, PAGE_SIZE); +#endif +#ifdef USE_MEMCPY + memcpy(dst, src, PAGE_SIZE); +#endif +#ifdef WHILE_COPY_WORD + unsigned long count = PAGE_SIZE; + while (count--) { + *dst++ = *src++; + } +#endif +} + +static inline int copy_image(void) +{ + int i, pages; + unsigned long *src, *dst; + unsigned long base = (unsigned long)swsusp_header; + suspend_pagedir_t *pagedir; + + swsusp_info = (struct swsusp_info *) + (base + (swsusp_header->swsusp_info.val * PAGE_SIZE)); + pagedir = (suspend_pagedir_t *) + (base + (swsusp_info->pagedir[0].val * PAGE_SIZE)); + pages = swsusp_info->image_pages; + printf("\tpages to copy: %d (0x%08lx)\n", pages, pages); + for (i=0; iorig_address - PAGE_OFFSET + PHYS_OFFSET; + src = base + (pagedir->swap_address.val * PAGE_SIZE); + + if (__check_area(dst, src)) + { + printf("check dst address %p failed.\n" + "\tdst:%p, src: %p\n", dst, dst, src); + return 1; + } + __copy_page(dst, src); + } + printf("bootss: copy image done.\n"); + return 0; +} + +extern void ss_pre_setup_peripherals(void); +extern void ss_post_setup_peripherals(void); +extern void ss_jump_to_resume(unsigned long); +int do_bootss(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unsigned long start; + show_args(cmdtp, argc, argv); + + if (argc < 2) + { + printf("missing argument: \n" + "usage: bootss \n"); + return 1; + } + + swsusp_header = + (struct swsusp_header *) simple_strtoul(argv[1], NULL, 16); + start = *(unsigned long *)((&swsusp_header->swsusp_info) - 1); + if (!check_sig()) + { + printf("specified address 0x%08p is not valid image header\n", + swsusp_header); + return 1; + } + ss_pre_setup_peripherals(); + if (copy_image()) + return 1; + ss_post_setup_peripherals(); + ss_jump_to_resume(start); + + return 0; +} + +U_BOOT_CMD( + bootss, CFG_MAXARGS, 1, do_bootss, + "bootss - boot application image from snapshot\n", + "snapshot image addr, image resume point addr\n" + " - boot using application snapshot image in swap, and \n" + "\tresume from previously suspended state.\n" + "\tCurrently supports linux system only." +); + +#endif /* CFG_CMD_BOOTSS */ Index: u-boot-1.1.4/common/cmd_bootss.h =================================================================== --- /dev/null +++ u-boot-1.1.4/common/cmd_bootss.h @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2006 + * Sony Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _CMD_BOOTSS_H_ +#define _CMD_BOOTSS_H_ + +/* These are same definition as in linux 2.6.11 kernel. */ +#define SWSUSP_SIG "S1SUSPEND" +#define PAGE_SIZE 4096 +#define PAGE_OFFSET (0xc0000000UL) +#define PHYS_OFFSET (0x10000000UL) + +typedef struct { + unsigned long val; +} swp_entry_t; + +struct swsusp_header { + char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; + swp_entry_t swsusp_info; + char orig_sig[10]; + char sig[10]; +}; + +struct new_utsname { + char sysname[65]; + char nodename[65]; + char release[65]; + char version[65]; + char machine[65]; + char domainname[65]; +}; + +/* page backup entry */ +typedef struct pbe { + unsigned long address; /* address of the copy */ + unsigned long orig_address; /* original address of page */ + swp_entry_t swap_address; + swp_entry_t dummy; /* we need scratch space at + * end of page (see link, diskpage) + */ +} suspend_pagedir_t; + +struct swsusp_info { + struct new_utsname uts; + u32 version_code; + unsigned long num_physpages; + int cpus; + unsigned long image_pages; + unsigned long pagedir_pages; + suspend_pagedir_t * suspend_pagedir; + swp_entry_t pagedir[768]; +}; + +#endif /* _CMD_BOOTSS_H_ */