- One more code sync up, change the startup code.

This commit is contained in:
Eric W. Biederman 2002-10-25 22:57:21 +00:00
parent 3c6821c4fa
commit a3c4d998ee
18 changed files with 193 additions and 220 deletions

View file

@ -3,6 +3,24 @@
*
*/
/*
* Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
*
* This file 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 of
* the License, or (at your option) any later version.
*
* Originally this code was part of ucl the data compression library
* for upx the ``Ultimate Packer of eXecutables''.
*
* - Converted to gas assembly, and refitted to work with etherboot.
* Eric Biederman 20 Aug 2002
* - Merged the nrv2b decompressor into crt0.base of LinuxBIOS
* Eric Biederman 26 Sept 2002
*/
#include <arch/asm.h>
#include <arch/intel.h>
@ -22,11 +40,11 @@
#include "crt0_includes.h"
CONSOLE_DEBUG_TX_STRING($str_after_ram)
/* clear boot_complete flag */
xorl %ebp, %ebp
__main:
CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)
/*
* Copy data into RAM and clear the BSS. Since these segments
@ -41,91 +59,108 @@ __main:
* the location it is compiled to run at.
* Normally this is copying from FLASH ROM to RAM.
*/
leal EXT(_liseg), %esi
leal EXT(_iseg), %edi
cmpl %esi, %edi
jz .Lnocopy
movl $EXT(_eliseg), %ecx
subl %esi, %ecx
jz .Lnocopy /* should not happen */
rep
#if !CONFIG_COMPRESS
movl $_liseg, %esi
movl $_iseg, %edi
movl $_eiseg, %ecx
subl %edi, %ecx
rep movsb
#else
leal 4+_liseg, %esi
leal _iseg, %edi
movl %ebp, %esp /* preserve %ebp */
movl $-1, %ebp /* last_m_off = -1 */
jmp dcl1_n2b
/* ------------- DECOMPRESSION -------------
Input:
%esi - source
%edi - dest
%ebp - -1
cld
Output:
%eax - 0
%ecx - 0
*/
.macro getbit bits
.if \bits == 1
addl %ebx, %ebx
jnz 1f
.endif
movl (%esi), %ebx
subl $-4, %esi /* sets carry flag */
adcl %ebx, %ebx
1:
.endm
decompr_literals_n2b:
movsb
.Lnocopy:
decompr_loop_n2b:
addl %ebx, %ebx
jnz dcl2_n2b
dcl1_n2b:
getbit 32
dcl2_n2b:
jc decompr_literals_n2b
xorl %eax, %eax
incl %eax /* m_off = 1 */
loop1_n2b:
getbit 1
adcl %eax, %eax /* m_off = m_off*2 + getbit() */
getbit 1
jnc loop1_n2b /* while(!getbit()) */
xorl %ecx, %ecx
subl $3, %eax
jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
shll $8, %eax
movb (%esi), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
incl %esi
xorl $-1, %eax
jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
movl %eax, %ebp /* last_m_off = m_off ?*/
decompr_ebpeax_n2b:
getbit 1
adcl %ecx, %ecx /* m_len = getbit() */
getbit 1
adcl %ecx, %ecx /* m_len = m_len*2 + getbit()) */
jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
incl %ecx /* m_len++ */
loop2_n2b:
getbit 1
adcl %ecx, %ecx /* m_len = m_len*2 + getbit() */
getbit 1
jnc loop2_n2b /* while(!getbit()) */
incl %ecx
incl %ecx /* m_len += 2 */
decompr_got_mlen_n2b:
cmpl $-0xd00, %ebp
adcl $1, %ecx /* m_len = m_len + 1 + (last_m_off > 0xd00) */
movl %esi, %edx
leal (%edi,%ebp), %esi /* m_pos = dst + olen + -m_off */
rep
movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
movl %edx, %esi
jmp decompr_loop_n2b
decompr_end_n2b:
intel_chip_post_macro(0x12) /* post 12 */
/** clear stack */
leal EXT(_stack), %edi
movl $EXT(_estack), %ecx
subl %edi, %ecx
xorl %eax, %eax
rep
stosb
/** clear bss */
leal EXT(_bss), %edi
movl $EXT(_ebss), %ecx
subl %edi, %ecx
jz .Lnobss
xorl %eax, %eax
rep
stosb
.Lnobss:
/* set new stack */
movl $_estack, %esp
#ifdef SMP
/* Get the cpu id */
movl $APIC_DEFAULT_BASE, %edi
movl APIC_ID(%edi), %eax
shrl $24, %eax
/* Get the cpu index (MAX_CPUS on error) */
movl $-4, %ebx
1: addl $4, %ebx
cmpl $(MAX_CPUS << 2), %ebx
je 2
cmpl %eax, EXT(initial_apicid)(%ebx)
jne 1b
2: shrl $2, %ebx
/* Now compute the appropriate stack */
movl %ebx, %eax
movl $STACK_SIZE, %ebx
mull %ebx
subl %eax, %esp
#endif
/* push the boot_complete flag */
pushl %ebp
/* Save the stack location */
movl %esp, %ebp
/*
* Now we are finished. Memory is up, data is copied and
* bss is cleared. Now we call the main routine and
* let it do the rest.
*/
intel_chip_post_macro(0xfe) /* post fe */
CONSOLE_DEBUG_TX_STRING($str_pre_main)
/* memory is up. Let\'s do the rest in C -- much easier. */
intel_chip_post_macro(0xfd) /* post fe */
/* Resort the stack location */
movl %ebp, %esp
#endif
/* The boot_complete flag has already been pushed */
call EXT(hardwaremain)
/*NOTREACHED*/
CONSOLE_DEBUG_TX_STRING($str_pre_main)
leal _iseg, %edi
jmp %edi
.Lhlt:
intel_chip_post_macro(0xee) /* post fe */
hlt
jmp .Lhlt
.section ".rom.data"
str_after_ram: .string "Copying LinuxBIOS to ram.\r\n"
str_copying_to_ram: .string "Copying LinuxBIOS to ram.\r\n"
str_pre_main: .string "Jumping to LinuxBIOS.\r\n"
.previous

