Files
moboot-for-veer/lib/bootlinux/bootlinux.c
T
2012-04-24 20:40:57 +08:00

207 lines
5.2 KiB
C

/*
* Copyright (c) 2011, James Sullins
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <kernel/thread.h>
#include <debug.h>
#include <lib/bootlinux.h>
#include <lib/uimage.h>
#include <lib/atags.h>
#define RAMDISK_ADDR 0x0A000000
char root_dev_ram[] = "/dev/ram0";
char root_dev_noram[] = "/dev/mmcblk0p14";
char tty_dev_fbcon[] = "tty1";
char tty_dev_nofbcon[] = "ttyS2,115200n8";
char *root_dev;
char *tty_dev;
extern unsigned *passed_atags;
void bootlinux_direct(void *kernel, unsigned machtype, unsigned *tags)
{
void (*entry)(unsigned,unsigned,unsigned*) = kernel;
enter_critical_section();
/* do any platform specific cleanup before kernel entry */
platform_uninit();
arch_disable_cache(UCACHE);
arch_disable_mmu();
entry(0, machtype, tags);
}
void bootlinux_atags(void *kernel, unsigned *tags,
const char *cmdline, unsigned machtype,
void *ramdisk, unsigned ramdisk_size)
{
unsigned *ptr = tags;
int cmdline_len = 0;
int have_cmdline = 0;
/* CORE */
*ptr++ = 5;
*ptr++ = 0x54410001;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
if (ramdisk_size) {
*ptr++ = 4;
*ptr++ = 0x54420005;
*ptr++ = (unsigned)ramdisk;
*ptr++ = ramdisk_size;
}
ptr = target_atag_mem(ptr);
*ptr++ = 3;
*ptr++ = 0x54410007;
*ptr++ = 0;
if (cmdline && cmdline[0]) {
cmdline_len = strlen(cmdline);
have_cmdline = 1;
}
if (cmdline_len > 0) {
const char *src;
char *dst;
unsigned n;
/* include terminating 0 and round up to a word multiple */
n = (cmdline_len + 4) & (~3);
*ptr++ = (n / 4) + 2;
*ptr++ = 0x54410009;
dst = (char *)ptr;
if (have_cmdline) {
src = cmdline;
while ((*dst++ = *src++));
}
ptr += (n / 4);
}
/* END */
*ptr++ = 0;
*ptr++ = 0;
bootlinux_direct(kernel, machtype, (unsigned *)tags);
}
unsigned bootlinux_uimage_mem(void *data, unsigned len, void (*callback)(),
unsigned flags)
{
unsigned kernel_addr, ramdisk_addr;
unsigned kernel_size, ramdisk_size;
unsigned kernel_load, kernel_ep;
char cmdline_buff[1024];
char *cmdline = cmdline_buff;
char *nduid;
unsigned rc;
printf("Checking uImage... ");
if (uimage_check(data, len)) {
return 1;
} else {
printf("OK\n");
}
printf("Parsing uImage... ");
if (uimage_parse((struct image_header *)data,
&kernel_load, &kernel_ep, &kernel_size,
&kernel_addr, &ramdisk_addr, &ramdisk_size)) {
return 1;
} else {
printf("OK\n");
}
if (!kernel_size) {
printf("No kernel!\n");
return 1;
}
memmove(kernel_load, kernel_addr, kernel_size);
if (ramdisk_size) {
memmove(RAMDISK_ADDR, ramdisk_addr, ramdisk_size);
root_dev = root_dev_ram;
} else {
root_dev = root_dev_noram;
}
printf("\nkernel @ 0x%08x (%u bytes)\n", kernel_load, kernel_size);
if (ramdisk_size) {
printf("ramdisk @ 0x%08x (%u bytes)\n", RAMDISK_ADDR, ramdisk_size);
}
if (flags & BOOTLINUX_VERBOSE) {
sprintf(cmdline
, "root=%s rootwait rw logo.nologo console=tty1 %s%s%s%s%s%s"
, root_dev
, atags_get_cmdline_arg(passed_atags, "fb")
, atags_get_cmdline_arg(passed_atags, "nduid")
, atags_get_cmdline_arg(passed_atags, "klog")
, atags_get_cmdline_arg(passed_atags, "klog_len")
, atags_get_cmdline_arg(passed_atags, "boardtype")
, atags_get_cmdline_arg(passed_atags, "lastboot")
);
} else {
sprintf(cmdline
,"root=%s rootwait ro fbcon=disable console=ttyS2,115200n8 %s%s%s%s%s lcd_enable_vsync %s"
, root_dev
, atags_get_cmdline_arg(passed_atags, "fb")
, atags_get_cmdline_arg(passed_atags, "nduid")
, atags_get_cmdline_arg(passed_atags, "klog")
, atags_get_cmdline_arg(passed_atags, "klog_len")
, atags_get_cmdline_arg(passed_atags, "boardtype")
, atags_get_cmdline_arg(passed_atags, "lastboot")
);
}
printf("cmdline='%s'\n", cmdline);
printf("\nBooting...\n");
if (callback) callback();
#if 1
bootlinux_atags(kernel_ep, (void *)0x00200100,
cmdline, MACH_TYPE, RAMDISK_ADDR, ramdisk_size);
#else
bootlinux_atags(kernel_ep, data, cmdline, MACH_TYPE,
RAMDISK_ADDR, ramdisk_size);
#endif
}