217 lines
4.9 KiB
ArmAsm
217 lines
4.9 KiB
ArmAsm
/*
|
|
Copyright (C) 2000, Entity Cyber, Inc.
|
|
|
|
Authors: Gary Byers (gb@thinguin.org)
|
|
Marty Connor (mdc@thinguin.org)
|
|
|
|
This software may be used and distributed according to the terms
|
|
of the GNU Public License (GPL), incorporated herein by reference.
|
|
|
|
Description:
|
|
|
|
This is just a little bit of code and data that can get prepended
|
|
to a ROM image in order to allow bootloaders to load the result
|
|
as if it were a Linux kernel image.
|
|
|
|
A real Linux kernel image consists of a one-sector boot loader
|
|
(to load the image from a floppy disk), followed a few sectors
|
|
of setup code, followed by the kernel code itself. There's
|
|
a table in the first sector (starting at offset 497) that indicates
|
|
how many sectors of setup code follow the first sector and which
|
|
contains some other parameters that aren't interesting in this
|
|
case.
|
|
|
|
When a bootloader loads the sectors that comprise a kernel image,
|
|
it doesn't execute the code in the first sector (since that code
|
|
would try to load the image from a floppy disk.) The code in the
|
|
first sector below doesn't expect to get executed (and prints an
|
|
error message if it ever -is- executed.)
|
|
|
|
We don't require much in the way of setup code. Historically, the
|
|
Linux kernel required at least 4 sectors of setup code.
|
|
Therefore, at least 4 sectors must be present even though we don't
|
|
use them.
|
|
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL_ANY )
|
|
|
|
#define SETUPSECS 4 /* Minimal nr of setup-sectors */
|
|
#define PREFIXSIZE ((SETUPSECS+1)*512)
|
|
#define PREFIXPGH (PREFIXSIZE / 16 )
|
|
#define BOOTSEG 0x07C0 /* original address of boot-sector */
|
|
#define INITSEG 0x9000 /* we move boot here - out of the way */
|
|
#define SETUPSEG 0x9020 /* setup starts here */
|
|
#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */
|
|
|
|
.text
|
|
.code16
|
|
.arch i386
|
|
.org 0
|
|
.section ".prefix", "ax", @progbits
|
|
/*
|
|
This is a minimal boot sector. If anyone tries to execute it (e.g., if
|
|
a .lilo file is dd'ed to a floppy), print an error message.
|
|
*/
|
|
|
|
bootsector:
|
|
jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */
|
|
1:
|
|
movw $0x2000, %di /* 0x2000 is arbitrary value >= length
|
|
of bootsect + room for stack */
|
|
|
|
movw $BOOTSEG, %ax
|
|
movw %ax,%ds
|
|
movw %ax,%es
|
|
|
|
cli
|
|
movw %ax, %ss /* put stack at BOOTSEG:0x2000. */
|
|
movw %di,%sp
|
|
sti
|
|
|
|
movw $why_end-why, %cx
|
|
movw $why, %si
|
|
|
|
movw $0x0007, %bx /* page 0, attribute 7 (normal) */
|
|
movb $0x0e, %ah /* write char, tty mode */
|
|
prloop:
|
|
lodsb
|
|
int $0x10
|
|
loop prloop
|
|
freeze: jmp freeze
|
|
|
|
why: .ascii "This image cannot be loaded from a floppy disk.\r\n"
|
|
why_end:
|
|
|
|
|
|
/*
|
|
The following header is documented in the Linux source code at
|
|
Documentation/i386/boot.txt
|
|
*/
|
|
.org 497
|
|
setup_sects:
|
|
.byte SETUPSECS
|
|
root_flags:
|
|
.word 0
|
|
syssize:
|
|
.long -PREFIXPGH
|
|
|
|
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
|
.ascii "ADDL"
|
|
.long syssize
|
|
.long 16
|
|
.long 0
|
|
.previous
|
|
|
|
ram_size:
|
|
.word 0
|
|
vid_mode:
|
|
.word 0
|
|
root_dev:
|
|
.word 0
|
|
boot_flag:
|
|
.word 0xAA55
|
|
jump:
|
|
/* Manually specify a two-byte jmp instruction here rather
|
|
* than leaving it up to the assembler. */
|
|
.byte 0xeb
|
|
.byte setup_code - header
|
|
header:
|
|
.byte 'H', 'd', 'r', 'S'
|
|
version:
|
|
.word 0x0207 /* 2.07 */
|
|
realmode_swtch:
|
|
.long 0
|
|
start_sys:
|
|
.word 0
|
|
kernel_version:
|
|
.word 0
|
|
type_of_loader:
|
|
.byte 0
|
|
loadflags:
|
|
.byte 0
|
|
setup_move_size:
|
|
.word 0
|
|
code32_start:
|
|
.long 0
|
|
ramdisk_image:
|
|
.long 0
|
|
ramdisk_size:
|
|
.long 0
|
|
bootsect_kludge:
|
|
.long 0
|
|
heap_end_ptr:
|
|
.word 0
|
|
pad1:
|
|
.word 0
|
|
cmd_line_ptr:
|
|
.long 0
|
|
initrd_addr_max:
|
|
/* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
|
|
* been known to require this field. Set the value to 2 GB. This
|
|
* value is also used by the Linux kernel. */
|
|
.long 0x7fffffff
|
|
kernel_alignment:
|
|
.long 0
|
|
relocatable_kernel:
|
|
.byte 0
|
|
pad2:
|
|
.byte 0, 0, 0
|
|
cmdline_size:
|
|
.long 0
|
|
hardware_subarch:
|
|
.long 0
|
|
hardware_subarch_data:
|
|
.byte 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
/*
|
|
We don't need to do too much setup.
|
|
|
|
This code gets loaded at SETUPSEG:0. It wants to start
|
|
executing the image that's loaded at SYSSEG:0 and
|
|
whose entry point is SYSSEG:0.
|
|
*/
|
|
setup_code:
|
|
/* We expect to be contiguous in memory once loaded. The Linux image
|
|
* boot process requires that setup code is loaded separately from
|
|
* "non-real code". Since we don't need any information that's left
|
|
* in the prefix, it doesn't matter: we just have to ensure that
|
|
* %cs:0000 is where the start of the image *would* be.
|
|
*/
|
|
ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_ipxe
|
|
|
|
|
|
.org PREFIXSIZE
|
|
/*
|
|
We're now at the beginning of the kernel proper.
|
|
*/
|
|
run_ipxe:
|
|
/* Set up stack just below 0x7c00 */
|
|
xorw %ax, %ax
|
|
movw %ax, %ss
|
|
movw $0x7c00, %sp
|
|
|
|
/* Install iPXE */
|
|
call install
|
|
|
|
/* Set up real-mode stack */
|
|
movw %bx, %ss
|
|
movw $_estack16, %sp
|
|
|
|
/* Jump to .text16 segment */
|
|
pushw %ax
|
|
pushw $1f
|
|
lret
|
|
.section ".text16", "awx", @progbits
|
|
1:
|
|
pushl $main
|
|
pushw %cs
|
|
call prot_call
|
|
popl %ecx /* discard */
|
|
|
|
/* Uninstall iPXE */
|
|
call uninstall
|
|
|
|
/* Boot next device */
|
|
int $0x18
|