/* * Copyright (c) 2008 Carsten Schlote * See file CREDITS for list of people who contributed to this project. * * This file is part of barebox. * * barebox 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 3 of the License, or * (at your option) any later version. * * barebox 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 barebox. If not, see . */ /** @file * @brief Linux boot preparation code. * * This file is responsible to start a linux kernel on * Coldfire targets. * * @note Only Colilo mode supported yet. */ #include #include #include #include #include #include #include #include #include #include #include #include static int m68k_architecture = MACH_TYPE_GENERIC; /* * Setup M68k/Coldfire bootrecord info */ #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ defined (CONFIG_CMDLINE_TAG) || \ defined (CONFIG_INITRD_TAG) static void setup_boot_record(char* start_boot_rec, const char* command_line) { struct bi_record* record; *start_boot_rec++ = 'C'; *start_boot_rec++ = 'o'; *start_boot_rec++ = 'L'; *start_boot_rec++ = 'i'; *start_boot_rec++ = 'L'; *start_boot_rec++ = 'o'; record = (struct bi_record*) start_boot_rec; /* specify memory layout */ #ifdef CONFIG_SETUP_MEMORY_TAGS record->tag = BI_MEMCHUNK; record->data[0] = 0; record->data[1] = 64 * 1024 * 1024; // TODO: to be changed for different boards record->size = sizeof (record->tag) + sizeof (record->size) + sizeof (record->data[0]) + sizeof (record->data[0]); record = (struct bi_record *) ((void *) record + record->size); #endif /* add a kernel command line */ #ifdef CONFIG_CMDLINE_TAG record->tag = BI_COMMAND_LINE; strcpy ((char *) &record->data, command_line); record->size = sizeof (record->tag) + sizeof (record->size) + max (sizeof (record->data[0]), strlen (command_line)+1); record = (struct bi_record *) ((void *) record + record->size); #endif /* Add reference to initrd */ #ifdef CONFIG_INITRD_TAG #endif /* Mark end of tags */ record->tag = 0; record->data[0] = 0; record->data[1] = 0; record->size = sizeof(record->tag) + sizeof (record->size) + sizeof (record->data[0]) + sizeof (record->data[0]); } #else #define setup_boot_record(start_boot_rec,command_line) while (0) { } #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ static int do_bootm_linux(struct image_data *data) { image_header_t *os_header = &data->os->header; void (*theKernel)(int zero, int arch, uint params); const char *commandline = getenv ("bootargs"); uint32_t loadaddr,loadsize; if (image_check_type(os_header, IH_TYPE_MULTI)) { printf("Multifile images not handled at the moment\n"); return -1; } printf("commandline: %s\n", commandline); theKernel = (void (*)(int,int,uint))image_get_ep(os_header); debug ("## Transferring control to Linux (at address %08lx) ...\n", (ulong) theKernel); loadaddr = (uint32_t)image_get_load(os_header); loadsize = (uint32_t)image_get_size(os_header); setup_boot_record( (char*)(loadaddr+loadsize),(char*)commandline); if (relocate_image(data->os, (void *)loadaddr)) return -1; /* we assume that the kernel is in place */ printf ("\nStarting kernel image at 0x%08x size 0x%08x eentry 0x%08x\n\n", loadaddr, loadsize, (ulong) theKernel); /* Bring board into inactive post-reset state again */ cleanup_before_linux (); /* Jump to kernel entry point */ theKernel (0, m68k_architecture, 0xdeadbeaf); enable_interrupts(); printf("Error: Loaded kernel returned. Probably it couldn't\n" "find it's bootrecord.\n"); return -1; } /* * Register handler for m68k Kernel Images */ static int image_handle_cmdline_parse(struct image_data *data, int opt, char *optarg) { switch (opt) { case 'a': m68k_architecture = simple_strtoul(optarg, NULL, 0); return 0; default: return 1; } } static struct image_handler handler = { .cmdline_options = "a:", .cmdline_parse = image_handle_cmdline_parse, .help_string = " -a use architecture number ", .bootm = do_bootm_linux, .image_type = IH_OS_LINUX, }; static int m68klinux_register_image_handler(void) { return register_image_handler(&handler); } late_initcall(m68klinux_register_image_handler);