summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/prefix
diff options
context:
space:
mode:
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.c13
-rw-r--r--src/arch/i386/prefix/unnrv2b.S198
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