diff options
| author | Michael Brown | 2005-04-08 17:01:17 +0200 |
|---|---|---|
| committer | Michael Brown | 2005-04-08 17:01:17 +0200 |
| commit | 0ff80b477dcff0726ebdbed95e8a93971e59e82b (patch) | |
| tree | 860b7150212a07c24a9529ea072f3fb12700974c /src/arch/i386/prefix | |
| parent | Merged this file into HEAD (diff) | |
| download | ipxe-0ff80b477dcff0726ebdbed95e8a93971e59e82b.tar.gz ipxe-0ff80b477dcff0726ebdbed95e8a93971e59e82b.tar.xz ipxe-0ff80b477dcff0726ebdbed95e8a93971e59e82b.zip | |
Merged mcb30-realmode-redesign back to HEAD
Diffstat (limited to 'src/arch/i386/prefix')
| -rw-r--r-- | src/arch/i386/prefix/dskprefix.S (renamed from src/arch/i386/prefix/floppyprefix.S) | 62 | ||||
| -rw-r--r-- | src/arch/i386/prefix/int19exit.c | 13 | ||||
| -rw-r--r-- | src/arch/i386/prefix/unnrv2b.S | 198 |
3 files changed, 178 insertions, 95 deletions
diff --git a/src/arch/i386/prefix/floppyprefix.S b/src/arch/i386/prefix/dskprefix.S index 18bed4c8f..d1f64e7ae 100644 --- a/src/arch/i386/prefix/floppyprefix.S +++ b/src/arch/i386/prefix/dskprefix.S @@ -1,3 +1,5 @@ +#include "compiler.h" + /* NOTE: this boot sector contains instructions that need at least an 80186. * Yes, as86 has a bug somewhere in the valid instruction set checks. * @@ -115,7 +117,6 @@ got_sectors: /* ok, we've written the Loading... message, now we want to load the system */ - pushw %es /* = ds */ movw $SYSSEG, %ax movw %ax,%es /* segment of SYSSEG<<4 */ pushw %es @@ -130,8 +131,6 @@ got_sectors: call print_nl pop %es /* = SYSSEG */ - pop %es /* balance push/pop es */ -sigok: /* Restore original disk parameters */ movw $0x78, %bx @@ -142,20 +141,47 @@ sigok: movw %di,(%bx) movw %si,2(%bx) -/* after that (everything loaded), we call to the .ROM file loaded. */ - - pushl $0 /* No parameters to preserve for exit path */ - pushw $0 /* Use prefix exit path mechanism */ - ljmp $SYSSEG, $_start - - .section ".text16", "ax", @progbits - .globl prefix_exit -prefix_exit: - xchgw %bx, %bx - int $0x19 /* should try to boot machine */ - .globl prefix_exit_end -prefix_exit_end: - .previous + /* Everything now loaded. %es = SYSSEG, so %es:0000 points to + * start of loaded image. + */ + +start_runtime: + +#ifdef COMPRESS + /* Decompress runtime image. %es:0000 points to decompressed + * image on exit. + */ + lcall $SYSSEG, $decompress16 +#endif + + /* Set up internal environment. Address of entry-point + * function is returned in %es:di. + */ + pushw %es /* setup16 says %ds:0000 must point to image */ + popw %ds + movw $setup16, %di + pushw %cs + call ljmp_to_es_di + + /* Call initialisation routine. Relocation may be done. New + * address of entry-point function is returned in %es:di. + */ + pushl $arch_rm_initialise + pushw %cs /* == lcall %es:di */ + call ljmp_to_es_di + + /* Call to arch_rm_main. Register INT19 as an exit path. This + * call will never return. + */ + movl $exit_via_int19, %eax + pushl $arch_rm_main + pushl %eax /* Dummy return address */ + + /* Do the equivalent of ljmp *%es:di */ +ljmp_to_es_di: + pushw %es + pushw %di + lret /* This routine loads the system at address SYSSEG<<4, making sure no 64kB * boundaries are crossed. We try to load it as fast as possible, loading whole @@ -164,7 +190,7 @@ prefix_exit_end: * in: es - starting address segment (normally SYSSEG) */ read_it: - movw $0,sread /* read whole image incl boot sector */ + movw $1,sread /* don't reload the prefix */ movw %es,%ax testw $0x0fff, %ax die: jne die /* es must be at 64kB boundary */ diff --git a/src/arch/i386/prefix/int19exit.c b/src/arch/i386/prefix/int19exit.c new file mode 100644 index 000000000..e7be06244 --- /dev/null +++ b/src/arch/i386/prefix/int19exit.c @@ -0,0 +1,13 @@ +#include "bochs.h" +#include "realmode.h" + +/* + * The "exit via INT 19" exit path. INT 19 is the old (pre-BBS) "boot + * system" interrupt. + * + */ + +void exit_via_int19 ( struct real_mode_regs *rm_regs ) { + bochsbp(); + /* Placeholder */ +} diff --git a/src/arch/i386/prefix/unnrv2b.S b/src/arch/i386/prefix/unnrv2b.S index 1836fa715..50776dc93 100644 --- a/src/arch/i386/prefix/unnrv2b.S +++ b/src/arch/i386/prefix/unnrv2b.S @@ -15,115 +15,159 @@ * - Structure modified to be a subroutine call rather than an * executable prefix. * Michael Brown 30 Mar 2004 + * + * - Modified to be compilable as either 16-bit or 32-bit code. + * Michael Brown 9 Mar 2005 */ +/**************************************************************************** + * This file provides the decompress_block() and decompress_block16() + * functions which can be called in order to decompress an image + * compressed with the nrv2b utility in src/util. + * + * These functions are designed to be called by the prefix. They are + * position-independent code. + * + * The same basic assembly code is used to compile both + * decompress_block() and decompress_block16(). + **************************************************************************** + */ .text .arch i386 .section ".prefix", "ax", @progbits - .code32 - - .globl decompress -decompress: - /* Save the initial register values */ - pushal - /* - * See where I am running, and compute %ebp - * %ebp holds delta between physical and virtual addresses. - */ - call 1f -1: popl %ebp - subl $1b, %ebp +#ifdef CODE16 +/**************************************************************************** + * decompress_block16 (real-mode near call, position independent) + * + * Parameters (passed via registers): + * %ds:%si - Pointer to compressed input data + * %es:%di - Pointer to output buffer + * Returns: + * All registers are preserved + * + * NOTE: The compressed data size must be in the range [1,65533-%si] + * and the uncompressed data size must be in the range [1,65536-%di] + * (where %si and %di are the input values for those registers). Note + * particularly that the lower limit is 1, not 0, and that the upper + * limit on the input (compressed) data really is 65533, since the + * algorithm may read up to three bytes beyond the end of the input + * data, since it reads dwords. + * + * Although splitting up the data into (almost) 64kB chunks for + * compression is awkward and worsens the compression ratio, it has + * little to no practical effect since our image size is currently + * <64kB for all single drivers. Having a decompression routine that + * can run in real-mode avoids the need to duplicate RM-to-PM + * transition code from librm (or have part of librm kept + * uncompressed, which is itself awkward) and means that we don't need + * to set up the PM stack until we hit the setup routine itself. + **************************************************************************** + */ + +#define REG(x) x - /* "compressed" and "decompress_to" defined by linker script */ - /* move compressed image up to temporary area before decompressing */ - std - movl $_compressed_size, %ecx - leal _compressed+4-1(%ebp, %ecx), %esi - leal _compressed_copy-1(%ebp, %ecx), %edi - rep movsb - /* Setup to run the decompressor */ - cld - leal _compressed_copy(%ebp), %esi - leal decompress_to(%ebp), %edi - movl $-1, %ebp /* last_m_off = -1 */ - jmp dcl1_n2b + .code16 + .globl decompress_block16 +decompress_block16: + +#else /* CODE16 */ -/* ------------- DECOMPRESSION ------------- +/**************************************************************************** + * decompress_block (32-bit protected-mode near call, position independent) + * + * Parameters (passed via registers): + * %ds:%esi - Pointer to compressed input data + * %es:%edi - Pointer to output buffer + * Returns: + * All registers are preserved + **************************************************************************** + */ - Input: - %esi - source - %edi - dest - %ebp - -1 - cld +#define REG(x) e ## x + + .code32 + .globl decompress_block +decompress_block: - Output: - %eax - 0 - %ecx - 0 -*/ +#endif /* CODE16 */ -.macro getbit bits -.if \bits == 1 - addl %ebx, %ebx - jnz 1f -.endif - movl (%esi), %ebx - subl $-4, %esi /* sets carry flag */ - adcl %ebx, %ebx -1: -.endm +#define xAX REG(ax) +#define xCX REG(cx) +#define xBP REG(bp) +#define xSI REG(si) +#define xDI REG(di) + /* Save registers */ + pushal + /* Do the decompression */ + cld + xor %xBP, %xBP + dec %xBP /* last_m_off = -1 */ + jmp dcl1_n2b + decompr_literals_n2b: movsb - decompr_loop_n2b: addl %ebx, %ebx jnz dcl2_n2b dcl1_n2b: - getbit 32 + call getbit32 dcl2_n2b: jc decompr_literals_n2b - xorl %eax, %eax - incl %eax /* m_off = 1 */ + xor %xAX, %xAX + inc %xAX /* m_off = 1 */ loop1_n2b: - getbit 1 - adcl %eax, %eax /* m_off = m_off*2 + getbit() */ - getbit 1 + call getbit1 + adc %xAX, %xAX /* m_off = m_off*2 + getbit() */ + call getbit1 jnc loop1_n2b /* while(!getbit()) */ - xorl %ecx, %ecx - subl $3, %eax + sub $3, %xAX jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */ - shll $8, %eax - movb (%esi), %al /* m_off = (m_off - 3)*256 + src[ilen++] */ - incl %esi - xorl $-1, %eax + shl $8, %xAX + movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */ + inc %xSI + not %xAX jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */ - movl %eax, %ebp /* last_m_off = m_off ?*/ + mov %xAX, %xBP /* last_m_off = m_off ?*/ decompr_ebpeax_n2b: - getbit 1 - adcl %ecx, %ecx /* m_len = getbit() */ - getbit 1 - adcl %ecx, %ecx /* m_len = m_len*2 + getbit()) */ + xor %xCX, %xCX + call getbit1 + adc %xCX, %xCX /* m_len = getbit() */ + call getbit1 + adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */ jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */ - incl %ecx /* m_len++ */ + inc %xCX /* m_len++ */ loop2_n2b: - getbit 1 - adcl %ecx, %ecx /* m_len = m_len*2 + getbit() */ - getbit 1 + call getbit1 + adc %xCX, %xCX /* m_len = m_len*2 + getbit() */ + call getbit1 jnc loop2_n2b /* while(!getbit()) */ - incl %ecx - incl %ecx /* m_len += 2 */ + inc %xCX + inc %xCX /* m_len += 2 */ decompr_got_mlen_n2b: - cmpl $-0xd00, %ebp - adcl $1, %ecx /* m_len = m_len + 1 + (last_m_off > 0xd00) */ - pushl %esi - leal (%edi,%ebp), %esi /* m_pos = dst + olen + -m_off */ + cmp $-0xd00, %xBP + adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */ + push %xSI + lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */ rep - movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */ - popl %esi + es movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */ + pop %xSI jmp decompr_loop_n2b + + +getbit1: + addl %ebx, %ebx + jnz 1f +getbit32: + movl (%xSI), %ebx + sub $-4, %xSI /* sets carry flag */ + adcl %ebx, %ebx +1: + ret + decompr_end_n2b: - /* Restore the initial register values */ + /* Restore registers and return */ popal ret |