View file

@ -31,9 +31,11 @@ OUTPUT_ARCH(i386)
ENTRY(_start)
TARGET(binary)
INPUT(linuxbios_payload)
SECTIONS
{
. = DEFINED(_ROMBASE)? _ROMBASE : _RAMBASE;
. = _ROMBASE;
/* This section might be better named .setup */
.rom . : {
_rom = .;
@ -44,88 +46,17 @@ SECTIONS
}
_lrom = LOADADDR(.rom);
_elrom = LOADADDR(.rom) + SIZEOF(.rom);
. = DEFINED(_ROMBASE)? _RAMBASE : . ;
/*
* First we place the code and read only data (typically const declared).
* This get placed in rom.
*/
.text . : AT (_elrom) {
_text = .;
*(.text);
*(.text.*);
. = ALIGN(16);
_etext = .;
.payload . : {
_payload = . ;
linuxbios_payload(*)
_epayload = . ;
}
_ltext = LOADADDR(.text);
_eltext = LOADADDR(.text) + SIZEOF(.text);
.rodata . : AT(_eltext){
_rodata = .;
. = ALIGN(4);
streams = . ;
*(.rodata.streams)
estreams = .;
. = ALIGN(4);
pci_drivers = . ;
*(.rodata.pci_drivers)
epci_drivers = . ;
*(.rodata)
*(.rodata.*)
_erodata = .;
}
_lrodata = LOADADDR(.rodata);
_elrodata = LOADADDR(.rodata) + SIZEOF(.rodata);
/*
* After the code we place initialized data (typically initialized
* global variables). This gets copied into ram by startup code.
* __data_start and __data_end shows where in ram this should be placed,
* whereas __data_loadstart and __data_loadend shows where in rom to
* copy from.
*/
.data . : AT(_elrodata) {
_data = .;
*(.data)
_edata = .;
}
_ldata = LOADADDR(.data);
_eldata = LOADADDR(.data) + SIZEOF(.data);
/* The initialized data segment.
* This is all of the data that we copy from rom into the ram.
*/
_iseg = _text;
_eiseg = _edata;
_liseg = _ltext;
_eliseg = _eldata;
/*
* bss does not contain data, it is just a space that should be zero
* initialized on startup. (typically uninitialized global variables)
* crt0.S fills between _bss and _ebss with zeroes.
*/
_bss = .;
.bss . : {
*(.bss)
*(.sbss)
*(COMMON)
}
_ebss = .;
_end = .;
_stack = .;
.stack . : {
/* Reserve a stack for each possible cpu, +1 extra */
. = ((MAX_CPUS * STACK_SIZE) + STACK_SIZE) ;
}
_estack = .;
_heap = .;
.heap . : {
/* Reserve 256K for the heap */
. = HEAP_SIZE ;
. = ALIGN(4);
}
_eheap = .;
/* The ram segment
* This is all address of the memory resident copy of linuxBIOS.
*/
_ram_seg = _text;
_eram_seg = _eheap;
_iseg = _RAMBASE;
_eiseg = _iseg + SIZEOF(.payload);
_liseg = _payload;
_eliseg = _epayload;
/DISCARD/ : {
*(.comment)
*(.note)

View file

@ -26,6 +26,8 @@ makerule floppy : all ; mcopy -o romimage a:
makerule romimage : linuxbios.rom payload.block ; cat payload.block linuxbios.rom > romimage
makerule nrv2b: $(TOP)/util/nrv2b/nrv2b.c ; $(HOSTCC) -O2 -DENCODE -DDECODE -DMAIN -DVERBOSE -DNDEBUG -DBITSIZE=32 -DENDIAN=0 $< -o $@
makerule linuxbios.rom: linuxbios.strip ;
addaction linuxbios.rom export size=`ls -l linuxbios.strip | (read p c u g size r ; echo $$size)` ; \
addaction linuxbios.rom echo $$size ; \

View file

@ -5,3 +5,5 @@ object pirq_routing.o HAVE_PIRQ_TABLE
object vgabios.o CONFIG_VGABIOS
object idt.o CONFIG_REALMODE_IDT
option CONFIG_LOGICAL_CPUS=1
object c_start.S

View file

@ -32,11 +32,22 @@ makerule ldoptions : Makefile.settings ; perl -e 'foreach $$var (split(" ", $$EN
makerule linuxbios.strip: linuxbios ; $(OBJCOPY) -O binary linuxbios linuxbios.strip
makerule linuxbios.o : crt0.o $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME) ; $(CC) -nostdlib -r -o $@ crt0.o $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME)
makerule linuxbios_c.o: $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME) ; $(CC) -nostdlib -r -o $@ c_start.o $(DRIVERS-1) linuxbios.a $(LIBGCC_FILE_NAME)
makerule linuxbios: linuxbios.o ldscript.ld ; $(CC) -nostdlib -nostartfiles -static -o $@ -T ldscript.ld linuxbios.o
addaction linuxbios nm -n linuxbios > linuxbios.map
makerule linuxbios_c: linuxbios_c.o $(TOP)/src/config/linuxbios_c.ld ldoptions ; $(CC) -nostdlib -nostartfiles -static -o $@ -T $(TOP)/src/config/linuxbios_c.ld linuxbios_c.o
option CONFIG_COMPRESS=1
expr CONFIG_UNCOMPRESSED=!CONFIG_COMPRESS
makedefine LINUXBIOS_PAYLOAD-$(CONFIG_COMPRESS):=linuxbios_payload.nrv2b
makedefine LINUXBIOS_PAYLOAD-$(CONFIG_UNCOMPRESSED):=linuxbios_payload.bin
addaction linuxbios_c nm -n linuxbios_c | sort > linuxbios_c.map
makerule linuxbios_payload.bin: linuxbios_c; $(OBJCOPY) -O binary $< $@
makerule linuxbios_payload.nrv2b: linuxbios_payload.bin nrv2b ; ./nrv2b e $< $@
makerule linuxbios_payload: $(LINUXBIOS_PAYLOAD-1) ; cp $(LINUXBIOS_PAYLOAD-1) linuxbios_payload
makerule linuxbios: crt0.o linuxbios_payload ldscript.ld ; $(CC) -nostdlib -nostartfiles -static -o $@ -T ldscript.ld crt0.o
addaction linuxbios nm -n linuxbios | sort > linuxbios.map
makerule linuxbios.a : $(OBJECTS-1) ; rm -f linuxbios.a
addaction linuxbios.a ar cr linuxbios.a $(OBJECTS-1)
@ -57,9 +68,9 @@ makerule etags: $(SOURCES) ; etags $(SOURCES)
makerule tags: $(SOURCES) ; ctags $(SOURCES)
makerule documentation: $(SOURCES) ; doxygen LinuxBIOSDoc.config
makerule build_opt_tbl: $(TOP)/util/options/build_opt_tbl.c ; $(HOSTCC) $(HOSTCFLAGS) $< -o $@
makerule build_opt_tbl: $(TOP)/util/options/build_opt_tbl.c $(TOP)/src/include/pc80/mc146818rtc.h $(TOP)/src/include/boot/linuxbios_tables.h ; $(HOSTCC) $(HOSTCFLAGS) $< -o $@
makerule /$(TARGET_DIR)/option_table.c : build_opt_tbl $(MAINBOARD)/cmos.conf ; ./build_opt_tbl -b --config $(MAINBOARD)/cmos.conf
makerule /$(TARGET_DIR)/option_table.c : build_opt_tbl $(MAINBOARD)/cmos.layout ; ./build_opt_tbl -b --config $(MAINBOARD)/cmos.layout
object /$(TARGET_DIR)/option_table.o HAVE_OPTION_TABLE

