Substract min_addr instead of PAGE_SIZE, align kernel address on PAGE_SIZE

This commit is contained in:
Laurent Vivier 2007-02-02 20:13:11 +00:00
parent 5b64251564
commit 7ea5409a1c
6 changed files with 120 additions and 13 deletions

View File

@ -28,7 +28,7 @@ LIBS = $(OPT_LIBS) -L$(TOP)/../libiso9660/m68k-linux \
LS = ls
AWK = awk
HEADERS = arch.h bank.h bootenv.h bootinfo.h bootx.h cli.h console.h driver.h enter_kernel030.h enter_kernel040.h enter_kernel.h enter_kernelnoMMU.h enter_kernelPPC.h head.h keyboard.h load.h misc.h MMU030.h MMU040.h serial.h vga.h config.h copymem.i
HEADERS = arch.h bank.h bootenv.h bootinfo.h bootx.h cli.h console.h driver.h enter_kernel030.h enter_kernel040.h enter_kernel.h enter_kernelnoMMU.h switch_to_PPC.h head.h keyboard.h load.h misc.h MMU030.h MMU040.h serial.h vga.h config.h copymem.i bootstrapPPC.h
SOURCES = head.S main.c console.c \
font_8x16.c \
@ -51,7 +51,7 @@ SOURCES_M68K = $(SOURCES_MMU) $(SOURCES_noMMU)
OBJS_M68K = $(patsubst %.c,%.o,$(SOURCES_M68K:.S=.o))
SOURCES_PPC = enter_kernelPPC.S PPC_asm.S
SOURCES_PPC = switch_to_PPC.S bootstrapPPC.S
OBJS_PPC = $(patsubst %.c,%.o,$(SOURCES_PPC:.S=.o))
@ -140,6 +140,9 @@ second: second.o
second.o: $(OBJS) $(TOP)/ld.script
$(LD) -T $(TOP)/ld.script -o second.o $(OBJS) $(LIBS)
bootstrapPPC.o: bootstrapPPC.S
$(PPC_CC) $(CPPFLAGS) -c $(TOP)/bootstrapPPC.S -o bootstrapPPC.o
.c.o:
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^

View File

@ -1,6 +1,6 @@
/*
*
* (c) 2005 Laurent Vivier <Laurent@lvivier.info>
* (c) 2005-2007 Laurent Vivier <Laurent@lvivier.info>
*
*/
@ -23,10 +23,6 @@ typedef void (*disable_cache_t) (void);
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef ARCH_PPC
#include "enter_kernelPPC.h"
#endif
extern void enter_kernel_init(void);
extern unsigned long enter_kernel;
extern unsigned long end_enter_kernel;

View File

@ -119,6 +119,8 @@ char* load_kernel(char* path, int bootstrap_size,
to_read = 0;
for (i = 0; i < elf_header.e_phnum; i++)
{
if (program_header[i].p_memsz == 0)
continue;
min_addr = (min_addr > program_header[i].p_vaddr) ?
program_header[i].p_vaddr : min_addr;
max_addr = (max_addr < program_header[i].p_vaddr + program_header[i].p_memsz) ?
@ -134,13 +136,12 @@ char* load_kernel(char* path, int bootstrap_size,
program_header[0].p_memsz -= PAGE_SIZE;
}
kernel_size = max_addr - min_addr;
*base = min_addr;
*entry = elf_header.e_entry;
*size = kernel_size;
kernel = (char*)malloc_contiguous(kernel_size + 4 + bootstrap_size);
kernel = (unsigned char*)(((unsigned long)kernel + 3) & 0xFFFFFFFC);
kernel = (char*)malloc_contiguous(kernel_size + PAGE_SIZE + bootstrap_size);
kernel = (unsigned char*)(((unsigned long)kernel + PAGE_SIZE) & ~(PAGE_SIZE - 1));
if (!check_full_in_bank((unsigned long)kernel, kernel_size))
error("Kernel between two banks, contact maintainer\n");
@ -155,7 +156,7 @@ char* load_kernel(char* path, int bootstrap_size,
error("Cannot seek");
}
ret = bar_read( stream,
kernel + program_header[i].p_vaddr - PAGE_SIZE,
kernel + program_header[i].p_vaddr - min_addr,
program_header[i].p_filesz,
read, to_read);
if (ret != program_header[i].p_filesz)

View File

@ -25,6 +25,7 @@
#endif
#ifdef ARCH_PPC
#include "bootx.h"
#include "switch_to_PPC.h"
#endif
#include "arch.h"
#include "misc.h"
@ -282,8 +283,7 @@ int start(emile_l2_header_t* info)
entry(physImage, kernel_size + BI_ALLOC_SIZE, start_mem, entry_point);
#endif
#ifdef ARCH_PPC
if (arch_type == gestaltPowerPC)
enter_kernelPPC((unsigned long)kernel, &regs);
// if (arch_type == gestaltPowerPC)
#endif
error("Kernel startup failed");

82
second/switch_to_PPC.S Normal file
View File

@ -0,0 +1,82 @@
/*
*
* (c) 2005-2007 Laurent Vivier <Laurent@lvivier.info>
* from BootX, (c) Benjamin Herrenschmidt
*
*/
.chip 68020
.equ PC, 0x00FC
.equ GPR, 0x0100
.equ FPR, 0x0200
#define pc %sp@(PC)
#define gpr(a) %sp@(GPR + 8 * a + 4)
#define fpr0(a) %sp@(FPR + 8 * a)
#define fpr1(a) %sp@(FPR + 8 * a + 4)
.macro copy_PC
move.l %a1@+, pc
.endm
.macro copy_GPR from=0, to=31
move.l %a1@+, gpr(\from)
.if \to-\from
copy_GPR "(\from+1)",\to
.endif
.endm
.macro copy_FPR from=0, to=31
move.l %a1@+, fpr0(\from)
move.l %a1@+, fpr1(\from)
.if \to-\from
copy_FPR "(\from+1)",\to
.endif
.endm
.macro _EnterPPC
move.l #0x47617279, %a0 /* 'Gary' */
move.l #0x05051956, %a1
move.l #0x0000C000, %d0
moveq #0, %d2
reset
move.l %sp,-(%sp)
0:
dc.w 0xFE03
beq 0b
.endm
.align 4
.global switch_to_PPC
switch_to_PPC:
link.w %fp,#0
/* get PPC registers values */
move.l 8(%fp), %a1
/* prepare stack */
move.l %sp, %d0
andi.l #0xFFFFFC00, %d0
move.l %d0, %sp
move.l #0x00BF, %d0
loop:
clr.l -(%sp)
dbra %d0, loop
/* Initialize PPC registers */
copy_PC
copy_GPR
copy_FPR
/* Switch to PPC */
_EnterPPC
unlk %fp
rts

25
second/switch_to_PPC.h Normal file
View File

@ -0,0 +1,25 @@
/*
*
* (c) 2005-2007 Laurent Vivier <Laurent@lvivier.info>
*
* Some parts from bootX, (c) BenH
*
*/
#ifndef __SWITH_TO_PPC_H__
#define __SWITH_TO_PPC_H__
#include "misc.h"
typedef u_int32_t float_reg_t[2];
typedef struct PPCRegisterList
{
u_int32_t PC;
u_int32_t GPR[32];
float_reg_t FPR[32];
} PPCRegisterList;
extern void switch_to_PPC(PPCRegisterList* regs);
#endif /* __SWITH_TO_PPC_H__ */