This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
load and boot support of linux bzImage for i386
- From: Masato Taruishi <taru at debian dot org>
- To: ecos-patches at sources dot redhat dot com
- Date: Fri, 19 Jul 2002 13:33:08 +0900
- Subject: load and boot support of linux bzImage for i386
Although it has a few limitations such as handling initrd, it allows
redboot-i386 to load and boot linux bzImage.
Index: hal/i386/arch/current/cdl/hal_i386.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/i386/arch/current/cdl/hal_i386.cdl,v
retrieving revision 1.10
diff -u -p -r1.10 hal_i386.cdl
--- hal/i386/arch/current/cdl/hal_i386.cdl 23 May 2002 23:03:02 -0000 1.10
+++ hal/i386/arch/current/cdl/hal_i386.cdl 19 Jul 2002 04:22:48 -0000
@@ -162,5 +162,41 @@ cdl_package CYGPKG_HAL_I386 {
cdl_interface CYGINT_HAL_I386_MEM_REAL_REGION_TOP {
display "Implementations of hal_i386_mem_real_region_top()"
}
+
+ cdl_component CYGPKG_REDBOOT_I386_OPTIONS {
+ display "Redboot for i386 options"
+ flavor none
+ no_define
+ parent CYGPKG_REDBOOT
+ active_if CYGPKG_REDBOOT
+ description "
+ This option lists the target's requirements for a valid Redboot
+ configuration."
+
+ cdl_component CYGSEM_REDBOOT_I386_LINUX_BOOT {
+ display "Support booting Linux via RedBoot"
+ flavor bool
+ default_value 1
+ description "
+ This option allows RedBoot to support booting of a Linux kernel."
+ compile -library=libextras.a redboot_linux_exec.c
+
+ cdl_component CYGOPT_REDBOOT_I386_BZIMAGE {
+ display "Support loading linux bzImage via RedBoot"
+ flavor bool
+ default_value 1
+ description "
+ This option allow RedBoot to support loading of a
+ linux bzImage."
+ }
+
+ cdl_option CYGDAT_REDBOOT_I386_LINUX_BOOT_COMMAND_LINE {
+ display "Default COMMAND_LINE"
+ flavor data
+ default_value { "" }
+ }
+ }
+ }
+
}
Index: hal/i386/pc/current/include/platform.inc
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/i386/pc/current/include/platform.inc,v
retrieving revision 1.7
diff -u -p -r1.7 platform.inc
--- hal/i386/pc/current/include/platform.inc 23 May 2002 23:03:12 -0000 1.7
+++ hal/i386/pc/current/include/platform.inc 19 Jul 2002 04:22:48 -0000
@@ -77,6 +77,10 @@ hal_cpu_init_start:
# Disable interrupt handling.
cli
+#ifdef CYGSEM_REDBOOT_I386_LINUX_BOOT
+#include <cyg/hal/linux.inc>
+#endif
+
# Make a GDT pointer in location 0 and load new GDTR
movw $(gdtEnd - gdtStart),%ax
movw %ax,0
@@ -137,6 +141,24 @@ gdtStart:
.byte 0x93
.byte 0xC7
.byte 0x00
+
+#ifdef CYGSEM_REDBOOT_I386_LINUX_BOOT
+ /* Selector 0x28 == code. real-mode boundary D-bit = 0*/
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x9B
+ .byte 0x00
+ .byte 0x00
+
+ /* Selector 0x30 == data. real-mode boundary D-bit = 0*/
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x93
+ .byte 0x00
+ .byte 0x00
+#endif
.align 4, 0xFF
gdtEnd:
Index: hal/i386/pcmb/current/include/pcmb.inc
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/i386/pcmb/current/include/pcmb.inc,v
retrieving revision 1.3
diff -u -p -r1.3 pcmb.inc
--- hal/i386/pcmb/current/include/pcmb.inc 23 May 2002 23:03:15 -0000 1.3
+++ hal/i386/pcmb/current/include/pcmb.inc 19 Jul 2002 04:22:49 -0000
@@ -228,6 +228,10 @@ _endload:
/* Now we're all loaded up in memory. */
+#ifdef CYGSEM_REDBOOT_I386_LINUX_BOOT
+#include <cyg/hal/linux.inc>
+#endif
+
/* Optionally switch to a high-res video before entering */
/* protected mode. The mode is controlled by an option in */
/* the RedBoot configuration, which is not readily visible */
@@ -357,6 +361,24 @@ gdtStart:
.byte 0x93
.byte 0xC7
.byte 0x00
+
+#ifdef CYGSEM_REDBOOT_I386_LINUX_BOOT
+ /* Selector 0x28 == code. real-mode boundary D-bit = 0*/
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x9B
+ .byte 0x00
+ .byte 0x00
+
+ /* Selector 0x30 == data. real-mode boundary D-bit = 0*/
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x93
+ .byte 0x00
+ .byte 0x00
+#endif
.align 4, 0xFF
gdtEnd:
Index: redboot/current/include/redboot.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/include/redboot.h,v
retrieving revision 1.25
diff -u -p -r1.25 redboot.h
--- redboot/current/include/redboot.h 18 Jul 2002 20:05:22 -0000 1.25
+++ redboot/current/include/redboot.h 19 Jul 2002 04:22:52 -0000
@@ -89,7 +89,14 @@ EXTERN unsigned long workspace_size;
EXTERN unsigned long entry_address;
EXTERN unsigned long load_address;
EXTERN unsigned long load_address_end;
+#ifdef CYGOPT_REDBOOT_I386_BZIMAGE
+EXTERN unsigned int linux_type;
+#define LINUX_RAW_IMAGE 0
+#define LINUX_ZIMAGE 1
+#define LINUX_BZIMAGE 2
+
+#endif
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
EXTERN bool console_selected;
Index: redboot/current/src/load.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/load.c,v
retrieving revision 1.26
diff -u -p -r1.26 load.c
--- redboot/current/src/load.c 18 Jul 2002 20:05:23 -0000 1.26
+++ redboot/current/src/load.c 19 Jul 2002 04:22:52 -0000
@@ -93,7 +93,7 @@ CYG_HAL_TABLE_END( __RedBoot_LOAD_TAB_EN
extern struct load_io_entry __RedBoot_LOAD_TAB__[], __RedBoot_LOAD_TAB_END__;
// Buffers, data used by redboot_getc
-#define BUF_SIZE 256
+#define BUF_SIZE 1024
struct {
getc_io_funcs_t *io;
int (*fun)(char *, int len, int *err);
@@ -408,6 +408,78 @@ load_elf_image(getc_t getc, unsigned lon
#endif // CYGSEM_REDBOOT_ELF
}
+#ifdef CYGOPT_REDBOOT_I386_BZIMAGE
+
+#define LINUX_PARAM_UINT16(offset) ((cyg_uint16 *)(real_mode_kernel+offset))
+
+#define SUPPORTED_LINUX_VERSION 0x0202
+
+extern unsigned char **command_line;
+
+static unsigned long
+load_bzImage_image(int (*getc)(void))
+{
+ int res;
+ int i;
+
+ cyg_uint8 *real_mode_kernel = (cyg_uint8 *)0x90000;
+ cyg_uint8 *protect_mode_kernel = (cyg_uint8 *)0x100000;
+
+ cyg_uint8 *setup_sects = real_mode_kernel+0x1f1;
+ cyg_uint16 *root_flags = LINUX_PARAM_UINT16(0x1f2);
+ cyg_uint16 *vid_mode = LINUX_PARAM_UINT16(0x1fa);
+ cyg_uint16 *root_dev = LINUX_PARAM_UINT16(0x1fc);
+ cyg_uint16 *boot_flag = LINUX_PARAM_UINT16(0x1fe);
+
+ cyg_uint16 *version = LINUX_PARAM_UINT16(0x206);
+ cyg_uint16 *kernel_version = LINUX_PARAM_UINT16(0x20e);
+ cyg_uint8 *loadflags = real_mode_kernel+0x211;
+
+ cyg_uint8 *type_of_loader = real_mode_kernel+0x210;
+
+ cyg_uint32 *cmd_line_ptr = real_mode_kernel+0x228;
+
+ /* cyg_uint16 heap_end_ptr; FIXME: not supported yet */
+
+ for(i=0;i<0x230;i++) {
+ if((res = (*getc)()) >= 0) {
+ *(real_mode_kernel+i) = res;
+ } else {
+ diag_printf("error while reading bzImage header!\n");
+ return -1;
+ }
+ }
+
+ if (*setup_sects == 0) {
+ *setup_sects = 4;
+ }
+
+ if (*version < SUPPORTED_LINUX_VERSION) {
+ diag_printf("bzImage version %x not supported!\n", *version);
+ return 0;
+ }
+
+ *type_of_loader = 5;
+
+ *cmd_line_ptr = (cyg_uint32)command_line;
+
+ for(i=0x230; i<(*setup_sects+1)*512;i++)
+ *(real_mode_kernel+i) = (*getc)();
+
+ /* protect-mode kernel */
+ i = 0;
+ while((res = getc()) >= 0) {
+ *(protect_mode_kernel+i) = res;
+ i++;
+ }
+
+ diag_printf("Linux bzImage: %d bytes (setup %d bytes)\n", i, (*setup_sects)*512);
+
+ linux_type = LINUX_BZIMAGE;
+ return i;
+}
+#endif
+
//
// Scan a string of hex bytes and update the checksum
@@ -584,7 +656,11 @@ do_load(int argc, char *argv[])
#endif
unsigned long base = 0;
unsigned long end = 0;
+#ifdef CYGOPT_REDBOOT_I386_BZIMAGE
+ char type[0x206];
+#else
char type[4];
+#endif
char *filename = 0;
struct option_info opts[7];
connection_info_t info;
@@ -751,6 +827,11 @@ do_load(int argc, char *argv[])
} else if ((type[0] == 'S') &&
((type[1] >= '0') && (type[1] <= '9'))) {
end = load_srec_image(redboot_getc, base);
+#ifdef CYGOPT_REDBOOT_I386_BZIMAGE
+ } else if (strncmp(&type[0x202], "HdrS", 4) ==0) {
+ end = load_bzImage_image(redboot_getc);
+#endif
+
} else {
redboot_getc_terminate(true);
diag_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);
--- /dev/null Thu Jul 18 01:27:46 2002
+++ hal/i386/arch/current/include/linux.inc Fri Jul 19 12:24:22 2002
@@ -0,0 +1,104 @@
+#ifndef CYGONCE_HAL_LINUX_INC
+#define CYGONCE_HAL_LINUX_INC
+##=============================================================================
+##
+## linux.inc
+##
+## linux support
+##
+##=============================================================================
+#####COPYRIGHTBEGIN####
+#
+# -------------------------------------------
+# The contents of this file are subject to the Red Hat eCos Public License
+# Version 1.1 (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.redhat.com/
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+# License for the specific language governing rights and limitations under
+# the License.
+#
+# The Original Code is eCos - Embedded Configurable Operating System,
+# released September 30, 1998.
+#
+# The Initial Developer of the Original Code is Red Hat.
+# Portions created by Red Hat are
+# Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
+# All Rights Reserved.
+# -------------------------------------------
+#
+#####COPYRIGHTEND####
+##=============================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s): taruishi
+## Contributors:
+## Date: 2002-07-05
+## Purpose: linux boot support
+## Description: This file contains assembler macros needed to
+## boot linux from eCos.
+##
+##
+######DESCRIPTIONEND####
+##
+##=============================================================================
+
+ jmp linux_end
+
+.globl linux_gdt
+linux_gdt:
+ .word linux_gdtEnd - linux_gdtStart
+ .long linux_gdtStart
+
+ .align 4, 0xFF
+
+linux_gdtStart:
+ /* Selector 0x00 == invalid. */
+ .word 0x0000
+ .word 0x0000
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+
+ /* Selector 0x08 == invalid. */
+ .word 0x0000
+ .word 0x0000
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+ .byte 0x00
+
+ /* Selector 0x10 == code. */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x9A
+ .byte 0xCF
+ .byte 0x00
+
+ /* Selector 0x18 == data. */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .byte 0x92
+ .byte 0xCF
+ .byte 0x00
+
+ .align 4, 0xFF
+linux_gdtEnd:
+
+linux_idt:
+ .globl linux_idt
+ .word 0
+ .long 0
+
+real_mode_idt:
+ .globl real_mode_idt
+ .word 0x03FF
+ .long 0
+
+linux_end:
+#endif
\ No newline at end of file
--- /dev/null Thu Jul 18 01:27:46 2002
+++ hal/i386/arch/current/src/redboot_linux_exec.c Fri Jul 19 13:09:31 2002
@@ -0,0 +1,186 @@
+//==========================================================================
+//
+// redboot_linux_exec.c
+//
+// RedBoot exec command for Linux bzImage booting
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Gary Thomas
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): taruishi
+// Contributors:
+// Date: 2002-07-05
+// Purpose: RedBoot exec command for Linux bzImage booting
+//
+// TODO: handle initrd, initial cursor location etc.
+//
+//####DESCRIPTIONEND####
+//
+//===========================================================================
+
+#include <redboot.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_cache.h>
+#include <cyg/hal/hal_if.h>
+
+#define xstr(s) str(s)
+#define str(s...) #s
+
+static void do_exec(int argc, char *argv[]);
+RedBoot_cmd("exec",
+ "Execute linux",
+ "[-c \"kernel command line\"] [-w <timeout>]",
+ do_exec
+ );
+
+#define REAL_MODE_ADDR 0x90000
+#define COMMAND_LINE_ADDR 0x99000
+
+const unsigned char **command_line = (unsigned char **)COMMAND_LINE_ADDR;
+
+#define LINUX_PARAM_UINT16(offset) ((cyg_uint16 *)(real_mode_kernel+offset))
+
+void
+do_exec(int argc, char *argv[])
+{
+ bool cmd_line_set, wait_time_set;
+ unsigned char *cmd_line = xstr(CYGDAT_REDBOOT_I386_LINUX_BOOT_COMMAND_LINE);
+ char *cmdp;
+ int wait_time, res;
+ struct option_info opts[2];
+ int oldints;
+ char line[8];
+
+ cyg_uint8 *real_mode_kernel = (cyg_uint8 *)REAL_MODE_ADDR;
+ cyg_uint16 *vid_mode = LINUX_PARAM_UINT16(0x1fa);
+ cyg_uint16 vid_val = 0;
+ int vid_mul;
+
+ init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
+ (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
+ init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR,
+ (void **)&cmd_line, &cmd_line_set, "kernel command line");
+
+ if (!scan_opts(argc, argv, 1, opts, 2, NULL,
+ OPTION_ARG_TYPE_NUM, ""))
+ return;
+
+ /* vga= special argument handling */
+ cmdp = cmd_line;
+ while(*cmdp != '\0') {
+ if (!memcmp(cmdp, "vga=", 4)) {
+ cmdp += 4;
+ if(!memcmp(cmdp, "normal", 6)) {
+ vid_val = 0xffff;
+ } else if(!memcmp(cmdp, "ext", 3)) {
+ vid_val = 0xfffe;
+ } else if(!memcmp(cmdp, "ask", 3)) {
+ vid_val = 0xfffd;
+ } else {
+ if(!memcmp(cmdp, "0x", 2)) {
+ cmdp += 2;
+ vid_mul = 16;
+ } else if(*cmdp == '0') {
+ cmdp++;
+ vid_mul = 8;
+ } else {
+ vid_mul = 10;
+ }
+ while(*cmdp != '\0' && *cmdp != ' ') {
+ vid_val = vid_val * vid_mul;
+ vid_val += *cmdp - '0';
+ cmdp++;
+ }
+ }
+ *vid_mode = vid_val;
+ break;
+ }
+ cmdp++;
+ }
+
+ strcpy(command_line, cmd_line);
+
+ diag_printf("Now booting linux kernel:\n");
+ diag_printf(" Cmdline : %s\n", command_line);
+
+ if (wait_time_set) {
+ diag_printf("About to start execution - abort with ^C within %d se
+conds\n", wait_time);
+ res = _rb_gets(line, sizeof(line), wait_time*1000);
+ if (res == _GETS_CTRLC) {
+ return;
+ }
+ }
+
+ HAL_DISABLE_INTERRUPTS(oldints);
+
+ asm volatile(" lidt real_mode_idt\n"
+
+ /* set memory protect boundary to real-mode */
+
+ " ljmp $0x28, $1f\n"
+ "1:\n"
+ " movw $0x30, %ax\n"
+ " movw %ax, %ds\n"
+ " movw %ax, %es\n"
+ " movw %ax, %ss\n"
+ " movw %ax, %fs\n"
+ " movw %ax, %gs\n"
+
+ /* now swith to real-mode */
+
+ " movl %cr0, %eax\n"
+ " andl $0xfffffffe, %eax\n"
+ " movl %eax, %cr0\n"
+ " jmp tmpseg\n"
+ "tmpseg:\n"
+ " ljmp $0, $realseg\n"
+ "realseg:\n"
+ ".code16\n"
+ " xorw %ax, %ax\n"
+ " movw %ax, %ds\n"
+ " movw %ax, %es\n"
+ " movw %ax, %ss\n"
+ " movw %ax, %fs\n"
+ " movw %ax, %gs\n"
+
+ /* jump to linux setup segment */
+
+ " ljmp $0x9020, $0\n"
+ ".code32\n");
+
+}