View file

@ -26,6 +26,7 @@ it with the version available from LANL.
*/
/* .section ".rom.text" */
#include <arch/rom_segs.h>
.code16
.globl EXT(_start)
.type EXT(_start), @function
@ -93,7 +94,7 @@ EXT(_start):
movl %eax, %cr0
/* Now that we are in protected mode jump to a 32 bit code segment. */
data32 ljmp $0x10, $__protected_start
data32 ljmp $ROM_CODE_SEG, $__protected_start
/** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
* at 0x18; these are Linux-compatible.

View file

@ -1,66 +1,40 @@
/* For starting linuxBIOS in protected mode */
#include <arch/rom_segs.h>
#include <arch/cache_ram.h>
/* .section ".rom.text" */
.code32
/** This gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
* at 0x18; these are Linux-compatible.
*/
/** GDT. we have modified this from the original freebios to make it
* compatible with linux. This puts text at seg 0x10 and data at 0x18
*/
.align 4
.globl EXT(gdtptr)
gdt:
EXT(gdtptr):
.word gdt_end - gdt -1 /* compute the table limit */
.long gdt /* we know the offset */
.word 0
gdt:
// selgdt 0
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
// selgdt 8
/* flat cache ram offset data segment */
.word 0xffff, _cache_ram_seg_base_low
.byte _cache_ram_seg_base_middle, 0x93, 0xcf
.byte _cache_ram_seg_base_high
// selgdt 0x10
/* flat code segment */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xcf, 0x00
//selgdt 0x18
/* flat data segment */
.word 0xffff, 0x0000
.byte 0x00, 0x93, 0xcf, 0x00
//selgdt 0x20
#if 0 /* FIXME make the cache as ram code work again */
/* flat rom offset code segment */
.word 0xffff, _rom_code_seg_base_low
.byte _rom_code_seg_base_middle, 0x9b, 0xcf
.byte _rom_code_seg_base_high
/* flat cache ram offset data segment */
.word 0xffff, _cache_ram_seg_base_low
.byte _cache_ram_seg_base_middle, 0x93, 0xcf
.byte _cache_ram_seg_base_high
#endif
#if defined(CONFIG_VGABIOS) && (CONFIG_VGABIOS == 1)
// from monty:
/* 0x00009a00,0000ffffULL, 20h: 16-bit 64k code at 0x00000000 */
/* 0x00009200,0000ffffULL 28h: 16-bit 64k data at 0x00000000 */
// selgdt 0x28
/*16-bit 64k code at 0x00000000 */
.word 0xffff, 0x0000
.byte 0, 0x9a, 0, 0
// selgdt 0x30
/*16-bit 64k data at 0x00000000 */
.word 0xffff, 0x0000
.byte 0, 0x92, 0, 0
#endif // defined(CONFIG_VGABIOS) && (CONFIG_VGABIOS == 1)
gdt_end:
@ -80,12 +54,12 @@ gdt_end:
EXT(protected_start):
lgdt %cs:gdtptr
ljmp $0x10, $__protected_start
ljmp $ROM_CODE_SEG, $__protected_start
__protected_start:
intel_chip_post_macro(0x10) /* post 10 */
movw $0x18, %ax
movw $ROM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss

View file

@ -1,3 +1,4 @@
/*
_cache_ram_seg_base = DEFINED(CACHE_RAM_BASE)? CACHE_RAM_BASE - _rodata : 0;
_cache_ram_seg_base_low = (_cache_ram_seg_base) & 0xffff;
_cache_ram_seg_base_middle = (_cache_ram_seg_base >> 16) & 0xff;
@ -7,6 +8,7 @@
_rom_code_seg_base_low = (_rom_code_seg_base) & 0xffff;
_rom_code_seg_base_middle = (_rom_code_seg_base >> 16) & 0xff;
_rom_code_seg_base_high = (_rom_code_seg_base >> 24) & 0xff;
*/

View file

@ -30,7 +30,7 @@
movl %eax, %cr0
/* Reload the normal data segments */
movw $0x18, %ax
movw $ROM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss

View file

@ -54,9 +54,8 @@ start_cacheram: .string "Start cache ram\r\n"
cmpl %esi, %edi
jnz 1b
intel_chip_post_macro(0x02)
/* Load a different set of data segments */
movw $0x08, %ax
movw $CACHE_RAM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss

View file

@ -34,11 +34,11 @@
* - I change teh code segments back to my normal segment with
* a 4GB limit and a base address of 0.
*/
ljmp $0x20, $___cache_ram_code_start
ljmp $CACHE_RAM_CODE_SEG, $___cache_ram_code_start
.globl __cache_ram_code_start
__cache_ram_code_start:
lcall $0x20, $cache_ram_start
ljmp $0x10, $__cache_ram_code_done
lcall $CACHE_RAM_CODE_SEG, $cache_ram_start
ljmp $ROM_CODE_SEG, $__cache_ram_code_done
.globl __cache_ram_code_done
__cache_ram_code_done:

