aboutsummaryrefslogtreecommitdiff
path: root/util/mkelfImage/linux-i386/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'util/mkelfImage/linux-i386/head.S')
-rw-r--r--util/mkelfImage/linux-i386/head.S581
1 files changed, 0 insertions, 581 deletions
diff --git a/util/mkelfImage/linux-i386/head.S b/util/mkelfImage/linux-i386/head.S
deleted file mode 100644
index 9c52896e0c..0000000000
--- a/util/mkelfImage/linux-i386/head.S
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * exec_kernel/user_space/head.S
- *
- * Copyright (C) 2000, 2002, 2003 Eric Biederman
- *
- * Parts of this code were take from the linux startup
- * code of linux-2.4.0-test9
- *
- * Other parts were taken from etherboot-5.0.5
- */
-
-#define ASSEMBLY 1
-
-#define RELOC 0x10000
-#define PROT_CODE_SEG 0x10
-#define PROT_DATA_SEG 0x18
-#define REAL_CODE_SEG 0x08
-#define REAL_DATA_SEG 0x20
-
- .equ CR0_PE,1
-
-.text
-.code32
-
-
-#include "convert.h"
-
- .globl startup_32
-startup_32:
- cld
- cli
-
- # Save the arguments safely out of the way
- movl %eax, boot_type
- movl %ebx, boot_data
- cmp $0,%esp
- jz 1f
- movl 4(%esp), %eax
- movl %eax, boot_param
-1:
-
- movl stack_start, %esp
-
- # Clear eflags
- pushl $0
- popfl
-
- # Clear BSS
- xorl %eax,%eax
- movl $ _edata,%edi
- movl $ _end,%ecx
- subl %edi,%ecx
- cld
- rep
- stosb
-
- # Move the gdt where Linux will not smash it during decompression
- movl $gdt, %esi
- movl $GDTLOC, %edi
- movl $(gdt_end - gdt), %ecx
- rep movsb
-
- # Linux makes stupid assumptions about the segments
- # that are already setup, so setup a new gdt & ldt
- # and then reload the segment registers.
-
- lgdt gdt_48
- lidt idt_48
-
- # Load the data segment registers
- movl $ PROT_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %fs
- movl %eax, %gs
- movl %eax, %ss
-
- pushl $image_params # image build time parameters as forth arg
- pushl boot_param # boot_param pointer as third arg
- pushl boot_data # boot data pointer as second arg
- pushl boot_type # boot data type as first argument
- call convert_params
-
- movl %eax, %esi # put the real mode pointer in a safe place
- addl $16, %esp # pop the arguments
-
-
- # Setup the registers before jumping to linux
-
-
- # clear eflags
- pushl $0
- popfl
-
- # Flag to indicate we are the bootstrap processor
- xorl %ebx, %ebx
-
- movl switch_64, %eax
- cmp $1, %eax
- jz switch_to_64
-
- # Clear the unspecified registers for good measure
- xorl %eax, %eax
- xorl %ecx, %ecx
- xorl %edx, %edx
- xorl %edi, %edi
- xorl %ebp, %ebp
-
- # do not clear esp, we still need to use lret later
-
- pushl $PROT_CODE_SEG
- movl entry, %eax
- pushl %eax
-
- lret
-
-switch_to_64:
-
- /* We need to switch to 64bit before use startup_64 entry go to kernel */
- /*
- * Prepare for entering 64 bit mode
- */
- # Move the gdt64 where Linux will not smash it during decompression
- movl %esi, %eax # save the real mode pointer
- movl $gdt64, %esi
- movl $GDT64LOC, %edi
- movl $(gdt64_end - gdt64), %ecx
- rep movsb
- movl %eax, %esi
-
- /* Load new GDT with the 64bit segments using 32bit descriptor */
- lgdt gdt64
-
- /* Enable PAE mode */
- xorl %eax, %eax
- btsl $5, %eax
- movl %eax, %cr4
-
- /*
- * Build early 4G boot pagetable
- */
- /* Initialize Page tables to 0*/
- movl $PGTLOC, %edi
- xorl %eax, %eax
- movl $((4096*6)/4), %ecx
- rep stosl
-
- /* Build Level 4 */
- movl $(PGTLOC + 0), %edi
- leal 0x1007 (%edi), %eax
- movl %eax, 0(%edi)
-
- /* Build Level 3 */
- movl $(PGTLOC + 0x1000), %edi
- leal 0x1007(%edi), %eax
- movl $4, %ecx
-1: movl %eax, 0x00(%edi)
- addl $0x00001000, %eax
- addl $8, %edi
- decl %ecx
- jnz 1b
-
- /* Build Level 2 */
- movl $(PGTLOC + 0x2000), %edi
- movl $0x00000183, %eax
- movl $2048, %ecx
-1: movl %eax, 0(%edi)
- addl $0x00200000, %eax
- addl $8, %edi
- decl %ecx
- jnz 1b
-
- /* Enable the boot page tables */
- movl $PGTLOC, %eax
- movl %eax, %cr3
-
- /* Enable Long mode in EFER (Extended Feature Enable Register) */
- movl $0xc0000080, %ecx
- rdmsr
- btsl $8, %eax
- wrmsr
-
- /* Preparing for 64bit jmp */
- pushl $PROT_CODE_SEG
- movl entry, %eax
- pushl %eax
-
- /* Enter paged protected Mode, activating Long Mode */
- xorl %eax, %eax
- btsl $31, %eax
- btsl $0, %eax
- movl %eax, %cr0
-
- /*
- * At this point we're in long mode but in 32bit compatibility mode
- * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
- * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
- * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
- */
-
- lret
-
-
- /* Routines to query the BIOS... */
-/**************************************************************************
-E820_MEMSIZE - Get a listing of memory regions
-**************************************************************************/
-#define SMAP 0x534d4150
- .globl meme820
-meme820:
- pushl %ebp
- movl %esp, %ebp
- pushl %ebx
- pushl %esi
- pushl %edi
- movl 8(%ebp), %edi /* Address to return e820 structures at */
- subl $RELOC, %edi
- movl 12(%ebp), %esi /* Maximum number of e820 structurs to return */
- pushl %esi
- call _prot_to_real
- .code16
- xorl %ebx, %ebx
-jmpe820:
- movl $0xe820, %eax
- movl $SMAP, %edx
- movl $20, %ecx
- /* %di was setup earlier */
- int $0x15
- jc bail820
-
- cmpl $SMAP, %eax
- jne bail820
-
-good820:
- /* If this is useable memory, we save it by simply advancing %di by
- * sizeof(e820rec)
- */
- decl %esi
- testl %esi,%esi
- jz bail820
-
- addw $20, %di
-again820:
- cmpl $0, %ebx /* check to see if %ebx is set to EOF */
- jne jmpe820
-
-bail820:
- data32 call _real_to_prot
- .code32
- popl %eax
- subl %esi, %eax /* Compute how many structure we read */
-
- /* Restore everything else */
- popl %edi
- popl %esi
- popl %ebx
- movl %ebp, %esp
- popl %ebp
- ret
-
-
-/**************************************************************************
-MEME801 - Determine size of extended memory
-**************************************************************************/
- .globl meme801
-meme801:
- pushl %ebx
- pushl %esi
- pushl %edi
- call _prot_to_real
- .code16
-
- stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which dont clear/set
- xorw %dx,%dx # carry on pass/error of
- # e801h memory size call
- # or merely pass cx,dx though
- # without changing them.
- movw $0xe801,%ax
- int $0x15
- jc e801absent
-
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
- movw %ax, %cx # seems to indicate AX/BX
- movw %bx, %dx # are more reasonable anyway...
-
-e801usecxdx:
- andl $0xffff, %edx # clear sign extend
- shll $6, %edx # and go from 64k to 1k chunks
- movl %edx, %eax # store extended memory size
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, %eax # and add lower memory into
-
- jmp e801out
-e801absent:
- xorl %eax,%eax
-
-e801out:
- data32 call _real_to_prot
- .code32
- /* Restore Everything */
- popl %edi
- popl %esi
- popl %ebx
- ret
-
-/**************************************************************************
-MEM88 - Determine size of extended memory
-**************************************************************************/
- .globl mem88
-mem88:
- pushl %ebx
- pushl %esi
- pushl %edi
- call _prot_to_real
- .code16
-
- movb $0x88, %ah
- int $0x15
- andl $0xffff, %eax
-
- data32 call _real_to_prot
- .code32
-
- /* Restore Everything */
- popl %edi
- popl %esi
- popl %ebx
- ret
-
-
-/**************************************************************************
-BASEMEMSIZE - Get size of the conventional (base) memory
-**************************************************************************/
- .globl basememsize
-basememsize:
- call _prot_to_real
- .code16
- int $0x12
- movw %ax,%cx
- DATA32 call _real_to_prot
- .code32
- movw %cx,%ax
- ret
-
-/**************************************************************************
-_REAL_TO_PROT - Go from REAL mode to Protected Mode
-**************************************************************************/
- .globl _real_to_prot
-_real_to_prot:
- .code16
- cli
- cs
- addr32 lgdt gdt_48 - RELOC
- movl %cr0,%eax
- orl $CR0_PE,%eax
- movl %eax,%cr0 /* turn on protected mode */
-
- /* flush prefetch queue, and reload %cs:%eip */
- data32 ljmp $PROT_CODE_SEG,$1f
-1:
- .code32
- /* reload other segment registers */
- movl $PROT_DATA_SEG,%eax
- movl %eax,%ds
- movl %eax,%es
- movl %eax,%ss
- addl $RELOC,%esp /* Fix up stack pointer */
- xorl %eax,%eax
- movl %eax,%fs
- movl %eax,%gs
- popl %eax /* Fix up return address */
- addl $RELOC,%eax
- pushl %eax
-
- /* switch to protected mode idt */
- cs
- lidt idt_48
- ret
-
-/**************************************************************************
-_PROT_TO_REAL - Go from Protected Mode to REAL Mode
-**************************************************************************/
- .globl _prot_to_real
-_prot_to_real:
- .code32
- popl %eax
- subl $RELOC,%eax /* Adjust return address */
- pushl %eax
- subl $RELOC,%esp /* Adjust stack pointer */
- ljmp $REAL_CODE_SEG,$1f- RELOC /* jump to a 16 bit segment */
-1:
- .code16
- /* clear the PE bit of CR0 */
- movl %cr0,%eax
- andl $0!CR0_PE,%eax
- movl %eax,%cr0
-
- /* make intersegment jmp to flush the processor pipeline
- * and reload %cs:%eip (to clear upper 16 bits of %eip).
- */
- data32 ljmp $(RELOC)>>4,$2f- RELOC
-2:
- /* we are in real mode now
- * set up the real mode segment registers : %ds, $ss, %es
- */
- movw %cs,%ax
- movw %ax,%ds
- movw %ax,%es
- movw %ax,%ss
- movw %ax,%fs
- movw %ax,%gs
-
- /* Switch to the real mode idt */
- cs
- addr32 lidt idt_real - RELOC
-
- sti
- data32 ret /* There is a 32 bit return address on the stack */
- .code32
-
-boot_type: .long 0
-boot_data: .long 0
-boot_param: .long 0
-
-idt_real:
- .word 0x400 # idt limit = 256
- .word 0, 0
-idt_48:
- .word 0 # idt limit = 0
- .word 0, 0 # idt base = 0L
-gdt_48:
- .word gdt_end - gdt - 1 # gdt limit=40,
- # (5 GDT entries)
- .long GDTLOC # gdt base
-
-# Descriptor tables
-# These need to be in a seperate section so I can be
-# certain later activities dont stomp them
-gdt:
- /* 0x00 */
- .word 0, 0, 0, 0 # dummy
-
- /* 0x08 */
- /* 16 bit real mode code segment */
- .word 0xffff,(RELOC&0xffff)
- .byte (RELOC>>16),0x9b,0x00,(RELOC>>24)
-
- /* 0x10 */
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- /* 0x18 */
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- /* 0x20 */
- /* 16 bit real mode data segment */
- .word 0xffff,(RELOC&0xffff)
- .byte (RELOC>>16),0x93,0x00,(RELOC>>24)
-
- /* For 2.5.x the kernel segments have moved */
-
- /* 0x28 dummy */
- .quad 0
-
- /* 0x30 dummy */
- .quad 0
- /* 0x38 dummy */
- .quad 0
- /* 0x40 dummy */
- .quad 0
- /* 0x48 dummy */
- .quad 0
- /* 0x50 dummy */
- .quad 0
- /* 0x58 dummy */
- .quad 0
-
-
- /* 0x60 */
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- /* 0x68 */
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
-/*
- * The layout of the per-CPU GDT under Linux:
- *
- * 0 - null
- * 1 - reserved
- * 2 - reserved
- * 3 - reserved
- *
- * 4 - default user CS <==== new cacheline
- * 5 - default user DS
- *
- * ------- start of TLS (Thread-Local Storage) segments:
- *
- * 6 - TLS segment #1 [ glibc's TLS segment ]
- * 7 - TLS segment #2 [ Wine's %fs Win32 segment ]
- * 8 - TLS segment #3
- * 9 - reserved
- * 10 - reserved
- * 11 - reserved
- *
- * ------- start of kernel segments:
- *
- * 12 - kernel code segment <==== new cacheline
- * 13 - kernel data segment
- * 14 - TSS
- * 15 - LDT
- * 16 - PNPBIOS support (16->32 gate)
- * 17 - PNPBIOS support
- * 18 - PNPBIOS support
- * 19 - PNPBIOS support
- * 20 - PNPBIOS support
- * 21 - APM BIOS support
- * 22 - APM BIOS support
- * 23 - APM BIOS support
- */
-gdt_end:
-
-gdt64:
- .word gdt64_end - gdt64
- .long GDT64LOC
- .word 0
- .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x00af9a000000ffff /* __KERNEL_CS */
- .quad 0x00cf92000000ffff /* __KERNEL_DS */
-gdt64_end:
-
- .section ".trailer", "a"
- /* Constants set at build time, these are at the very end of my image */
- .balign 16
- .global image_params
-image_params:
-
-convert_magic:
- .long CONVERT_MAGIC
-gdt_size:
- .long gdt_end - gdt
-gdt64_size:
- .long gdt64_end - gdt64
-pgt_size:
- .long 4096*6
-bss_size:
- .long bss_sizex
-ramdisk_flags:
- .word 0
-root_dev:
- .word DEFAULT_ROOT_DEV
-entry:
- .long 0
-switch_64:
- .long 0
-initrd_start:
- .long 0
-initrd_size:
- .long 0
-cmdline:
- .asciz "BOOT_IMAGE=head.S console=ttyS0 ip=dhcp root=/dev/nfs"
- .org cmdline + CMDLINE_MAX, 0
-cmdline_end: