remove old i386 support
This commit is contained in:
parent
ece38eddf5
commit
3c4c4d2e66
|
@ -1,46 +0,0 @@
|
|||
#
|
||||
# (C) Copyright 2002-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program 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.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(ARCH).a
|
||||
|
||||
SOBJS = bios.o bios_pci.o realmode_switch.o
|
||||
|
||||
COBJS = board.o bios_setup.o i386_linux.o zimage.o realmode.o \
|
||||
pci_type1.o pci.o video_bios.o video.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
|
||||
|
||||
$(LIB): $(obj).depend $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
462
lib_i386/bios.S
462
lib_i386/bios.S
|
@ -1,462 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on msbios.c from rolo 1.6:
|
||||
*----------------------------------------------------------------------
|
||||
* (C) Copyright 2000
|
||||
* Sysgo Real-Time Solutions GmbH
|
||||
* Klein-Winternheim, Germany
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "bios.h"
|
||||
|
||||
/*
|
||||
* During it's initialization phase, before switching to protected
|
||||
* mode, the Linux Kernel makes a few BIOS calls. This won't work
|
||||
* if the board does not have a BIOS.
|
||||
*
|
||||
* This is a very minimalisic BIOS that supplies just enough
|
||||
* functionality to keep the Linux Kernel happy. It is NOT
|
||||
* a general purpose replacement for a real BIOS !!
|
||||
*/
|
||||
|
||||
|
||||
.section .bios, "ax"
|
||||
.code16
|
||||
.org 0
|
||||
/* a call to f000:0 should warmboot */
|
||||
jmp realmode_reset
|
||||
|
||||
.globl rm_int00
|
||||
rm_int00:
|
||||
pushw $0
|
||||
jmp any_interrupt16
|
||||
.globl rm_int01
|
||||
rm_int01:
|
||||
pushw $1
|
||||
jmp any_interrupt16
|
||||
.globl rm_int02
|
||||
rm_int02:
|
||||
pushw $2
|
||||
jmp any_interrupt16
|
||||
.globl rm_int03
|
||||
rm_int03:
|
||||
pushw $3
|
||||
jmp any_interrupt16
|
||||
.globl rm_int04
|
||||
rm_int04:
|
||||
pushw $4
|
||||
jmp any_interrupt16
|
||||
.globl rm_int05
|
||||
rm_int05:
|
||||
pushw $5
|
||||
jmp any_interrupt16
|
||||
.globl rm_int06
|
||||
rm_int06:
|
||||
pushw $6
|
||||
jmp any_interrupt16
|
||||
.globl rm_int07
|
||||
rm_int07:
|
||||
pushw $7
|
||||
jmp any_interrupt16
|
||||
.globl rm_int08
|
||||
rm_int08:
|
||||
pushw $8
|
||||
jmp any_interrupt16
|
||||
.globl rm_int09
|
||||
rm_int09:
|
||||
pushw $9
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0a
|
||||
rm_int0a:
|
||||
pushw $10
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0b
|
||||
rm_int0b:
|
||||
pushw $11
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0c
|
||||
rm_int0c:
|
||||
pushw $12
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0d
|
||||
rm_int0d:
|
||||
pushw $13
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0e
|
||||
rm_int0e:
|
||||
pushw $14
|
||||
jmp any_interrupt16
|
||||
.globl rm_int0f
|
||||
rm_int0f:
|
||||
pushw $15
|
||||
jmp any_interrupt16
|
||||
.globl rm_int10
|
||||
rm_int10:
|
||||
pushw $16
|
||||
jmp any_interrupt16
|
||||
.globl rm_int11
|
||||
rm_int11:
|
||||
pushw $17
|
||||
jmp any_interrupt16
|
||||
.globl rm_int12
|
||||
rm_int12:
|
||||
pushw $18
|
||||
jmp any_interrupt16
|
||||
.globl rm_int13
|
||||
rm_int13:
|
||||
pushw $19
|
||||
jmp any_interrupt16
|
||||
.globl rm_int14
|
||||
rm_int14:
|
||||
pushw $20
|
||||
jmp any_interrupt16
|
||||
.globl rm_int15
|
||||
rm_int15:
|
||||
pushw $21
|
||||
jmp any_interrupt16
|
||||
.globl rm_int16
|
||||
rm_int16:
|
||||
pushw $22
|
||||
jmp any_interrupt16
|
||||
.globl rm_int17
|
||||
rm_int17:
|
||||
pushw $23
|
||||
jmp any_interrupt16
|
||||
.globl rm_int18
|
||||
rm_int18:
|
||||
pushw $24
|
||||
jmp any_interrupt16
|
||||
.globl rm_int19
|
||||
rm_int19:
|
||||
pushw $25
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1a
|
||||
rm_int1a:
|
||||
pushw $26
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1b
|
||||
rm_int1b:
|
||||
pushw $27
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1c
|
||||
rm_int1c:
|
||||
pushw $28
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1d
|
||||
rm_int1d:
|
||||
pushw $29
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1e
|
||||
rm_int1e:
|
||||
pushw $30
|
||||
jmp any_interrupt16
|
||||
.globl rm_int1f
|
||||
rm_int1f:
|
||||
pushw $31
|
||||
jmp any_interrupt16
|
||||
.globl rm_def_int
|
||||
rm_def_int:
|
||||
iret
|
||||
|
||||
|
||||
/*
|
||||
* All interrupt jumptable entries jump to here
|
||||
* after pushing the interrupt vector number onto the
|
||||
* stack.
|
||||
*/
|
||||
any_interrupt16:
|
||||
MAKE_BIOS_STACK
|
||||
|
||||
gs movw OFFS_VECTOR(%bp), %ax
|
||||
cmpw $0x10, %ax
|
||||
je Lint_10h
|
||||
cmpw $0x11, %ax
|
||||
je Lint_11h
|
||||
cmpw $0x12, %ax
|
||||
je Lint_12h
|
||||
cmpw $0x13, %ax
|
||||
je Lint_13h
|
||||
cmpw $0x15, %ax
|
||||
je Lint_15h
|
||||
cmpw $0x16, %ax
|
||||
je Lint_16h
|
||||
cmpw $0x1a, %ax
|
||||
je Lint_1ah
|
||||
movw $0xffff, %ax
|
||||
jmp Lout
|
||||
Lint_10h: /* VGA BIOS services */
|
||||
call bios_10h
|
||||
jmp Lout
|
||||
Lint_11h:
|
||||
call bios_11h
|
||||
jmp Lout
|
||||
Lint_12h:
|
||||
call bios_12h
|
||||
jmp Lout
|
||||
Lint_13h: /* BIOS disk services */
|
||||
call bios_13h
|
||||
jmp Lout
|
||||
Lint_15h: /* Misc. BIOS services */
|
||||
call bios_15h
|
||||
jmp Lout
|
||||
Lint_16h: /* keyboard services */
|
||||
call bios_16h
|
||||
jmp Lout
|
||||
Lint_1ah: /* PCI bios */
|
||||
call bios_1ah
|
||||
jmp Lout
|
||||
Lout:
|
||||
cmpw $0, %ax
|
||||
je Lhandeled
|
||||
|
||||
/* Insert code for unhandeled INTs here.
|
||||
*
|
||||
* ROLO prints a message to the console
|
||||
* (we could do that but then we're in 16bit mode
|
||||
* so we'll have to get back into 32bit mode
|
||||
* to use the console I/O routines (if we do this
|
||||
* we shuls make int 0x10 and int 0x16 work as well))
|
||||
*/
|
||||
Lhandeled:
|
||||
RESTORE_CALLERS_STACK
|
||||
addw $2,%sp /* dump vector number */
|
||||
iret /* return from interrupt */
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 10h -- VGA services
|
||||
************************************************************
|
||||
*/
|
||||
bios_10h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
shrw $8, %ax
|
||||
cmpw $0x3, %ax
|
||||
je Lcur_pos
|
||||
cmpw $0xf, %ax
|
||||
je Lvid_state
|
||||
cmpw $0x12, %ax
|
||||
je Lvid_cfg
|
||||
movw $0xffff, %ax
|
||||
ret
|
||||
Lcur_pos: /* Read Cursor Position and Size */
|
||||
gs movw $0, OFFS_CX(%bp)
|
||||
gs movw $0, OFFS_DX(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
Lvid_state: /* Get Video State */
|
||||
gs movw $(80 << 8|0x03), OFFS_AX(%bp) /* 80 columns, 80x25, 16 colors */
|
||||
gs movw $0, OFFS_BX(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
Lvid_cfg: /* Video Subsystem Configuration (EGA/VGA) */
|
||||
gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 11h -- Equipment determination
|
||||
************************************************************
|
||||
*/
|
||||
|
||||
bios_11h:
|
||||
cs movw bios_equipment, %ax
|
||||
gs movw %ax, OFFS_AX(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 12h -- Get Memory Size
|
||||
************************************************************
|
||||
*/
|
||||
bios_12h:
|
||||
cs movw ram_in_64kb_chunks, %ax
|
||||
cmpw $0xa, %ax
|
||||
ja b12_more_than_640k
|
||||
shlw $6, %ax
|
||||
jmp b12_return
|
||||
b12_more_than_640k:
|
||||
movw $0x280, %ax
|
||||
b12_return:
|
||||
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */
|
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
andw $0xfffe, %ax /* clear carry -- function succeeded */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 13h -- Disk services
|
||||
************************************************************
|
||||
*/
|
||||
bios_13h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
shrw $8, %ax
|
||||
cmpw $0x15, %ax
|
||||
je Lfunc_15h
|
||||
movw $0xffff, %ax
|
||||
ret
|
||||
Lfunc_15h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
andw $0xff, %ax /* return AH=0->drive not present */
|
||||
gs movw %ax, OFFS_AX(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
***********************************************************
|
||||
* BIOS interrupt 15h -- Miscellaneous services
|
||||
***********************************************************
|
||||
*/
|
||||
bios_15h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
shrw $8, %ax
|
||||
cmpw $0xc0, %ax
|
||||
je Lfunc_c0h
|
||||
cmpw $0xe8, %ax
|
||||
je Lfunc_e8h
|
||||
cmpw $0x88, %ax
|
||||
je Lfunc_88h
|
||||
movw $0xffff, %ax
|
||||
ret
|
||||
|
||||
Lfunc_c0h: /* Return System Configuration Parameters (PS2 only) */
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
orw $1, %ax /* return carry -- function not supported */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
Lfunc_e8h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
andw $0xff, %ax
|
||||
cmpw $1, %ax
|
||||
je Lfunc_e801h
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
orw $1, %ax /* return carry -- function not supported */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
Lfunc_e801h: /* Get memory size for >64M Configurations */
|
||||
cs movw ram_in_64kb_chunks, %ax
|
||||
cmpw $0x100, %ax
|
||||
ja e801_more_than_16mb
|
||||
shlw $6, %ax /* multiply by 64 */
|
||||
subw $0x400, %ax /* 1st meg does not count */
|
||||
|
||||
gs movw %ax, OFFS_AX(%bp) /* return memory size between 1M and 16M in 1kb chunks in AX and CX */
|
||||
gs movw %ax, OFFS_CX(%bp)
|
||||
gs movw $0, OFFS_BX(%bp) /* set BX and DX to 0*/
|
||||
gs movw $0, OFFS_DX(%bp)
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
andw $0xfffe, %ax /* clear carry -- function succeeded */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
e801_more_than_16mb:
|
||||
subw $0x100, %ax /* subtract 16MB */
|
||||
|
||||
gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-1MB) in AX and CX */
|
||||
gs movw $0x3c00, OFFS_CX(%bp)
|
||||
gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks above 16MB */
|
||||
gs movw %ax, OFFS_DX(%bp)
|
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
andw $0xfffe, %ax /* clear carry -- function succeeded */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
Lfunc_88h:
|
||||
cs movw ram_in_64kb_chunks, %ax
|
||||
cmpw $0x100, %ax
|
||||
jna b88_not_more_than16
|
||||
movw $0x100, %ax
|
||||
b88_not_more_than16:
|
||||
shlw $6, %ax
|
||||
subw $0x400, %ax /* 1st meg does not count */
|
||||
|
||||
gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes between 16MB and 16MB in ax */
|
||||
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
andw $0xfffe, %ax /* clear carry -- function succeeded */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
|
||||
xorw %ax, %ax
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 16h -- keyboard services
|
||||
************************************************************
|
||||
*/
|
||||
bios_16h:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
shrw $8, %ax
|
||||
cmpw $0x03, %ax
|
||||
je Lfunc_03h
|
||||
movw $0xffff, %ax
|
||||
ret
|
||||
Lfunc_03h:
|
||||
xorw %ax, %ax /* do nothing -- function not supported */
|
||||
ret
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* BIOS interrupt 1ah -- PCI bios
|
||||
************************************************************
|
||||
*/
|
||||
bios_1ah:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
cmpb $0xb1, %ah
|
||||
je Lfunc_b1h
|
||||
movw $0xffff, %ax
|
||||
ret
|
||||
Lfunc_b1h:
|
||||
call realmode_pci_bios
|
||||
xorw %ax, %ax /* do nothing -- function not supported */
|
||||
ret
|
||||
|
||||
|
||||
.globl ram_in_64kb_chunks
|
||||
ram_in_64kb_chunks:
|
||||
.word 0
|
||||
|
||||
.globl bios_equipment
|
||||
bios_equipment:
|
||||
.word 0
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _BIOS_H_
|
||||
#define _BIOS_H_
|
||||
|
||||
#define OFFS_ES 0 /* 16bit */
|
||||
#define OFFS_GS 2 /* 16bit */
|
||||
#define OFFS_DS 4 /* 16bit */
|
||||
#define OFFS_EDI 6 /* 32bit */
|
||||
#define OFFS_DI 6 /* low 16 bits of EDI */
|
||||
#define OFFS_ESI 10 /* 32bit */
|
||||
#define OFFS_SI 10 /* low 16 bits of ESI */
|
||||
#define OFFS_EBP 14 /* 32bit */
|
||||
#define OFFS_BP 14 /* low 16 bits of EBP */
|
||||
#define OFFS_ESP 18 /* 32bit */
|
||||
#define OFFS_SP 18 /* low 16 bits of ESP */
|
||||
#define OFFS_EBX 22 /* 32bit */
|
||||
#define OFFS_BX 22 /* low 16 bits of EBX */
|
||||
#define OFFS_BL 22 /* low 8 bits of BX */
|
||||
#define OFFS_BH 23 /* high 8 bits of BX */
|
||||
#define OFFS_EDX 26 /* 32bit */
|
||||
#define OFFS_DX 26 /* low 16 bits of EBX */
|
||||
#define OFFS_DL 26 /* low 8 bits of BX */
|
||||
#define OFFS_DH 27 /* high 8 bits of BX */
|
||||
#define OFFS_ECX 30 /* 32bit */
|
||||
#define OFFS_CX 30 /* low 16 bits of EBX */
|
||||
#define OFFS_CL 30 /* low 8 bits of BX */
|
||||
#define OFFS_CH 31 /* high 8 bits of BX */
|
||||
#define OFFS_EAX 34 /* 32bit */
|
||||
#define OFFS_AX 34 /* low 16 bits of EBX */
|
||||
#define OFFS_AL 34 /* low 8 bits of BX */
|
||||
#define OFFS_AH 35 /* high 8 bits of BX */
|
||||
#define OFFS_VECTOR 38 /* 16bit */
|
||||
#define OFFS_IP 40 /* 16bit */
|
||||
#define OFFS_CS 42 /* 16bit */
|
||||
#define OFFS_FLAGS 44 /* 16bit */
|
||||
|
||||
#define SEGMENT 0x40
|
||||
#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */
|
||||
|
||||
/* save general registers */
|
||||
/* save some segments */
|
||||
/* save callers stack segment .. */
|
||||
/* ... in gs */
|
||||
/* setup my segments */
|
||||
/* setup BIOS stackpointer */
|
||||
|
||||
#define MAKE_BIOS_STACK \
|
||||
pushal ; \
|
||||
pushw %ds ; \
|
||||
pushw %gs ; \
|
||||
pushw %es ; \
|
||||
pushw %ss ; \
|
||||
popw %gs ; \
|
||||
movw $SEGMENT,%ax ; \
|
||||
movw %ax,%ds ; \
|
||||
movw %ax,%es ; \
|
||||
movw %ax,%ss ; \
|
||||
movw %sp,%bp ; \
|
||||
movw $STACK,%sp
|
||||
|
||||
#define RESTORE_CALLERS_STACK \
|
||||
pushw %gs ; /* restore callers stack segment */ \
|
||||
popw %ss ; \
|
||||
movw %bp,%sp ; /* restore stackpointer */ \
|
||||
\
|
||||
popw %es ; /* restore segment selectors */ \
|
||||
popw %gs ; \
|
||||
popw %ds ; \
|
||||
\
|
||||
popal /* restore GP registers */
|
||||
|
||||
#endif
|
|
@ -1,411 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* x86 realmode assembly implementation of a PCI BIOS
|
||||
* for platforms that use one PCI hose and configuration
|
||||
* access type 1. (The common case for low-end PC's)
|
||||
*/
|
||||
|
||||
#include "bios.h"
|
||||
|
||||
#define PCI_BIOS_DEBUG
|
||||
|
||||
.section .bios, "ax"
|
||||
.code16
|
||||
.globl realmode_pci_bios_call_entry
|
||||
realmode_pci_bios_call_entry:
|
||||
MAKE_BIOS_STACK
|
||||
call realmode_pci_bios
|
||||
RESTORE_CALLERS_STACK
|
||||
ret
|
||||
|
||||
|
||||
.globl realmode_pci_bios
|
||||
realmode_pci_bios:
|
||||
gs movw OFFS_AX(%bp), %ax
|
||||
cmpb $1, %al
|
||||
je pci_bios_present
|
||||
cmpb $2, %al
|
||||
je pci_bios_find_device
|
||||
cmpb $3, %al
|
||||
je pci_bios_find_class
|
||||
cmpb $6, %al
|
||||
je pci_bios_generate_special_cycle
|
||||
cmpb $8, %al
|
||||
je pci_bios_read_cfg_byte
|
||||
cmpb $9, %al
|
||||
je pci_bios_read_cfg_word
|
||||
cmpb $10, %al
|
||||
je pci_bios_read_cfg_dword
|
||||
cmpb $11, %al
|
||||
je pci_bios_write_cfg_byte
|
||||
cmpb $12, %al
|
||||
je pci_bios_write_cfg_word
|
||||
cmpb $13, %al
|
||||
je pci_bios_write_cfg_dword
|
||||
cmpb $14, %al
|
||||
je pci_bios_get_irq_routing
|
||||
cmpb $15, %al
|
||||
je pci_bios_set_irq
|
||||
jmp unknown_function
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_present:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_present
|
||||
#endif
|
||||
movl $0x20494350, %eax
|
||||
gs movl %eax, OFFS_EDX(%bp)
|
||||
movb $0x01, %al
|
||||
gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
|
||||
movw $0x0210, %ax /* version 2.10 */
|
||||
gs movw %ax, OFFS_BX(%bp)
|
||||
cs movb pci_last_bus, %al /* last bus number */
|
||||
gs movb %al, OFFS_CL(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* device 0-31, function 0-7 */
|
||||
pci_bios_find_device:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_find_device
|
||||
#endif
|
||||
gs movw OFFS_CX(%bp), %di
|
||||
shll $16, %edi
|
||||
gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
|
||||
* bits and vendor in lower 16 bits */
|
||||
gs movw OFFS_SI(%bp), %si
|
||||
xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
|
||||
pfd_loop:
|
||||
xorw %ax, %ax /* dword 0 is vendor/device */
|
||||
call __pci_bios_select_register
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
cmpl %edi, %eax /* our device ? */
|
||||
je pfd_found_one
|
||||
pfd_next_dev:
|
||||
/* check for multi function devices */
|
||||
movw %bx, %ax
|
||||
andw $3, %ax
|
||||
jnz pfd_function_not_zero
|
||||
movw $0x000c, %ax
|
||||
call __pci_bios_select_register
|
||||
movw $0xcfe, %dx
|
||||
inb %dx, %al
|
||||
andb $0x80, %al
|
||||
jz pfd_not_multi_function
|
||||
pfd_function_not_zero:
|
||||
incw %bx /* next function, overflows in to
|
||||
* device number, then bus number */
|
||||
jmp pfd_check_bus
|
||||
|
||||
pfd_not_multi_function:
|
||||
andw $0xfff8, %bx /* remove function bits */
|
||||
addw $0x0008, %bx /* next device, overflows in to bus number */
|
||||
pfd_check_bus:
|
||||
cs movb pci_last_bus, %ah
|
||||
cmpb %ah, %bh
|
||||
ja pfd_not_found
|
||||
jmp pfd_loop
|
||||
pfd_found_one:
|
||||
decw %si
|
||||
js pfd_done
|
||||
jmp pfd_next_dev
|
||||
|
||||
pfd_done:
|
||||
gs movw %bx, OFFS_BX(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
pfd_not_found:
|
||||
movb $0x86, %ah /* device not found */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_find_class:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_find_class
|
||||
#endif
|
||||
gs movl OFFS_ECX(%bp), %edi
|
||||
andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
|
||||
gs movw OFFS_SI(%bp), %si
|
||||
xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
|
||||
pfc_loop:
|
||||
movw $8, %ax /* dword 8 is class-code high 24bits */
|
||||
call __pci_bios_select_register
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
shrl $8, %eax
|
||||
andl $0x00ffffff, %eax
|
||||
cmpl %edi, %eax /* our device ? */
|
||||
je pfc_found_one
|
||||
pfc_next_dev:
|
||||
/* check for multi function devices */
|
||||
andw $3, %bx
|
||||
jnz pfc_function_not_zero
|
||||
movw $0x000c, %ax
|
||||
call __pci_bios_select_register
|
||||
movw $0xcfe, %dx
|
||||
inb %dx, %al
|
||||
andb $0x80, %al
|
||||
jz pfc_not_multi_function
|
||||
pfc_function_not_zero:
|
||||
incw %bx /* next function, overflows in to
|
||||
* device number, then bus number */
|
||||
jmp pfc_check_bus
|
||||
|
||||
pfc_not_multi_function:
|
||||
andw $0xfff8, %bx /* remove function bits */
|
||||
addw $0x0008, %bx /* next device, overflows in to bus number */
|
||||
pfc_check_bus:
|
||||
cs movb pci_last_bus, %ah
|
||||
cmpb %ah, %bh
|
||||
ja pfc_not_found
|
||||
jmp pfc_loop
|
||||
pfc_found_one:
|
||||
decw %si
|
||||
js pfc_done
|
||||
jmp pfc_next_dev
|
||||
|
||||
pfc_done:
|
||||
gs movw %bx, OFFS_BX(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
pfc_not_found:
|
||||
movb $0x86, %ah /* device not found */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_generate_special_cycle:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_generate_special_cycle
|
||||
#endif
|
||||
movb $0x81, %ah /* function not supported */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_read_cfg_byte:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_read_cfg_byte
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
gs movw OFFS_DI(%bp), %dx
|
||||
andw $3, %dx
|
||||
addw $0xcfc, %dx
|
||||
inb %dx, %al
|
||||
gs movb %al, OFFS_CL(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_read_cfg_word:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_read_cfg_word
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
gs movw OFFS_DI(%bp), %dx
|
||||
andw $2, %dx
|
||||
addw $0xcfc, %dx
|
||||
inw %dx, %ax
|
||||
gs movw %ax, OFFS_CX(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_read_cfg_dword:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_read_cfg_dword
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
movw $0xcfc, %dx
|
||||
inl %dx, %eax
|
||||
gs movl %eax, OFFS_ECX(%bp)
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_write_cfg_byte:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_write_cfg_byte
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
gs movw OFFS_DI(%bp), %dx
|
||||
gs movb OFFS_CL(%bp), %al
|
||||
andw $3, %dx
|
||||
addw $0xcfc, %dx
|
||||
outb %al, %dx
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_write_cfg_word:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_write_cfg_word
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
gs movw OFFS_DI(%bp), %dx
|
||||
gs movw OFFS_CX(%bp), %ax
|
||||
andw $2, %dx
|
||||
addw $0xcfc, %dx
|
||||
outw %ax, %dx
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_write_cfg_dword:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_write_cfg_dword
|
||||
#endif
|
||||
call pci_bios_select_register
|
||||
gs movl OFFS_ECX(%bp), %eax
|
||||
movw $0xcfc, %dx
|
||||
outl %eax, %dx
|
||||
jmp clear_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_get_irq_routing:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_get_irq_routing
|
||||
#endif
|
||||
movb $0x81, %ah /* function not supported */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_set_irq:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_set_irq
|
||||
#endif
|
||||
movb $0x81, %ah /* function not supported */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
unknown_function:
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
cs incl num_pci_bios_unknown_function
|
||||
#endif
|
||||
movb $0x81, %ah /* function not supported */
|
||||
jmp set_carry
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
pci_bios_select_register:
|
||||
gs movw OFFS_BX(%bp), %bx
|
||||
gs movw OFFS_DI(%bp), %ax
|
||||
/* destroys eax, dx */
|
||||
__pci_bios_select_register: /* BX holds device id, AX holds register index */
|
||||
pushl %ebx
|
||||
andl $0xfc, %eax
|
||||
andl $0xffff, %ebx
|
||||
shll $8, %ebx
|
||||
orl %ebx, %eax
|
||||
orl $0x80000000, %eax
|
||||
movw $0xcf8, %dx
|
||||
outl %eax, %dx
|
||||
popl %ebx
|
||||
ret
|
||||
|
||||
|
||||
clear_carry:
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
andw $0xfffe, %ax /* clear carry -- function succeeded */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
xorw %ax, %ax
|
||||
gs movb %ah, OFFS_AH(%bp)
|
||||
ret
|
||||
|
||||
set_carry:
|
||||
gs movb %ah, OFFS_AH(%bp)
|
||||
gs movw OFFS_FLAGS(%bp), %ax
|
||||
orw $1, %ax /* return carry -- function not supported */
|
||||
gs movw %ax, OFFS_FLAGS(%bp)
|
||||
movw $-1, %ax
|
||||
ret
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
.globl pci_last_bus
|
||||
pci_last_bus:
|
||||
.byte 0
|
||||
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
.globl num_pci_bios_present
|
||||
num_pci_bios_present:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_find_device
|
||||
num_pci_bios_find_device:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_find_class
|
||||
num_pci_bios_find_class:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_generate_special_cycle
|
||||
num_pci_bios_generate_special_cycle:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_byte
|
||||
num_pci_bios_read_cfg_byte:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_word
|
||||
num_pci_bios_read_cfg_word:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_read_cfg_dword
|
||||
num_pci_bios_read_cfg_dword:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_byte
|
||||
num_pci_bios_write_cfg_byte:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_word
|
||||
num_pci_bios_write_cfg_word:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_write_cfg_dword
|
||||
num_pci_bios_write_cfg_dword:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_get_irq_routing
|
||||
num_pci_bios_get_irq_routing:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_set_irq
|
||||
num_pci_bios_set_irq:
|
||||
.long 0
|
||||
|
||||
.globl num_pci_bios_unknown_function
|
||||
num_pci_bios_unknown_function:
|
||||
.long 0
|
||||
#endif
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Partly based on msbios.c from rolo 1.6:
|
||||
*----------------------------------------------------------------------
|
||||
* (C) Copyright 2000
|
||||
* Sysgo Real-Time Solutions GmbH
|
||||
* Klein-Winternheim, Germany
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define NUMVECTS 256
|
||||
|
||||
#define BIOS_DATA ((char*)0x400)
|
||||
#define BIOS_DATA_SIZE 256
|
||||
#define BIOS_BASE ((char*)0xf0000)
|
||||
#define BIOS_CS 0xf000
|
||||
|
||||
/* these are defined in a 16bit segment and needs
|
||||
* to be accessed with the RELOC_16_xxxx() macros below
|
||||
*/
|
||||
extern u16 ram_in_64kb_chunks;
|
||||
extern u16 bios_equipment;
|
||||
extern u8 pci_last_bus;
|
||||
|
||||
extern void *rm_int00;
|
||||
extern void *rm_int01;
|
||||
extern void *rm_int02;
|
||||
extern void *rm_int03;
|
||||
extern void *rm_int04;
|
||||
extern void *rm_int05;
|
||||
extern void *rm_int06;
|
||||
extern void *rm_int07;
|
||||
extern void *rm_int08;
|
||||
extern void *rm_int09;
|
||||
extern void *rm_int0a;
|
||||
extern void *rm_int0b;
|
||||
extern void *rm_int0c;
|
||||
extern void *rm_int0d;
|
||||
extern void *rm_int0e;
|
||||
extern void *rm_int0f;
|
||||
extern void *rm_int10;
|
||||
extern void *rm_int11;
|
||||
extern void *rm_int12;
|
||||
extern void *rm_int13;
|
||||
extern void *rm_int14;
|
||||
extern void *rm_int15;
|
||||
extern void *rm_int16;
|
||||
extern void *rm_int17;
|
||||
extern void *rm_int18;
|
||||
extern void *rm_int19;
|
||||
extern void *rm_int1a;
|
||||
extern void *rm_int1b;
|
||||
extern void *rm_int1c;
|
||||
extern void *rm_int1d;
|
||||
extern void *rm_int1e;
|
||||
extern void *rm_int1f;
|
||||
extern void *rm_def_int;
|
||||
|
||||
extern void *realmode_reset;
|
||||
extern void *realmode_pci_bios_call_entry;
|
||||
|
||||
static int set_jmp_vector(int entry_point, void *target)
|
||||
{
|
||||
if (entry_point & ~0xffff) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((u32)target-0xf0000) & ~0xffff) {
|
||||
return -1;
|
||||
}
|
||||
printf("set_jmp_vector: 0xf000:%04x -> %p\n",
|
||||
entry_point, target);
|
||||
|
||||
/* jmp opcode */
|
||||
writeb(0xea, 0xf0000 + entry_point);
|
||||
|
||||
/* offset */
|
||||
writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1);
|
||||
|
||||
/* segment */
|
||||
writew(0xf000, 0xf0000 + entry_point + 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
************************************************************
|
||||
* Install an interrupt vector
|
||||
************************************************************
|
||||
*/
|
||||
|
||||
static void setvector(int vector, u16 segment, void *handler)
|
||||
{
|
||||
u16 *ptr = (u16*)(vector*4);
|
||||
ptr[0] = ((u32)handler - (segment << 4))&0xffff;
|
||||
ptr[1] = segment;
|
||||
|
||||
}
|
||||
|
||||
#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off)
|
||||
#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off)
|
||||
#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off)
|
||||
|
||||
int bios_setup(void)
|
||||
{
|
||||
static int done=0;
|
||||
int vector;
|
||||
struct pci_controller *pri_hose;
|
||||
|
||||
if (done) {
|
||||
return 0;
|
||||
}
|
||||
done = 1;
|
||||
|
||||
if (i386boot_bios_size > 65536) {
|
||||
printf("BIOS too large (%ld bytes, max is 65536)\n",
|
||||
i386boot_bios_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(BIOS_BASE, (void*)i386boot_bios, i386boot_bios_size);
|
||||
|
||||
/* clear bda */
|
||||
memset(BIOS_DATA, 0, BIOS_DATA_SIZE);
|
||||
|
||||
/* enter some values to the bda */
|
||||
writew(0x3f8, BIOS_DATA); /* com1 addr */
|
||||
writew(0x2f8, BIOS_DATA+2); /* com2 addr */
|
||||
writew(0x3e8, BIOS_DATA+4); /* com3 addr */
|
||||
writew(0x2e8, BIOS_DATA+6); /* com4 addr */
|
||||
writew(0x278, BIOS_DATA+8); /* lpt1 addr */
|
||||
/*
|
||||
* The kernel wants to read the base memory size
|
||||
* from 40:13. Put a zero there to avoid an error message
|
||||
*/
|
||||
writew(0, BIOS_DATA+0x13); /* base memory size */
|
||||
|
||||
|
||||
/* setup realmode interrupt vectors */
|
||||
for (vector = 0; vector < NUMVECTS; vector++) {
|
||||
setvector(vector, BIOS_CS, &rm_def_int);
|
||||
}
|
||||
|
||||
setvector(0x00, BIOS_CS, &rm_int00);
|
||||
setvector(0x01, BIOS_CS, &rm_int01);
|
||||
setvector(0x02, BIOS_CS, &rm_int02);
|
||||
setvector(0x03, BIOS_CS, &rm_int03);
|
||||
setvector(0x04, BIOS_CS, &rm_int04);
|
||||
setvector(0x05, BIOS_CS, &rm_int05);
|
||||
setvector(0x06, BIOS_CS, &rm_int06);
|
||||
setvector(0x07, BIOS_CS, &rm_int07);
|
||||
setvector(0x08, BIOS_CS, &rm_int08);
|
||||
setvector(0x09, BIOS_CS, &rm_int09);
|
||||
setvector(0x0a, BIOS_CS, &rm_int0a);
|
||||
setvector(0x0b, BIOS_CS, &rm_int0b);
|
||||
setvector(0x0c, BIOS_CS, &rm_int0c);
|
||||
setvector(0x0d, BIOS_CS, &rm_int0d);
|
||||
setvector(0x0e, BIOS_CS, &rm_int0e);
|
||||
setvector(0x0f, BIOS_CS, &rm_int0f);
|
||||
setvector(0x10, BIOS_CS, &rm_int10);
|
||||
setvector(0x11, BIOS_CS, &rm_int11);
|
||||
setvector(0x12, BIOS_CS, &rm_int12);
|
||||
setvector(0x13, BIOS_CS, &rm_int13);
|
||||
setvector(0x14, BIOS_CS, &rm_int14);
|
||||
setvector(0x15, BIOS_CS, &rm_int15);
|
||||
setvector(0x16, BIOS_CS, &rm_int16);
|
||||
setvector(0x17, BIOS_CS, &rm_int17);
|
||||
setvector(0x18, BIOS_CS, &rm_int18);
|
||||
setvector(0x19, BIOS_CS, &rm_int19);
|
||||
setvector(0x1a, BIOS_CS, &rm_int1a);
|
||||
setvector(0x1b, BIOS_CS, &rm_int1b);
|
||||
setvector(0x1c, BIOS_CS, &rm_int1c);
|
||||
setvector(0x1d, BIOS_CS, &rm_int1d);
|
||||
setvector(0x1e, BIOS_CS, &rm_int1e);
|
||||
setvector(0x1f, BIOS_CS, &rm_int1f);
|
||||
|
||||
set_jmp_vector(0xfff0, &realmode_reset);
|
||||
set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry);
|
||||
|
||||
/* fill in data area */
|
||||
RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16;
|
||||
RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */
|
||||
|
||||
/* If we assume only one PCI hose, this PCI hose
|
||||
* will own PCI bus #0, and the last PCI bus of
|
||||
* that PCI hose will be the last PCI bus in the
|
||||
* system.
|
||||
* (This, ofcause break on multi hose systems,
|
||||
* but our PCI BIOS only support one hose anyway)
|
||||
*/
|
||||
pri_hose = pci_bus_to_hose(0);
|
||||
if (NULL != pri_hose) {
|
||||
/* fill in last pci bus number for use by the realmode
|
||||
* PCI BIOS */
|
||||
RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
423
lib_i386/board.c
423
lib_i386/board.c
|
@ -1,423 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <devices.h>
|
||||
#include <version.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <ide.h>
|
||||
#include <asm/u-boot-i386.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
extern long _i386boot_start;
|
||||
extern long _i386boot_end;
|
||||
extern long _i386boot_romdata_start;
|
||||
extern long _i386boot_romdata_dest;
|
||||
extern long _i386boot_romdata_size;
|
||||
extern long _i386boot_bss_start;
|
||||
extern long _i386boot_bss_size;
|
||||
|
||||
extern long _i386boot_realmode;
|
||||
extern long _i386boot_realmode_size;
|
||||
extern long _i386boot_bios;
|
||||
extern long _i386boot_bios_size;
|
||||
|
||||
/* The symbols defined by the linker script becomes pointers
|
||||
* which is somewhat inconveient ... */
|
||||
ulong i386boot_start = (ulong)&_i386boot_start; /* code start (in flash) defined in start.S */
|
||||
ulong i386boot_end = (ulong)&_i386boot_end; /* code end (in flash) */
|
||||
ulong i386boot_romdata_start = (ulong)&_i386boot_romdata_start; /* datasegment in flash (also code+rodata end) */
|
||||
ulong i386boot_romdata_dest = (ulong)&_i386boot_romdata_dest; /* data location segment in ram */
|
||||
ulong i386boot_romdata_size = (ulong)&_i386boot_romdata_size; /* size of data segment */
|
||||
ulong i386boot_bss_start = (ulong)&_i386boot_bss_start; /* bss start */
|
||||
ulong i386boot_bss_size = (ulong)&_i386boot_bss_size; /* bss size */
|
||||
|
||||
ulong i386boot_realmode = (ulong)&_i386boot_realmode; /* start of realmode entry code */
|
||||
ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* size of realmode entry code */
|
||||
ulong i386boot_bios = (ulong)&_i386boot_bios; /* start of BIOS emulation code */
|
||||
ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; /* size of BIOS emulation code */
|
||||
|
||||
|
||||
const char version_string[] =
|
||||
U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
|
||||
|
||||
|
||||
/*
|
||||
* Begin and End of memory area for malloc(), and current "brk"
|
||||
*/
|
||||
static ulong mem_malloc_start = 0;
|
||||
static ulong mem_malloc_end = 0;
|
||||
static ulong mem_malloc_brk = 0;
|
||||
|
||||
static int mem_malloc_init(void)
|
||||
{
|
||||
/* start malloc area right after the stack */
|
||||
mem_malloc_start = i386boot_bss_start +
|
||||
i386boot_bss_size + CFG_STACK_SIZE;
|
||||
mem_malloc_start = (mem_malloc_start+3)&~3;
|
||||
|
||||
/* Use all available RAM for malloc() */
|
||||
mem_malloc_end = gd->ram_size;
|
||||
|
||||
mem_malloc_brk = mem_malloc_start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sbrk (ptrdiff_t increment)
|
||||
{
|
||||
ulong old = mem_malloc_brk;
|
||||
ulong new = old + increment;
|
||||
|
||||
if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
|
||||
return (NULL);
|
||||
}
|
||||
mem_malloc_brk = new;
|
||||
|
||||
return ((void *) old);
|
||||
}
|
||||
|
||||
char *strmhz (char *buf, long hz)
|
||||
{
|
||||
long l, n;
|
||||
long m;
|
||||
|
||||
n = hz / 1000000L;
|
||||
l = sprintf (buf, "%ld", n);
|
||||
m = (hz % 1000000L) / 1000L;
|
||||
if (m != 0)
|
||||
sprintf (buf + l, ".%03ld", m);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Init Utilities *
|
||||
************************************************************************
|
||||
* Some of this code should be moved into the core functions,
|
||||
* or dropped completely,
|
||||
* but let's get it working (again) first...
|
||||
*/
|
||||
static int init_baudrate (void)
|
||||
{
|
||||
char tmp[64]; /* long enough for environment variables */
|
||||
int i = getenv_r("baudrate", tmp, 64);
|
||||
|
||||
gd->baudrate = (i != 0)
|
||||
? (int) simple_strtoul (tmp, NULL, 10)
|
||||
: CONFIG_BAUDRATE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int display_banner (void)
|
||||
{
|
||||
|
||||
printf ("\n\n%s\n\n", version_string);
|
||||
printf ("U-Boot code: %08lX -> %08lX data: %08lX -> %08lX\n"
|
||||
" BSS: %08lX -> %08lX stack: %08lX -> %08lX\n",
|
||||
i386boot_start, i386boot_romdata_start-1,
|
||||
i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1,
|
||||
i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1,
|
||||
i386boot_bss_start+i386boot_bss_size,
|
||||
i386boot_bss_start+i386boot_bss_size+CFG_STACK_SIZE-1);
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING: this code looks "cleaner" than the PowerPC version, but
|
||||
* has the disadvantage that you either get nothing, or everything.
|
||||
* On PowerPC, you might see "DRAM: " before the system hangs - which
|
||||
* gives a simple yet clear indication which part of the
|
||||
* initialization if failing.
|
||||
*/
|
||||
static int display_dram_config (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
puts ("DRAM Configuration:\n");
|
||||
|
||||
for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
|
||||
printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
|
||||
print_size (gd->bd->bi_dram[i].size, "\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void display_flash_config (ulong size)
|
||||
{
|
||||
puts ("Flash: ");
|
||||
print_size (size, "\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Breath some life into the board...
|
||||
*
|
||||
* Initialize an SMC for serial comms, and carry out some hardware
|
||||
* tests.
|
||||
*
|
||||
* The first part of initialization is running from Flash memory;
|
||||
* its main purpose is to initialize the RAM so that we
|
||||
* can relocate the monitor code to RAM.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All attempts to come up with a "common" initialization sequence
|
||||
* that works for all boards and architectures failed: some of the
|
||||
* requirements are just _too_ different. To get rid of the resulting
|
||||
* mess of board dependend #ifdef'ed code we now make the whole
|
||||
* initialization sequence configurable to the user.
|
||||
*
|
||||
* The requirements for any new initalization function is simple: it
|
||||
* receives a pointer to the "global data" structure as it's only
|
||||
* argument, and returns an integer return code, where 0 means
|
||||
* "continue" and != 0 means "fatal error, hang the system".
|
||||
*/
|
||||
typedef int (init_fnc_t) (void);
|
||||
|
||||
init_fnc_t *init_sequence[] = {
|
||||
cpu_init, /* basic cpu dependent setup */
|
||||
board_init, /* basic board dependent setup */
|
||||
dram_init, /* configure available RAM banks */
|
||||
mem_malloc_init, /* dependant on dram_init */
|
||||
interrupt_init, /* set up exceptions */
|
||||
timer_init,
|
||||
serial_init,
|
||||
env_init, /* initialize environment */
|
||||
init_baudrate, /* initialze baudrate settings */
|
||||
serial_init, /* serial communications setup */
|
||||
display_banner,
|
||||
display_dram_config,
|
||||
|
||||
NULL,
|
||||
};
|
||||
|
||||
gd_t *global_data;
|
||||
|
||||
void start_i386boot (void)
|
||||
{
|
||||
char *s;
|
||||
int i;
|
||||
ulong size;
|
||||
static gd_t gd_data;
|
||||
static bd_t bd_data;
|
||||
init_fnc_t **init_fnc_ptr;
|
||||
|
||||
show_boot_progress(0x21);
|
||||
|
||||
gd = global_data = &gd_data;
|
||||
/* compiler optimization barrier needed for GCC >= 3.4 */
|
||||
__asm__ __volatile__("": : :"memory");
|
||||
|
||||
memset (gd, 0, sizeof (gd_t));
|
||||
gd->bd = &bd_data;
|
||||
memset (gd->bd, 0, sizeof (bd_t));
|
||||
show_boot_progress(0x22);
|
||||
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
|
||||
for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) {
|
||||
show_boot_progress(0xa130|i);
|
||||
|
||||
if ((*init_fnc_ptr)() != 0) {
|
||||
hang ();
|
||||
}
|
||||
}
|
||||
show_boot_progress(0x23);
|
||||
|
||||
/* configure available FLASH banks */
|
||||
size = flash_init();
|
||||
display_flash_config(size);
|
||||
show_boot_progress(0x24);
|
||||
|
||||
show_boot_progress(0x25);
|
||||
|
||||
/* initialize environment */
|
||||
env_relocate ();
|
||||
show_boot_progress(0x26);
|
||||
|
||||
|
||||
/* IP Address */
|
||||
bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
|
||||
|
||||
/* MAC Address */
|
||||
{
|
||||
int i;
|
||||
ulong reg;
|
||||
char *s, *e;
|
||||
uchar tmp[64];
|
||||
|
||||
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
|
||||
s = (i > 0) ? tmp : NULL;
|
||||
|
||||
for (reg = 0; reg < 6; ++reg) {
|
||||
bd_data.bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
|
||||
if (s)
|
||||
s = (*e) ? e + 1 : e;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
/*
|
||||
* Do pci configuration
|
||||
*/
|
||||
pci_init();
|
||||
#endif
|
||||
|
||||
show_boot_progress(0x27);
|
||||
|
||||
|
||||
devices_init ();
|
||||
|
||||
jumptable_init ();
|
||||
|
||||
/* Initialize the console (after the relocation and devices init) */
|
||||
console_init_r();
|
||||
|
||||
#ifdef CONFIG_MISC_INIT_R
|
||||
/* miscellaneous platform dependent initialisations */
|
||||
misc_init_r();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && !(CONFIG_COMMANDS & CFG_CMD_IDE)
|
||||
WATCHDOG_RESET();
|
||||
puts ("PCMCIA:");
|
||||
pcmcia_init();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
WATCHDOG_RESET();
|
||||
puts("KGDB: ");
|
||||
kgdb_init();
|
||||
#endif
|
||||
|
||||
/* enable exceptions */
|
||||
enable_interrupts();
|
||||
show_boot_progress(0x28);
|
||||
|
||||
/* Must happen after interrupts are initialized since
|
||||
* an irq handler gets installed
|
||||
*/
|
||||
#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
|
||||
serial_buffered_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STATUS_LED
|
||||
status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
|
||||
#endif
|
||||
|
||||
udelay(20);
|
||||
|
||||
set_timer (0);
|
||||
|
||||
/* Initialize from environment */
|
||||
if ((s = getenv ("loadaddr")) != NULL) {
|
||||
load_addr = simple_strtoul (s, NULL, 16);
|
||||
}
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
if ((s = getenv ("bootfile")) != NULL) {
|
||||
copy_filename (BootFile, s, sizeof (BootFile));
|
||||
}
|
||||
#endif /* CFG_CMD_NET */
|
||||
|
||||
WATCHDOG_RESET();
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IDE)
|
||||
WATCHDOG_RESET();
|
||||
puts("IDE: ");
|
||||
ide_init();
|
||||
#endif /* CFG_CMD_IDE */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
|
||||
WATCHDOG_RESET();
|
||||
puts("SCSI: ");
|
||||
scsi_init();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DOC)
|
||||
WATCHDOG_RESET();
|
||||
puts("DOC: ");
|
||||
doc_init();
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#if defined(CONFIG_NET_MULTI)
|
||||
WATCHDOG_RESET();
|
||||
puts("Net: ");
|
||||
#endif
|
||||
eth_initialize(gd->bd);
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET) && (0)
|
||||
WATCHDOG_RESET();
|
||||
# ifdef DEBUG
|
||||
puts ("Reset Ethernet PHY\n");
|
||||
# endif
|
||||
reset_phy();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LAST_STAGE_INIT
|
||||
WATCHDOG_RESET();
|
||||
/*
|
||||
* Some parts can be only initialized if all others (like
|
||||
* Interrupts) are up and running (i.e. the PC-style ISA
|
||||
* keyboard).
|
||||
*/
|
||||
last_stage_init();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_POST
|
||||
post_run (NULL, POST_RAM | post_bootmode_get(0));
|
||||
#endif
|
||||
|
||||
|
||||
show_boot_progress(0x29);
|
||||
|
||||
/* main_loop() can return to retry autoboot, if so just run it again. */
|
||||
for (;;) {
|
||||
main_loop();
|
||||
}
|
||||
|
||||
/* NOTREACHED - no way out of command loop except booting */
|
||||
}
|
||||
|
||||
void hang (void)
|
||||
{
|
||||
puts ("### ERROR ### Please RESET the board ###\n");
|
||||
for (;;);
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Marius Groeger <mgroeger@sysgo.de>
|
||||
*
|
||||
* Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <zlib.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/zimage.h>
|
||||
|
||||
/*cmd_boot.c*/
|
||||
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||
|
||||
extern image_header_t header; /* from cmd_bootm.c */
|
||||
|
||||
|
||||
image_header_t *fake_header(image_header_t *hdr, void *ptr, int size)
|
||||
{
|
||||
/* try each supported image type in order */
|
||||
if (NULL != fake_zimage_header(hdr, ptr, size)) {
|
||||
return hdr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
|
||||
ulong addr, ulong *len_ptr, int verify)
|
||||
{
|
||||
void *base_ptr;
|
||||
|
||||
ulong len = 0, checksum;
|
||||
ulong initrd_start, initrd_end;
|
||||
ulong data;
|
||||
image_header_t *hdr = &header;
|
||||
|
||||
/*
|
||||
* Check if there is an initrd image
|
||||
*/
|
||||
if (argc >= 3) {
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memcpy (&header, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf ("Bad Magic Number\n");
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
data = (ulong)&header;
|
||||
len = sizeof(image_header_t);
|
||||
|
||||
checksum = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (char *)data, len) != checksum) {
|
||||
printf ("Bad Header Checksum\n");
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
print_image_hdr (hdr);
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = ntohl(hdr->ih_size);
|
||||
|
||||
if (verify) {
|
||||
ulong csum = 0;
|
||||
|
||||
printf (" Verifying Checksum ... ");
|
||||
csum = crc32 (0, (char *)data, len);
|
||||
if (csum != ntohl(hdr->ih_dcrc)) {
|
||||
printf ("Bad Data CRC\n");
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
printf ("OK\n");
|
||||
}
|
||||
|
||||
if ((hdr->ih_os != IH_OS_LINUX) ||
|
||||
(hdr->ih_arch != IH_CPU_I386) ||
|
||||
(hdr->ih_type != IH_TYPE_RAMDISK) ) {
|
||||
printf ("No Linux i386 Ramdisk Image\n");
|
||||
do_reset (cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check if we have a multifile image
|
||||
*/
|
||||
} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
|
||||
ulong tail = ntohl(len_ptr[0]) % 4;
|
||||
int i;
|
||||
|
||||
/* skip kernel length and terminator */
|
||||
data = (ulong)(&len_ptr[2]);
|
||||
/* skip any additional image length fields */
|
||||
for (i=1; len_ptr[i]; ++i)
|
||||
data += 4;
|
||||
/* add kernel length, and align */
|
||||
data += ntohl(len_ptr[0]);
|
||||
if (tail) {
|
||||
data += 4 - tail;
|
||||
}
|
||||
|
||||
len = ntohl(len_ptr[1]);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* no initrd image
|
||||
*/
|
||||
data = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!data) {
|
||||
printf ("No initrd\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data) {
|
||||
initrd_start = data;
|
||||
initrd_end = initrd_start + len;
|
||||
printf (" Loading Ramdisk to %08lx, end %08lx ... ",
|
||||
initrd_start, initrd_end);
|
||||
memmove ((void *)initrd_start, (void *)data, len);
|
||||
printf ("OK\n");
|
||||
} else {
|
||||
initrd_start = 0;
|
||||
initrd_end = 0;
|
||||
}
|
||||
|
||||
/* if multi-part image, we need to advance base ptr */
|
||||
if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
|
||||
int i;
|
||||
for (i=0, addr+=sizeof(int); len_ptr[i++]; addr+=sizeof(int));
|
||||
}
|
||||
|
||||
base_ptr = load_zimage((void*)addr + sizeof(image_header_t), ntohl(hdr->ih_size),
|
||||
initrd_start, initrd_end-initrd_start, 0);
|
||||
|
||||
if (NULL == base_ptr) {
|
||||
printf ("## Kernel loading failed ...\n");
|
||||
do_reset(cmdtp, flag, argc, argv);
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("## Transferring control to Linux (at address %08x) ...\n",
|
||||
(u32)base_ptr);
|
||||
#endif
|
||||
|
||||
/* we assume that the kernel is in place */
|
||||
printf("\nStarting kernel ...\n\n");
|
||||
|
||||
boot_zimage(base_ptr);
|
||||
|
||||
}
|
141
lib_i386/pci.c
141
lib_i386/pci.c
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pci.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#undef PCI_ROM_SCAN_VERBOSE
|
||||
|
||||
int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
|
||||
{
|
||||
struct pci_controller *hose;
|
||||
int res = -1;
|
||||
int i;
|
||||
|
||||
u32 rom_addr;
|
||||
u32 addr_reg;
|
||||
u32 size;
|
||||
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
u32 class_code;
|
||||
|
||||
hose = pci_bus_to_hose(PCI_BUS(dev));
|
||||
pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
|
||||
pci_read_config_word(dev, PCI_DEVICE_ID, &device);
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
|
||||
|
||||
class_code &= 0xffffff00;
|
||||
class_code >>= 8;
|
||||
|
||||
/* Enable the rom addess decoder */
|
||||
pci_write_config_dword(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
|
||||
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
|
||||
|
||||
if (!addr_reg) {
|
||||
/* register unimplemented */
|
||||
printf("pci_chadow_rom: device do not seem to have a rom\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;
|
||||
|
||||
rom_addr = pci_get_rom_window(hose, size);
|
||||
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
|
||||
pci_phys_to_mem(dev, rom_addr)
|
||||
|PCI_ROM_ADDRESS_ENABLE);
|
||||
|
||||
|
||||
for (i=rom_addr;i<rom_addr+size; i+=512) {
|
||||
|
||||
|
||||
if (readw(i) == 0xaa55) {
|
||||
u32 pci_data;
|
||||
#ifdef PCI_ROM_SCAN_VERBOSE
|
||||
printf("ROM signature found\n");
|
||||
#endif
|
||||
pci_data = readw(0x18+i);
|
||||
pci_data += i;
|
||||
|
||||
if (0==memcmp((void*)pci_data, "PCIR", 4)) {
|
||||
#ifdef PCI_ROM_SCAN_VERBOSE
|
||||
printf("Fount PCI rom image at offset %d\n", i-rom_addr);
|
||||
printf("Vendor %04x device %04x class %06x\n",
|
||||
readw(pci_data+4), readw(pci_data+6),
|
||||
readl(pci_data+0x0d)&0xffffff);
|
||||
printf("%s\n",
|
||||
(readw(pci_data+0x15) &0x80)?
|
||||
"Last image":"More images follow");
|
||||
switch (readb(pci_data+0x14)) {
|
||||
case 0:
|
||||
printf("X86 code\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("Openfirmware code\n");
|
||||
break;
|
||||
case 2:
|
||||
printf("PARISC code\n");
|
||||
break;
|
||||
}
|
||||
printf("Image size %d\n", readw(pci_data+0x10) * 512);
|
||||
#endif
|
||||
/* FixMe: I think we should compare the class code
|
||||
* bytes as well but I have no reference on the
|
||||
* exact order of these bytes in the PCI ROM header */
|
||||
if (readw(pci_data+4) == vendor &&
|
||||
readw(pci_data+6) == device &&
|
||||
/* (readl(pci_data+0x0d)&0xffffff) == class_code && */
|
||||
readb(pci_data+0x14) == 0 /* x86 code image */ ) {
|
||||
#ifdef PCI_ROM_SCAN_VERBOSE
|
||||
printf("Suitable ROM image found, copying\n");
|
||||
#endif
|
||||
memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
|
||||
res = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
if (readw(pci_data+0x15) &0x80) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef PCI_ROM_SCAN_VERBOSE
|
||||
if (res) {
|
||||
printf("No suitable image found\n");
|
||||
}
|
||||
#endif
|
||||
/* disable PAR register and PCI device ROM address devocer */
|
||||
pci_remove_rom_window(hose, rom_addr);
|
||||
|
||||
pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Support for type PCI configuration cycles.
|
||||
* based on pci_indirect.c
|
||||
*
|
||||
* Copyright (C) 2002 Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <pci.h>
|
||||
|
||||
#define cfg_read(val, addr, op) *val = op((int)(addr))
|
||||
#define cfg_write(val, addr, op) op((val), (int)(addr))
|
||||
|
||||
#define TYPE1_PCI_OP(rw, size, type, op, mask) \
|
||||
static int \
|
||||
type1_##rw##_config_##size(struct pci_controller *hose, \
|
||||
pci_dev_t dev, int offset, type val) \
|
||||
{ \
|
||||
outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr); \
|
||||
cfg_##rw(val, hose->cfg_data + (offset & mask), op); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
TYPE1_PCI_OP(read, byte, u8 *, inb, 3)
|
||||
TYPE1_PCI_OP(read, word, u16 *, inw, 2)
|
||||
TYPE1_PCI_OP(read, dword, u32 *, inl, 0)
|
||||
|
||||
TYPE1_PCI_OP(write, byte, u8, outb, 3)
|
||||
TYPE1_PCI_OP(write, word, u16, outw, 2)
|
||||
TYPE1_PCI_OP(write, dword, u32, outl, 0)
|
||||
|
||||
void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
|
||||
{
|
||||
pci_set_ops(hose,
|
||||
type1_read_config_byte,
|
||||
type1_read_config_word,
|
||||
type1_read_config_dword,
|
||||
type1_write_config_byte,
|
||||
type1_write_config_word,
|
||||
type1_write_config_dword);
|
||||
|
||||
hose->cfg_addr = (unsigned int *) cfg_addr;
|
||||
hose->cfg_data = (unsigned char *) cfg_data;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/realmode.h>
|
||||
|
||||
|
||||
#define REALMODE_BASE ((char*)0x7c0)
|
||||
#define REALMODE_MAILBOX ((char*)0xe00)
|
||||
|
||||
|
||||
extern char realmode_enter;
|
||||
|
||||
int realmode_setup(void)
|
||||
{
|
||||
/* copy the realmode switch code */
|
||||
if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) {
|
||||
printf("realmode switch too large (%ld bytes, max is %d)\n",
|
||||
i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size);
|
||||
asm("wbinvd\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
|
||||
{
|
||||
|
||||
/* setup out thin bios emulation */
|
||||
if (bios_setup()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (realmode_setup()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
in->eip = off;
|
||||
in->xcs = seg;
|
||||
if (3>(in->esp & 0xffff)) {
|
||||
printf("Warning: entering realmode with sp < 4 will fail\n");
|
||||
}
|
||||
|
||||
memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
|
||||
asm("wbinvd\n");
|
||||
|
||||
__asm__ volatile (
|
||||
"lcall $0x20,%0\n" : : "i" (&realmode_enter) );
|
||||
|
||||
asm("wbinvd\n");
|
||||
memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
|
||||
|
||||
return out->eax;
|
||||
}
|
||||
|
||||
|
||||
/* This code is supposed to access a realmode interrupt
|
||||
* it does currently not work for me */
|
||||
int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
|
||||
{
|
||||
/* place two instructions at 0x700 */
|
||||
writeb(0xcd, 0x700); /* int $lvl */
|
||||
writeb(lvl, 0x701);
|
||||
writeb(0xcb, 0x702); /* lret */
|
||||
asm("wbinvd\n");
|
||||
|
||||
enter_realmode(0x00, 0x700, in, out);
|
||||
|
||||
return out->eflags&1;
|
||||
}
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* 32bit -> 16bit -> 32bit mode switch code */
|
||||
|
||||
/*
|
||||
* Stack frame at 0xe00
|
||||
* e00 ebx;
|
||||
* e04 ecx;
|
||||
* e08 edx;
|
||||
* e0c esi;
|
||||
* e10 edi;
|
||||
* e14 ebp;
|
||||
* e18 eax;
|
||||
* e1c ds;
|
||||
* e20 es;
|
||||
* e24 fs;
|
||||
* e28 gs;
|
||||
* e2c orig_eax;
|
||||
* e30 eip;
|
||||
* e34 cs;
|
||||
* e38 eflags;
|
||||
* e3c esp;
|
||||
* e40 ss;
|
||||
*/
|
||||
|
||||
#define a32 .byte 0x67; /* address size prefix 32 */
|
||||
#define o32 .byte 0x66; /* operand size prefix 32 */
|
||||
|
||||
.section .realmode, "ax"
|
||||
.code16
|
||||
/* 16bit protected mode code here */
|
||||
.globl realmode_enter
|
||||
realmode_enter:
|
||||
o32 pusha
|
||||
o32 pushf
|
||||
cli
|
||||
sidt saved_idt
|
||||
sgdt saved_gdt
|
||||
movl %esp, %eax
|
||||
movl %eax, saved_protected_mode_esp
|
||||
|
||||
movl $0x10, %eax
|
||||
movl %eax, %esp
|
||||
movw $0x28, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
lidt realmode_idt_ptr
|
||||
movl %cr0, %eax /* Go back into real mode by */
|
||||
andl $0x7ffffffe, %eax /* clearing PE to 0 */
|
||||
movl %eax, %cr0
|
||||
ljmp $0x0,$do_realmode /* switch to real mode */
|
||||
|
||||
do_realmode: /* realmode code from here */
|
||||
movw %cs,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
|
||||
/* create a temporary stack */
|
||||
|
||||
movw $0xc0, %ax
|
||||
movw %ax, %ss
|
||||
movw $0x200, %ax
|
||||
movw %ax, %sp
|
||||
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %eax
|
||||
movl %eax, temp_eax
|
||||
popl %eax
|
||||
movw %ax, %ds
|
||||
popl %eax
|
||||
movw %ax, %es
|
||||
popl %eax
|
||||
movw %ax, %fs
|
||||
popl %eax
|
||||
movw %ax, %gs
|
||||
popl %eax /* orig_eax */
|
||||
popl %eax
|
||||
cs movw %ax, temp_ip
|
||||
popl %eax
|
||||
cs movw %ax, temp_cs
|
||||
o32 popf
|
||||
popl %eax
|
||||
popw %ss
|
||||
movl %eax, %esp
|
||||
cs movl temp_eax, %eax
|
||||
wbinvd /* self-modifying code,
|
||||
* better flush the cache */
|
||||
|
||||
.byte 0x9a /* lcall */
|
||||
temp_ip:
|
||||
.word 0 /* new ip */
|
||||
temp_cs:
|
||||
.word 0 /* new cs */
|
||||
realmode_ret:
|
||||
/* save eax, esp and ss */
|
||||
cs movl %eax, saved_eax
|
||||
movl %esp, %eax
|
||||
cs movl %eax, saved_esp
|
||||
movw %ss, %ax
|
||||
cs movw %ax, saved_ss
|
||||
|
||||
/* restore the stack, note that we set sp to 0x244;
|
||||
* pt_regs is 0x44 bytes long and we push the structure
|
||||
* backwards on to the stack, bottom first */
|
||||
|
||||
movw $0xc0, %ax
|
||||
movw %ax, %ss
|
||||
movw $0x244, %ax
|
||||
movw %ax, %sp
|
||||
|
||||
xorl %eax,%eax
|
||||
cs movw saved_ss, %ax
|
||||
pushl %eax
|
||||
cs movl saved_esp, %eax
|
||||
pushl %eax
|
||||
o32 pushf
|
||||
xorl %eax,%eax
|
||||
cs movw temp_cs, %ax
|
||||
pushl %eax
|
||||
cs movw temp_ip, %ax
|
||||
pushl %eax
|
||||
pushl $0
|
||||
movw %gs, %ax
|
||||
pushl %eax
|
||||
movw %fs, %ax
|
||||
pushl %eax
|
||||
movw %es, %ax
|
||||
pushl %eax
|
||||
movw %ds, %ax
|
||||
pushl %eax
|
||||
movl saved_eax, %eax
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
|
||||
o32 cs lidt saved_idt
|
||||
o32 cs lgdt saved_gdt /* Set GDTR */
|
||||
|
||||
movl %cr0, %eax /* Go back into protected mode */
|
||||
orl $1,%eax /* reset PE to 1 */
|
||||
movl %eax, %cr0
|
||||
jmp next_line /* flush prefetch queue */
|
||||
next_line:
|
||||
movw $return_ptr, %ax
|
||||
movw %ax,%bp
|
||||
o32 cs ljmp *(%bp)
|
||||
|
||||
.code32
|
||||
protected_mode:
|
||||
movl $0x18,%eax /* reload GDT[3] */
|
||||
movw %ax,%fs /* reset FS */
|
||||
movw %ax,%ds /* reset DS */
|
||||
movw %ax,%gs /* reset GS */
|
||||
movw %ax,%es /* reset ES */
|
||||
movw %ax,%ss /* reset SS */
|
||||
movl saved_protected_mode_esp, %eax
|
||||
movl %eax, %esp
|
||||
popf
|
||||
popa
|
||||
ret
|
||||
|
||||
temp_eax:
|
||||
.long 0
|
||||
|
||||
saved_ss:
|
||||
.word 0
|
||||
saved_esp:
|
||||
.long 0
|
||||
saved_eax:
|
||||
.long 0
|
||||
|
||||
realmode_idt_ptr:
|
||||
.word 0x400
|
||||
.word 0x0, 0x0
|
||||
|
||||
saved_gdt:
|
||||
.word 0, 0, 0, 0
|
||||
saved_idt:
|
||||
.word 0, 0, 0, 0
|
||||
|
||||
saved_protected_mode_esp:
|
||||
.long 0
|
||||
|
||||
return_ptr:
|
||||
.long protected_mode
|
||||
.word 0x10
|
234
lib_i386/video.c
234
lib_i386/video.c
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
#include <devices.h>
|
||||
#include <i8042.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pci.h>
|
||||
|
||||
|
||||
/* basic textmode I/O from linux kernel */
|
||||
static char *vidmem = (char *)0xb8000;
|
||||
static int vidport;
|
||||
static int lines, cols;
|
||||
static int orig_x, orig_y;
|
||||
|
||||
static void beep(int dur)
|
||||
{
|
||||
int i;
|
||||
|
||||
outb_p(3, 0x61);
|
||||
for (i=0;i<10*dur;i++) {
|
||||
udelay(1000);
|
||||
}
|
||||
outb_p(0, 0x61);
|
||||
}
|
||||
|
||||
static void scroll(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
|
||||
for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
|
||||
vidmem[i] = ' ';
|
||||
}
|
||||
|
||||
static void __video_putc(const char c, int *x, int *y)
|
||||
{
|
||||
if (c == '\n') {
|
||||
(*x) = 0;
|
||||
if ( ++(*y) >= lines ) {
|
||||
scroll();
|
||||
(*y)--;
|
||||
}
|
||||
} else if (c == '\b') {
|
||||
if ((*x) != 0) {
|
||||
--(*x);
|
||||
vidmem [ ( (*x) + cols * (*y) ) * 2 ] = ' ';
|
||||
}
|
||||
} else if (c == '\r') {
|
||||
(*x) = 0;
|
||||
|
||||
} else if (c == '\a') {
|
||||
beep(3);
|
||||
|
||||
} else if (c == '\t') {
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
__video_putc(' ', x, y);
|
||||
} else if (c == '\v') {
|
||||
switch ((*x) % 8) {
|
||||
case 0:
|
||||
__video_putc(' ', x, y);
|
||||
case 7:
|
||||
__video_putc(' ', x, y);
|
||||
case 6:
|
||||
__video_putc(' ', x, y);
|
||||
case 5:
|
||||
__video_putc(' ', x, y);
|
||||
case 4:
|
||||
__video_putc(' ', x, y);
|
||||
case 3:
|
||||
__video_putc(' ', x, y);
|
||||
case 2:
|
||||
__video_putc(' ', x, y);
|
||||
case 1:
|
||||
__video_putc(' ', x, y);
|
||||
}
|
||||
} else if (c == '\f') {
|
||||
int i;
|
||||
for (i=0;i<lines*cols*2;i+=2) {
|
||||
vidmem[i] = 0;
|
||||
}
|
||||
(*x) = 0;
|
||||
(*y) = 0;
|
||||
} else {
|
||||
vidmem [ ( (*x) + cols * (*y) ) * 2 ] = c;
|
||||
if ( ++(*x) >= cols ) {
|
||||
(*x) = 0;
|
||||
if ( ++(*y) >= lines ) {
|
||||
scroll();
|
||||
(*y)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void video_putc(const char c)
|
||||
{
|
||||
int x,y,pos;
|
||||
|
||||
x = orig_x;
|
||||
y = orig_y;
|
||||
|
||||
__video_putc(c, &x, &y);
|
||||
|
||||
orig_x = x;
|
||||
orig_y = y;
|
||||
|
||||
pos = (x + cols * y) * 2; /* Update cursor position */
|
||||
outb_p(14, vidport);
|
||||
outb_p(0xff & (pos >> 9), vidport+1);
|
||||
outb_p(15, vidport);
|
||||
outb_p(0xff & (pos >> 1), vidport+1);
|
||||
}
|
||||
|
||||
static void video_puts(const char *s)
|
||||
{
|
||||
int x,y,pos;
|
||||
char c;
|
||||
|
||||
x = orig_x;
|
||||
y = orig_y;
|
||||
|
||||
while ( ( c = *s++ ) != '\0' ) {
|
||||
__video_putc(c, &x, &y);
|
||||
}
|
||||
|
||||
orig_x = x;
|
||||
orig_y = y;
|
||||
|
||||
pos = (x + cols * y) * 2; /* Update cursor position */
|
||||
outb_p(14, vidport);
|
||||
outb_p(0xff & (pos >> 9), vidport+1);
|
||||
outb_p(15, vidport);
|
||||
outb_p(0xff & (pos >> 1), vidport+1);
|
||||
}
|
||||
|
||||
int video_init(void)
|
||||
{
|
||||
u16 pos;
|
||||
|
||||
static device_t vga_dev;
|
||||
static device_t kbd_dev;
|
||||
|
||||
vidmem = (char *) 0xb8000;
|
||||
vidport = 0x3d4;
|
||||
|
||||
lines = 25;
|
||||
cols = 80;
|
||||
|
||||
outb_p(14, vidport);
|
||||
pos = inb_p(vidport+1);
|
||||
pos <<= 8;
|
||||
outb_p(15, vidport);
|
||||
pos |= inb_p(vidport+1);
|
||||
|
||||
orig_x = pos%cols;
|
||||
orig_y = pos/cols;
|
||||
|
||||
if (orig_y > lines) {
|
||||
orig_x = orig_y =0;
|
||||
}
|
||||
|
||||
|
||||
memset(&vga_dev, 0, sizeof(vga_dev));
|
||||
strcpy(vga_dev.name, "vga");
|
||||
vga_dev.ext = 0;
|
||||
vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
|
||||
vga_dev.putc = video_putc; /* 'putc' function */
|
||||
vga_dev.puts = video_puts; /* 'puts' function */
|
||||
vga_dev.tstc = NULL; /* 'tstc' function */
|
||||
vga_dev.getc = NULL; /* 'getc' function */
|
||||
|
||||
if (device_register(&vga_dev) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i8042_kbd_init()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&kbd_dev, 0, sizeof(kbd_dev));
|
||||
strcpy(kbd_dev.name, "kbd");
|
||||
kbd_dev.ext = 0;
|
||||
kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
|
||||
kbd_dev.putc = NULL; /* 'putc' function */
|
||||
kbd_dev.puts = NULL; /* 'puts' function */
|
||||
kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
|
||||
kbd_dev.getc = i8042_getc; /* 'getc' function */
|
||||
|
||||
if (device_register(&kbd_dev) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int drv_video_init(void)
|
||||
{
|
||||
if (video_bios_init()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return video_init();
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pci.h>
|
||||
|
||||
#undef PCI_BIOS_DEBUG
|
||||
#undef VGA_BIOS_DEBUG
|
||||
|
||||
#ifdef VGA_BIOS_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
|
||||
extern u32 num_pci_bios_present;
|
||||
extern u32 num_pci_bios_find_device;
|
||||
extern u32 num_pci_bios_find_class;
|
||||
extern u32 num_pci_bios_generate_special_cycle;
|
||||
extern u32 num_pci_bios_read_cfg_byte;
|
||||
extern u32 num_pci_bios_read_cfg_word;
|
||||
extern u32 num_pci_bios_read_cfg_dword;
|
||||
extern u32 num_pci_bios_write_cfg_byte;
|
||||
extern u32 num_pci_bios_write_cfg_word;
|
||||
extern u32 num_pci_bios_write_cfg_dword;
|
||||
extern u32 num_pci_bios_get_irq_routing;
|
||||
extern u32 num_pci_bios_set_irq;
|
||||
extern u32 num_pci_bios_unknown_function;
|
||||
|
||||
void print_bios_bios_stat(void)
|
||||
{
|
||||
printf("16 bit functions:\n");
|
||||
printf("pci_bios_present: %d\n", RELOC_16(0xf000, num_pci_bios_present));
|
||||
printf("pci_bios_find_device: %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
|
||||
printf("pci_bios_find_class: %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
|
||||
printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
|
||||
printf("pci_bios_read_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
|
||||
printf("pci_bios_read_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
|
||||
printf("pci_bios_read_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
|
||||
printf("pci_bios_write_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
|
||||
printf("pci_bios_write_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
|
||||
printf("pci_bios_write_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
|
||||
printf("pci_bios_get_irq_routing: %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
|
||||
printf("pci_bios_set_irq: %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
|
||||
printf("pci_bios_unknown_function: %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PCI_CLASS_VIDEO 3
|
||||
#define PCI_CLASS_VIDEO_STD 0
|
||||
#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
|
||||
|
||||
|
||||
static u32 probe_pci_video(void)
|
||||
{
|
||||
pci_dev_t devbusfn;
|
||||
|
||||
if ((devbusfn = pci_find_class(PCI_CLASS_VIDEO,
|
||||
PCI_CLASS_VIDEO_STD,
|
||||
PCI_CLASS_VIDEO_PROG_IF_VGA, 0)) != -1) {
|
||||
u32 old;
|
||||
u32 addr;
|
||||
|
||||
/* PCI video device detected */
|
||||
printf("Found PCI VGA device at %02x.%02x.%x\n",
|
||||
PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
|
||||
|
||||
/* Enable I/O decoding as well, PCI viudeo boards
|
||||
* support I/O accesses, but they provide no
|
||||
* bar register for this since the ports are fixed.
|
||||
*/
|
||||
pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
|
||||
|
||||
/* Test the ROM decoder, do the device support a rom? */
|
||||
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);
|
||||
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
|
||||
pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
|
||||
pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
|
||||
|
||||
if (!addr) {
|
||||
printf("PCI VGA have no ROM?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* device have a rom */
|
||||
if (pci_shadow_rom(devbusfn, (void*)0xc0000)) {
|
||||
printf("Shadowing of PCI VGA BIOS failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now enable lagacy VGA port access */
|
||||
if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
|
||||
printf("PCI VGA enable failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* return the pci device info, that we'll need later */
|
||||
return PCI_BUS(devbusfn) << 8 |
|
||||
PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static int probe_isa_video(void)
|
||||
{
|
||||
u32 ptr;
|
||||
char *buf;
|
||||
|
||||
if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
|
||||
return -1;
|
||||
}
|
||||
if (NULL == (buf=malloc(0x8000))) {
|
||||
isa_unmap_rom(ptr);
|
||||
return -1;
|
||||
}
|
||||
if (readw(ptr) != 0xaa55) {
|
||||
free(buf);
|
||||
isa_unmap_rom(ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* shadow the rom */
|
||||
memcpy(buf, (void*)ptr, 0x8000);
|
||||
isa_unmap_rom(ptr);
|
||||
memcpy((void*)0xc0000, buf, 0x8000);
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int video_bios_init(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
/* clear the video bios area in case we warmbooted */
|
||||
memset((void*)0xc0000, 0, 0x8000);
|
||||
memset(®s, 0, sizeof(struct pt_regs));
|
||||
|
||||
if (probe_isa_video()) {
|
||||
/* No ISA board found, try the PCI bus */
|
||||
regs.eax = probe_pci_video();
|
||||
}
|
||||
|
||||
/* Did we succeed in mapping any video bios */
|
||||
if (readw(0xc0000) == 0xaa55) {
|
||||
int size;
|
||||
int i;
|
||||
u8 sum;
|
||||
|
||||
PRINTF("Found video bios signature\n");
|
||||
size = 512*readb(0xc0002);
|
||||
PRINTF("size %d\n", size);
|
||||
sum=0;
|
||||
for (i=0;i<size;i++) {
|
||||
sum += readb(0xc0000 + i);
|
||||
}
|
||||
PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
|
||||
if (sum) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* some video bioses (ATI Mach64) seem to think that
|
||||
* the original int 10 handler is always at
|
||||
* 0xf000:0xf065 , place an iret instruction there
|
||||
*/
|
||||
writeb(0xcf, 0xff065);
|
||||
|
||||
regs.esp = 0x8000;
|
||||
regs.xss = 0x2000;
|
||||
enter_realmode(0xc000, 3, ®s, ®s);
|
||||
PRINTF("INT 0x10 vector after: %04x:%04x\n",
|
||||
readw(0x42), readw(0x40));
|
||||
PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
|
||||
#ifdef PCI_BIOS_DEBUG
|
||||
print_bios_bios_stat();
|
||||
#endif
|
||||
return (regs.eflags & 1);
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB, daniel@omicron.se
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Linux i386 zImage and bzImage loading
|
||||
*
|
||||
* based on the procdure described in
|
||||
* linux/Documentation/i386/boot.txt
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/zimage.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/*
|
||||
* Memory lay-out:
|
||||
*
|
||||
* relative to setup_base (which is 0x90000 currently)
|
||||
*
|
||||
* 0x0000-0x7FFF Real mode kernel
|
||||
* 0x8000-0x8FFF Stack and heap
|
||||
* 0x9000-0x90FF Kernel command line
|
||||
*/
|
||||
#define DEFAULT_SETUP_BASE 0x90000
|
||||
#define COMMAND_LINE_OFFSET 0x9000
|
||||
#define HEAP_END_OFFSET 0x8e00
|
||||
|
||||
#define COMMAND_LINE_SIZE 2048
|
||||
|
||||
static void build_command_line(char *command_line, int auto_boot)
|
||||
{
|
||||
char *env_command_line;
|
||||
|
||||
command_line[0] = '\0';
|
||||
|
||||
env_command_line = getenv("bootargs");
|
||||
|
||||
/* set console= argument if we use a serial console */
|
||||
if (NULL == strstr(env_command_line, "console=")) {
|
||||
if (0==strcmp(getenv("stdout"), "serial")) {
|
||||
|
||||
/* We seem to use serial console */
|
||||
sprintf(command_line, "console=ttyS0,%s ",
|
||||
getenv("baudrate"));
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_boot) {
|
||||
strcat(command_line, "auto ");
|
||||
}
|
||||
|
||||
if (NULL != env_command_line) {
|
||||
strcat(command_line, env_command_line);
|
||||
}
|
||||
|
||||
|
||||
printf("Kernel command line: \"%s\"\n", command_line);
|
||||
}
|
||||
|
||||
void *load_zimage(char *image, unsigned long kernel_size,
|
||||
unsigned long initrd_addr, unsigned long initrd_size,
|
||||
int auto_boot)
|
||||
{
|
||||
void *setup_base;
|
||||
int setup_size;
|
||||
int bootproto;
|
||||
int big_image;
|
||||
void *load_address;
|
||||
|
||||
|
||||
setup_base = (void*)DEFAULT_SETUP_BASE; /* base address for real-mode segment */
|
||||
|
||||
if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) {
|
||||
printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n",
|
||||
*(u16*)(image + BOOT_FLAG_OFF));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* determine boot protocol version */
|
||||
if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) {
|
||||
bootproto = *(u16*)(image+VERSION_OFF);
|
||||
} else {
|
||||
/* Very old kernel */
|
||||
bootproto = 0x0100;
|
||||
}
|
||||
|
||||
/* determine size of setup */
|
||||
if (0 == *(u8*)(image + SETUP_SECTS_OFF)) {
|
||||
setup_size = 5 * 512;
|
||||
} else {
|
||||
setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512;
|
||||
}
|
||||
|
||||
if (setup_size > SETUP_MAX_SIZE) {
|
||||
printf("Error: Setup is too large (%d bytes)\n", setup_size);
|
||||
}
|
||||
|
||||
/* Determine image type */
|
||||
big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG);
|
||||
|
||||
/* Derermine load address */
|
||||
load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR);
|
||||
|
||||
/* load setup */
|
||||
memmove(setup_base, image, setup_size);
|
||||
|
||||
printf("Using boot protocol version %x.%02x\n",
|
||||
(bootproto & 0xff00) >> 8, bootproto & 0xff);
|
||||
|
||||
|
||||
if (bootproto == 0x0100) {
|
||||
|
||||
*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
|
||||
*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
|
||||
|
||||
/* A very old kernel MUST have its real-mode code
|
||||
* loaded at 0x90000 */
|
||||
|
||||
if ((u32)setup_base != 0x90000) {
|
||||
/* Copy the real-mode kernel */
|
||||
memmove((void*)0x90000, setup_base, setup_size);
|
||||
/* Copy the command line */
|
||||
memmove((void*)0x99000, setup_base+COMMAND_LINE_OFFSET,
|
||||
COMMAND_LINE_SIZE);
|
||||
|
||||
setup_base = (void*)0x90000; /* Relocated */
|
||||
}
|
||||
|
||||
/* It is recommended to clear memory up to the 32K mark */
|
||||
memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size);
|
||||
}
|
||||
|
||||
if (bootproto >= 0x0200) {
|
||||
*(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff;
|
||||
printf("Linux kernel version %s\n",
|
||||
(char*)(setup_base + SETUP_START_OFFSET +
|
||||
*(u16*)(setup_base + START_SYS_OFF + 2)));
|
||||
|
||||
if (initrd_addr) {
|
||||
printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n",
|
||||
initrd_addr, initrd_size);
|
||||
|
||||
*(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr;
|
||||
*(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (bootproto >= 0x0201) {
|
||||
*(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET;
|
||||
|
||||
/* CAN_USE_HEAP */
|
||||
*(u8*)(setup_base + LOADFLAGS_OFF) =
|
||||
*(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG;
|
||||
}
|
||||
|
||||
if (bootproto >= 0x0202) {
|
||||
*(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET;
|
||||
} else if (bootproto >= 0x0200) {
|
||||
*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC;
|
||||
*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
|
||||
*(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100;
|
||||
}
|
||||
|
||||
|
||||
if (big_image) {
|
||||
if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) {
|
||||
printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n",
|
||||
kernel_size - setup_size, BZIMAGE_MAX_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) {
|
||||
printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
|
||||
kernel_size - setup_size, ZIMAGE_MAX_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* build command line at COMMAND_LINE_OFFSET */
|
||||
build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot);
|
||||
|
||||
printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ',
|
||||
(u32)load_address, kernel_size - setup_size);
|
||||
|
||||
|
||||
memmove(load_address, image + setup_size, kernel_size - setup_size);
|
||||
|
||||
/* ready for booting */
|
||||
return setup_base;
|
||||
}
|
||||
|
||||
|
||||
void boot_zimage(void *setup_base)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
memset(®s, 0, sizeof(struct pt_regs));
|
||||
regs.xds = (u32)setup_base >> 4;
|
||||
regs.xss = 0x9000;
|
||||
regs.esp = 0x9000;
|
||||
regs.eflags = 0;
|
||||
enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s);
|
||||
}
|
||||
|
||||
|
||||
image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size)
|
||||
{
|
||||
/* There is no way to know the size of a zImage ... *
|
||||
* so we assume that 2MB will be enough for now */
|
||||
#define ZIMAGE_SIZE 0x200000
|
||||
|
||||
/* load a 1MB, the loaded will have to be moved to its final
|
||||
* position again later... */
|
||||
#define ZIMAGE_LOAD 0x100000
|
||||
|
||||
ulong checksum;
|
||||
|
||||
if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) {
|
||||
/* not a zImage or bzImage */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (-1 == size) {
|
||||
size = ZIMAGE_SIZE;
|
||||
}
|
||||
checksum = 0;
|
||||
memset(hdr, 0, sizeof(image_header_t));
|
||||
|
||||
/* Build new header */
|
||||
hdr->ih_magic = htonl(IH_MAGIC);
|
||||
hdr->ih_time = 0;
|
||||
hdr->ih_size = htonl(size);
|
||||
hdr->ih_load = htonl(ZIMAGE_LOAD);
|
||||
hdr->ih_ep = 0;
|
||||
hdr->ih_dcrc = htonl(checksum);
|
||||
hdr->ih_os = IH_OS_LINUX;
|
||||
hdr->ih_arch = IH_CPU_I386;
|
||||
hdr->ih_type = IH_TYPE_KERNEL;
|
||||
hdr->ih_comp = IH_COMP_NONE;
|
||||
|
||||
strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN);
|
||||
|
||||
checksum = crc32(0,(const char *)hdr,sizeof(image_header_t));
|
||||
|
||||
hdr->ih_hcrc = htonl(checksum);
|
||||
|
||||
return hdr;
|
||||
}
|
Loading…
Reference in New Issue