2003-01-31 Yoshinori K. Okuji <okuji@enbug.org>

* kern/i386/pc/lzo1x.S: New file.

	* util/i386/pc/pupa-mkimage.c: Include lzo1x.h.
	(compress_kernel): New variable.
	(generate_image): Heavily modified to support compressing a
	large part of the core image.

	* util/misc.c (pupa_util_read_image): Fix a file descriptor
	leak.
	(pupa_util_load_image): New function.

	* kern/i386/pc/startup.S: Include pupa/machine/kernel.h.
	(pupa_compressed_size): New variable.
	(codestart): Enable Gate A20 here.
	Decompress the compressed part of the core image.
	Rearrange the code to put functions and variables which are
	required for initialization in the non-compressed part.
	Include lzo1x.S.

	* kern/i386/pc/init.c (pupa_machine_init): Don't enable Gate A20
	here.

	* include/pupa/util/misc.h (pupa_util_write_image): Declared.

	* include/pupa/i386/pc/kernel.h
	(PUPA_KERNEL_MACHINE_COMPRESSED_SIZE): New macro.
	(PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): Increased by 4.
	(PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise.
	(PUPA_KERNEL_MACHINE_PREFIX): Likewise.
	(PUPA_KERNEL_MACHINE_RAW_SIZE): New macro.

	* conf/i386-pc.rmk (pupa_mkimage_LDFLAGS): New variable.

	* genmk.rb (Image#rule): Put LDFLAGS at the end of a line.
	(Utility#rule): Likewise.

	* configure.ac: Check if LZO is available.
This commit is contained in:
okuji 2003-01-31 03:26:56 +00:00
parent ce5bf700ca
commit 1f5ab4280a
18 changed files with 931 additions and 298 deletions

View file

@ -130,9 +130,11 @@ pupa_machine_init (void)
/* Sanity check. */
if (pupa_lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
pupa_fatal ("too small memory");
#if 0
/* Turn on Gate A20 to access >1MB. */
pupa_gate_a20 (1);
#endif
/* Add the lower memory into free memory. */
if (pupa_lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)

323
kern/i386/pc/lzo1x.S Normal file
View file

@ -0,0 +1,323 @@
/*
* PUPA -- Preliminary Universal Programming Architecture for GRUB
* Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
* Copyright (C) 2003 Yoshinori K. Okuji <okuji@enbug.org>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This code was stolen from the files enter.sh, leave.sh, lzo1x_d.sh,
* lzo1x_f.s and lzo_asm.h in LZO version 1.08, and was heavily modified
* to adapt it to PUPA's requirement.
*
* See <http://www.oberhumer.com/opensource/lzo/>, for more information
* about LZO.
*/
#define INP 4+16(%esp)
#define INS 8+16(%esp)
#define OUTP 12+16(%esp)
#define NN 3
#define N_3 %ebp
#define N_255 $255
#define LODSB movb (%esi), %al ; incl %esi
#define NOTL_3(r) xorl N_3, r
#define MOVSL(r1,r2,x) movl (r1), x ; addl $4, r1 ; movl x, (r2) ; addl $4, r2
#define COPYL_C(r1,r2,x,rc) 9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b
#define COPYL(r1,r2,x) COPYL_C(r1,r2,x,%ecx)
lzo1x_decompress:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
cld
movl INP, %esi
movl OUTP, %edi
movl $3, %ebp
xorl %eax, %eax
xorl %ebx, %ebx /* high bits 9-32 stay 0 */
lodsb
cmpb $17, %al
jbe .L01
subb $17-NN, %al
jmp .LFLR
/***********************************************************************
// literal run
************************************************************************/
0: addl N_255, %eax
1: movb (%esi), %bl
incl %esi
orb %bl, %bl
jz 0b
leal 18+NN(%eax,%ebx), %eax
jmp 3f
.align 8
.L00:
LODSB
.L01:
cmpb $16, %al
jae .LMATCH
/* a literal run */
orb %al, %al
jz 1b
addl $3+NN, %eax
3:
.LFLR:
movl %eax, %ecx
NOTL_3(%eax)
shrl $2, %ecx
andl N_3, %eax
COPYL(%esi,%edi,%edx)
subl %eax, %esi
subl %eax, %edi
LODSB
cmpb $16, %al
jae .LMATCH
/***********************************************************************
// R1
************************************************************************/
shrl $2, %eax
movb (%esi), %bl
leal -0x801(%edi), %edx
leal (%eax,%ebx,4), %eax
incl %esi
subl %eax, %edx
movl (%edx), %ecx
movl %ecx, (%edi)
addl N_3, %edi
jmp .LMDONE
/***********************************************************************
// M2
************************************************************************/
.align 8
.LMATCH:
cmpb $64, %al
jb .LM3MATCH
/* a M2 match */
movl %eax, %ecx
shrl $2, %eax
leal -1(%edi), %edx
andl $7, %eax
movb (%esi), %bl
shrl $5, %ecx
leal (%eax,%ebx,8), %eax
incl %esi
subl %eax, %edx
addl $1+3, %ecx
cmpl N_3, %eax
jae .LCOPYLONG
jmp .LCOPYBYTE
/***********************************************************************
// M3
************************************************************************/
0: addl N_255, %eax
1: movb (%esi), %bl
incl %esi
orb %bl, %bl
jz 0b
leal 33+NN(%eax,%ebx), %ecx
xorl %eax, %eax
jmp 3f
.align 8
.LM3MATCH:
cmpb $32, %al
jb .LM4MATCH
/* a M3 match */
andl $31, %eax
jz 1b
lea 2+NN(%eax), %ecx
3:
movw (%esi), %ax
leal -1(%edi), %edx
shrl $2, %eax
addl $2, %esi
subl %eax, %edx
cmpl N_3, %eax
jb .LCOPYBYTE
/***********************************************************************
// copy match
************************************************************************/
.align 2
.LCOPYLONG: /* copy match using longwords */
leal -3(%edi,%ecx), %eax
shrl $2, %ecx
COPYL(%edx,%edi,%ebx)
movl %eax, %edi
xorl %ebx, %ebx
.LMDONE:
movb -2(%esi), %al
andl N_3, %eax
jz .L00
.LFLR3:
movl (%esi), %edx
addl %eax, %esi
movl %edx, (%edi)
addl %eax, %edi
LODSB
jmp .LMATCH
.align 8
.LCOPYBYTE: /* copy match using bytes */
xchgl %edx,%esi
subl N_3,%ecx
rep
movsb
movl %edx, %esi
jmp .LMDONE
/***********************************************************************
// M4
************************************************************************/
0: addl N_255, %ecx
1: movb (%esi), %bl
incl %esi
orb %bl, %bl
jz 0b
leal 9+NN(%ebx,%ecx), %ecx
jmp 3f
.align 8
.LM4MATCH:
cmpb $16, %al
jb .LM1MATCH
/* a M4 match */
movl %eax, %ecx
andl $8, %eax
shll $13, %eax /* save in bit 16 */
andl $7, %ecx
jz 1b
addl $2+NN, %ecx
3:
movw (%esi), %ax
addl $2, %esi
leal -0x4000(%edi), %edx
shrl $2, %eax
jz .LEOF
subl %eax, %edx
jmp .LCOPYLONG
/***********************************************************************
// M1
************************************************************************/
.align 8
.LM1MATCH:
/* a M1 match */
shrl $2, %eax
movb (%esi), %bl
leal -1(%edi), %edx
leal (%eax,%ebx,4), %eax
incl %esi
subl %eax, %edx
movb (%edx), %al /* we must use this because edx can be edi-1 */
movb %al, (%edi)
movb 1(%edx), %bl
movb %bl, 1(%edi)
addl $2, %edi
jmp .LMDONE
/***********************************************************************
//
************************************************************************/
.LEOF:
/**** xorl %eax,%eax eax=0 from above */
cmpl $3+NN, %ecx /* ecx must be 3/6 */
setnz %al
/* check compressed size */
movl INP, %edx
addl INS, %edx
cmpl %edx, %esi /* check compressed size */
ja .L_input_overrun
jb .L_input_not_consumed
.L_leave:
negl %eax
jnz 1f
subl OUTP, %edi /* write back the uncompressed size */
movl %edi, %eax
1: popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.L_input_not_consumed:
movl $8, %eax /* LZO_E_INPUT_NOT_CONSUMED */
jmp .L_leave
.L_input_overrun:
movl $4, %eax /* LZO_E_INPUT_OVERRUN */
jmp .L_leave
#undef INP
#undef INS
#undef OUTP
#undef NN
#undef NN
#undef N_3
#undef N_255
#undef LODSB
#undef NOTL_3
#undef MOVSL
#undef COPYL_C
#undef COPYL

View file

@ -1,7 +1,7 @@
/*
* PUPA -- Preliminary Universal Programming Architecture for GRUB
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
* Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
* Copyright (C) 2002,2003 Yoshinori K. Okuji <okuji@enbug.org>
*
* 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
@ -50,7 +50,8 @@
#include <pupa/machine/memory.h>
#include <pupa/machine/console.h>
#include <pupa/machine/linux.h>
#include <pupa/machine/kernel.h>
#define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup.S"
@ -88,6 +89,8 @@ VARIABLE(pupa_total_module_size)
.long 0
VARIABLE(pupa_kernel_image_size)
.long 0
VARIABLE(pupa_compressed_size)
.long 0
VARIABLE(pupa_install_dos_part)
.long 0xFFFFFFFF
VARIABLE(pupa_install_bsd_part)
@ -129,6 +132,25 @@ codestart:
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
call EXT_C(pupa_gate_a20)
/* decompress the compressed part and put the result at 1MB */
movl $0x100000, %esi
movl $(START_SYMBOL + PUPA_KERNEL_MACHINE_RAW_SIZE), %edi
pushl %esi
pushl EXT_C(pupa_compressed_size)
pushl %edi
call lzo1x_decompress
addl $12, %esp
/* copy back the decompressed part */
movl %eax, %ecx
cld
rep
movsb
/* copy modules before cleaning out the bss */
movl EXT_C(pupa_total_module_size), %ecx
movl EXT_C(pupa_kernel_image_size), %esi
@ -148,8 +170,9 @@ codestart:
/* compute the bss length */
movl $END_SYMBOL, %ecx
subl %edi, %ecx
/* clean out */
xorl %eax, %eax
cld
rep
stosb
@ -160,6 +183,255 @@ codestart:
call EXT_C(pupa_main)
/*
* This is the area for all of the special variables.
*/
.p2align 2 /* force 4-byte alignment */
protstack:
.long PUPA_MEMORY_MACHINE_PROT_STACK
VARIABLE(pupa_boot_drive)
.long 0
VARIABLE(pupa_start_addr)
.long START_SYMBOL
VARIABLE(pupa_end_addr)
.long END_SYMBOL
VARIABLE(pupa_apm_bios_info)
.word 0 /* version */
.word 0 /* cseg */
.long 0 /* offset */
.word 0 /* cseg_16 */
.word 0 /* dseg_16 */
.word 0 /* cseg_len */
.word 0 /* cseg_16_len */
.word 0 /* dseg_16_len */
/*
* This is the Global Descriptor Table
*
* An entry, a "Segment Descriptor", looks like this:
*
* 31 24 19 16 7 0
* ------------------------------------------------------------
* | | |B| |A| | | |1|0|E|W|A| |
* | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 |
* | | |D| |L| 19..16| | |1|1|C|R|A| |
* ------------------------------------------------------------
* | | |
* | BASE 15..0 | LIMIT 15..0 |
* | | |
* ------------------------------------------------------------
*
* Note the ordering of the data items is reversed from the above
* description.
*/
.p2align 2 /* force 4-byte alignment */
gdt:
.word 0, 0
.byte 0, 0, 0, 0
/* code segment */
.word 0xFFFF, 0
.byte 0, 0x9A, 0xCF, 0
/* data segment */
.word 0xFFFF, 0
.byte 0, 0x92, 0xCF, 0
/* 16 bit real mode CS */
.word 0xFFFF, 0
.byte 0, 0x9E, 0, 0
/* 16 bit real mode DS */
.word 0xFFFF, 0
.byte 0, 0x92, 0, 0
/* this is the GDT descriptor */
gdtdesc:
.word 0x27 /* limit */
.long gdt /* addr */
/*
* These next two routines, "real_to_prot" and "prot_to_real" are structured
* in a very specific way. Be very careful when changing them.
*
* NOTE: Use of either one messes up %eax and %ebp.
*/
real_to_prot:
.code16
cli
/* load the GDT register */
DATA32 ADDR32 lgdt gdtdesc
/* turn on protected mode */
movl %cr0, %eax
orl $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax
movl %eax, %cr0
/* jump to relocation, flush prefetch queue, and reload %cs */
DATA32 ljmp $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
.code32
protcseg:
/* reload other segment registers */
movw $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* put the return address in a known safe location */
movl (%esp), %eax
movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK
/* get protected mode stack */
movl protstack, %eax
movl %eax, %esp
movl %eax, %ebp
/* get return address onto the right stack */
movl PUPA_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, (%esp)
/* zero %eax */
xorl %eax, %eax
/* return on the old (or initialized) stack! */
ret
prot_to_real:
/* just in case, set GDT */
lgdt gdtdesc
/* save the protected mode stack */
movl %esp, %eax
movl %eax, protstack
/* get the return address */
movl (%esp), %eax
movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK
/* set up new stack */
movl $PUPA_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, %esp
movl %eax, %ebp
/* set up segment limits */
movw $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* this might be an extra step */
/* jump to a 16 bit segment */
ljmp $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
tmpcseg:
.code16
/* clear the PE bit of CR0 */
movl %cr0, %eax
andl $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax
movl %eax, %cr0
/* flush prefetch queue, reload %cs */
DATA32 ljmp $0, $realcseg
realcseg:
/* we are in real mode now
* set up the real mode segment registers : DS, SS, ES
*/
/* zero %eax */
xorl %eax, %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* restore interrupts */
sti
/* return on new stack! */
DATA32 ret
.code32
/*
* pupa_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
FUNCTION(pupa_gate_a20)
movl %eax, %ecx
call gloop1
movb $0xd1, %al
outb $0x64
gloopint1:
inb $0x64
andb $0x02, %al
jnz gloopint1
movb $0xdd, %al
testl %ecx, %ecx
jz gdoit
orb $0x02, %al
gdoit:
outb $0x60
call gloop1
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gloop1
ret
gloop1:
inb $0x64
andb $0x02, %al
jnz gloop1
gloop2:
inb $0x64
andb $0x01, %al
jz gloop2ret
inb $0x60
jmp gloop2
gloop2ret:
ret
#include "lzo1x.S"
/*
* This call is special... it never returns... in fact it should simply
* hang at this point!
@ -348,120 +620,6 @@ linux_setup_seg:
.code32
/*
* These next two routines, "real_to_prot" and "prot_to_real" are structured
* in a very specific way. Be very careful when changing them.
*
* NOTE: Use of either one messes up %eax and %ebp.
*/
real_to_prot:
.code16
cli
/* load the GDT register */
DATA32 ADDR32 lgdt gdtdesc
/* turn on protected mode */
movl %cr0, %eax
orl $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax
movl %eax, %cr0
/* jump to relocation, flush prefetch queue, and reload %cs */
DATA32 ljmp $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
.code32
protcseg:
/* reload other segment registers */
movw $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* put the return address in a known safe location */
movl (%esp), %eax
movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK
/* get protected mode stack */
movl protstack, %eax
movl %eax, %esp
movl %eax, %ebp
/* get return address onto the right stack */
movl PUPA_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, (%esp)
/* zero %eax */
xorl %eax, %eax
/* return on the old (or initialized) stack! */
ret
prot_to_real:
/* just in case, set GDT */
lgdt gdtdesc
/* save the protected mode stack */
movl %esp, %eax
movl %eax, protstack
/* get the return address */
movl (%esp), %eax
movl %eax, PUPA_MEMORY_MACHINE_REAL_STACK
/* set up new stack */
movl $PUPA_MEMORY_MACHINE_REAL_STACK, %eax
movl %eax, %esp
movl %eax, %ebp
/* set up segment limits */
movw $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* this might be an extra step */
/* jump to a 16 bit segment */
ljmp $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
tmpcseg:
.code16
/* clear the PE bit of CR0 */
movl %cr0, %eax
andl $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax
movl %eax, %cr0
/* flush prefetch queue, reload %cs */
DATA32 ljmp $0, $realcseg
realcseg:
/* we are in real mode now
* set up the real mode segment registers : DS, SS, ES
*/
/* zero %eax */
xorl %eax, %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
/* restore interrupts */
sti
/* return on new stack! */
DATA32 ret
.code32
/*
* int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
*
@ -931,63 +1089,6 @@ xsmap:
ret
/*
* pupa_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
FUNCTION(pupa_gate_a20)
pushl %eax
call gloop1
movb $0xd1, %al
outb $0x64
gloopint1:
inb $0x64
andb $0x02, %al
jnz gloopint1
movb $0xdd, %al
cmpb $0, 0x8(%esp)
jz gdoit
orb $0x02, %al
gdoit:
outb $0x60
call gloop1
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gloop1
popl %eax
ret
gloop1:
inb $0x64
andb $0x02, %al
jnz gloop1
gloop2:
inb $0x64
andb $0x01, %al
jz gloop2ret
inb $0x60
jmp gloop2
gloop2ret:
ret
/*
* void pupa_console_putchar (int c)
*
@ -1413,79 +1514,3 @@ FUNCTION(pupa_currticks)
popl %ebp
ret
/*
* This is the area for all of the special variables.
*/
.p2align 2 /* force 4-byte alignment */
protstack:
.long PUPA_MEMORY_MACHINE_PROT_STACK
VARIABLE(pupa_boot_drive)
.long 0
VARIABLE(pupa_start_addr)
.long START_SYMBOL
VARIABLE(pupa_end_addr)
.long END_SYMBOL
VARIABLE(pupa_apm_bios_info)
.word 0 /* version */
.word 0 /* cseg */
.long 0 /* offset */
.word 0 /* cseg_16 */
.word 0 /* dseg_16 */
.word 0 /* cseg_len */
.word 0 /* cseg_16_len */
.word 0 /* dseg_16_len */
/*
* This is the Global Descriptor Table
*
* An entry, a "Segment Descriptor", looks like this:
*
* 31 24 19 16 7 0
* ------------------------------------------------------------
* | | |B| |A| | | |1|0|E|W|A| |
* | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 |
* | | |D| |L| 19..16| | |1|1|C|R|A| |
* ------------------------------------------------------------
* | | |
* | BASE 15..0 | LIMIT 15..0 |
* | | |
* ------------------------------------------------------------
*
* Note the ordering of the data items is reversed from the above
* description.
*/
.p2align 2 /* force 4-byte alignment */
gdt:
.word 0, 0
.byte 0, 0, 0, 0
/* code segment */
.word 0xFFFF, 0
.byte 0, 0x9A, 0xCF, 0
/* data segment */
.word 0xFFFF, 0
.byte 0, 0x92, 0xCF, 0
/* 16 bit real mode CS */
.word 0xFFFF, 0
.byte 0, 0x9E, 0, 0
/* 16 bit real mode DS */
.word 0xFFFF, 0
.byte 0, 0x92, 0, 0
/* this is the GDT descriptor */
gdtdesc:
.word 0x27 /* limit */
.long gdt /* addr */

View file

@ -135,7 +135,7 @@ static void *
pupa_real_malloc (pupa_mm_header_t *first, pupa_size_t n, pupa_size_t align)
{
pupa_mm_header_t p, q;
if ((*first)->magic == PUPA_MM_ALLOC_MAGIC)
return 0;