View file

@ -30,7 +30,7 @@
movl %eax, %cr0
/* Reload the normal data segments */
movw $0x18, %ax
movw $ROM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss

View file

@ -41,7 +41,7 @@
jnz 1b
/* Load a different set of data segments */
movw $0x08, %ax
movw $CACHE_RAM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss

View file

@ -304,7 +304,7 @@ static void display_cpuid_update_microcode(void)
{
unsigned int eax, ebx, ecx, edx;
unsigned int pf, rev, sig, val[2];
unsigned int x86_model, i;
unsigned int x86_model, x86_family, i;
struct microcode *m;
/* cpuid sets msr 0x8B iff a microcode update has been loaded. */
@ -312,15 +312,16 @@ static void display_cpuid_update_microcode(void)
cpuid(1, &eax, &ebx, &ecx, &edx);
rdmsr(0x8B, val[0], rev);
x86_model = (eax >>4) & 0x0f;
x86_family = (eax >>8) & 0x0f;
sig = eax;
pf = 0;
if (x86_model >= 5) {
if ((x86_model >= 5)||(x86_family>6)) {
rdmsr(0x17, val[0], val[1]);
pf = 1 << ((val[1] >> 18) & 7);
}
printk_info("microcode_info: sig = 0x%08x pf=0x%08x rev = 0x%08x\n",
sig, pf, rev);
printk_debug("microcode_info: sig = 0x%08x pf=0x%08x rev = 0x%08x\n",
sig, pf, rev);
m = (void *)&microcode_updates;
for(i = 0; i < sizeof(microcode_updates)/sizeof(struct microcode); i++) {
@ -336,6 +337,6 @@ static void display_cpuid_update_microcode(void)
void p6_cpufixup(struct mem_range *mem)
{
printk_info("Updating microcode\n");
printk_debug("Updating microcode\n");
display_cpuid_update_microcode();
}

View file

@ -163,6 +163,21 @@ struct cmos_defaults {
uint8_t default_set[CMOS_IMAGE_BUFFER_SIZE]; /* default settings */
};
#define LB_TAG_OPTION_CHECKSUM 204
struct cmos_checksum {
uint32_t tag;
uint32_t size;
/* In practice everything is byte aligned, but things are measured
* in bits to be consistent.
*/
uint32_t range_start; /* First bit that is checksummed (byte aligned) */
uint32_t range_end; /* Last bit that is checksummed (byte aligned) */
uint32_t location; /* First bit of the checksum (byte aligned) */
uint32_t type; /* Checksum algorithm that is used */
#define CHECKSUM_NONE 0
#define CHECKSUM_PCBIOS 1
};
#endif /* LINUXBIOS_TABLES_H */

View file

@ -6,11 +6,11 @@ struct mem_range;
#include <cpu/k7/cpufixup.h>
#include <cpu/p6/cpufixup.h>
#ifdef CPU_FIXUP
#if CPU_FIXUP == 1
# if defined(k7)
# define cpufixup(mem) k7_cpufixup(mem)
# elif defined(i786)
# define cpufixup(mem) p6_cpufixup(mem)
# define cpufixup(mem) i786_cpufixup(mem)
# elif defined(i686)
# define cpufixup(mem) p6_cpufixup(mem)
# endif

View file

@ -1,8 +1,8 @@
#ifndef CPU_P6_CPUFIXUP_H
#define CPU_P6_CPUFIXUP_H
#ifdef UPDATE_MICROCODE
#define CPU_FIXUP
#if UPDATE_MICROCODE == 1
#define CPU_FIXUP 1
#endif
void p6_cpufixup(struct mem_range *mem);

View file

@ -1,4 +1,4 @@
option CONFIG_UDELAY_TSC
option CONFIG_UDELAY_TSC=1
object southbridge.o
object nvram.o
object amd766_ioapic.o