diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2012-10-31 14:31:31 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2012-10-31 14:31:31 +0000 |
commit | 9557829cedab1caf723629c0053691ca2086e80d (patch) | |
tree | 39a87f410cdee7d5c1103db3e3d86c08a3238b8b /sys/arch/i386 | |
parent | a598db0083212e273ae26daa59426c4ba169554a (diff) |
Make cdboot(8) and pxeboot(8) work correctly when it is larger than 64KB in
size. When relocating use blocks that are a maximum of 32KB in size and
increment the segment registers after relocating each block. This keeps us
within the confines of the %cx register and the real mode segmented
addressing.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/stand/cdboot/srt0.S | 49 | ||||
-rw-r--r-- | sys/arch/i386/stand/pxeboot/srt0.S | 51 |
2 files changed, 73 insertions, 27 deletions
diff --git a/sys/arch/i386/stand/cdboot/srt0.S b/sys/arch/i386/stand/cdboot/srt0.S index 9a3d241a263..5a721e21c02 100644 --- a/sys/arch/i386/stand/cdboot/srt0.S +++ b/sys/arch/i386/stand/cdboot/srt0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: srt0.S,v 1.2 2012/10/11 12:08:24 jsing Exp $ */ +/* $OpenBSD: srt0.S,v 1.3 2012/10/31 14:31:30 jsing Exp $ */ /* * Copyright (c) 1997 Michael Shalayeff @@ -58,13 +58,10 @@ _start: * Like the standard /boot, we are linked to run at 0x40120 * (load address 0x40000), so we relocate to there. * - * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so don't + * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so we don't * have to worry about an overlapping copy until cdboot is * over 225 KB. * - * Note that there are other reasons to be worried if - * sizeof(/boot) > 64 KB. So currently we copy a maximum of 64 KB. - * * Our cdbr CD-ROM boot sector passes us the drive number to use * in %dl. */ @@ -73,20 +70,46 @@ _start: movw %ax, %ss /* CPU disables interrupts till... */ movl $CDBOOTADDR-4, %esp /* after this instruction */ - movw $(CDBOOTADDR >> 4), %ax - movw %ax, %ds - xorw %si, %si /* Where we're coming from */ + pushl %edx /* Preserve the drive number. */ - movw $(LINKADDR >> 4), %ax - movw %ax, %es /* Set %es = 0x4000 */ - xorw %di, %di /* Where we're going to */ + movw $(CDBOOTADDR >> 4), %ax /* Reloc from %ds = 0x7c0. */ + movw $(LINKADDR >> 4), %bx /* Reloc to %es = 0x4012. */ - movl $_C_LABEL(end), %ecx - subl $_C_LABEL(_start), %ecx /* How big are we? */ + movl $_C_LABEL(end), %edx + subl $_C_LABEL(_start), %edx /* How big are we? */ + + /* + * Relocate in blocks that are a maximum of 32KB in size, incrementing + * the segment registers after each block. The 'rep; movsb' instruction + * uses %cx, which limits us to a maximum block size of 0xfff0, even + * though we can address the full 64KB within a single segment. + */ +#define RELOC_BLOCK_SIZE 0x8000 +reloc_loop: + movl %edx, %ecx + jcxz reloc_done + cmpl $RELOC_BLOCK_SIZE, %ecx + jbe reloc_notrunc + movl $RELOC_BLOCK_SIZE, %ecx +reloc_notrunc: + subl %ecx, %edx + + movw %ax, %ds /* Where we're coming from */ + xorw %si, %si + + movw %bx, %es /* Where we're going to */ + xorw %di, %di cld rep; movsb /* Copy into place */ + addw $(RELOC_BLOCK_SIZE >> 4), %ax + addw $(RELOC_BLOCK_SIZE >> 4), %bx + + jmp reloc_loop + +reloc_done: + popl %edx jmpl $(LINKADDR >> 4), $(relocated-_start) /* Now relocate */ relocated: diff --git a/sys/arch/i386/stand/pxeboot/srt0.S b/sys/arch/i386/stand/pxeboot/srt0.S index e0cc7ddb8f1..16a0313222c 100644 --- a/sys/arch/i386/stand/pxeboot/srt0.S +++ b/sys/arch/i386/stand/pxeboot/srt0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: srt0.S,v 1.2 2012/10/11 12:08:24 jsing Exp $ */ +/* $OpenBSD: srt0.S,v 1.3 2012/10/31 14:31:30 jsing Exp $ */ /* * Copyright (c) 1997 Michael Shalayeff @@ -56,13 +56,10 @@ _start: * the standard /boot, we are linked to run at 0x40120 (load * address 0x40000), so we relocate to there. * - * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so don't + * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so we don't * have to worry about an overlapping copy until pxeboot is * over 225 KB. * - * Note that there are other reasons to be worried if - * sizeof(/boot) > 64 KB. So currently we copy a maximum of 64 KB. - * * PXE loads us with a stack that grows down from 0x80000 (512 KB). * While it is unlikely that this will clash with our code that * we're copying up, we create a temporary stack just below us @@ -71,23 +68,49 @@ _start: */ #define PXEBOOTADDR 0x7c00 /* Address where we are loaded by PXE */ xorw %ax, %ax - movw %ax, %ss /* CPU disables interrupts till.. */ + movw %ax, %ss /* CPU disables interrupts till... */ movl $PXEBOOTADDR-4, %esp /* after this instruction */ - movw $(PXEBOOTADDR >> 4), %ax - movw %ax, %ds - xorw %si, %si /* Where we're coming from */ + pushl %edx /* Preserve the drive number. */ - movw $(LINKADDR >> 4), %ax - movw %ax, %es /* Set %es = 0x4000 */ - xorw %di, %di /* Where we're going to */ + movw $(PXEBOOTADDR >> 4), %ax /* Reloc from %ds = 0x7c0. */ + movw $(LINKADDR >> 4), %bx /* Reloc to %es = 0x4012. */ - movl $_C_LABEL(end), %ecx - subl $_C_LABEL(_start), %ecx /* How big are we? */ + movl $_C_LABEL(end), %edx + subl $_C_LABEL(_start), %edx /* How big are we? */ + + /* + * Relocate in blocks that are a maximum of 32KB in size, incrementing + * the segment registers after each block. The 'rep; movsb' instruction + * uses %cx, which limits us to a maximum block size of 0xfff0, even + * though we can address the full 64KB within a single segment. + */ +#define RELOC_BLOCK_SIZE 0x8000 +reloc_loop: + movl %edx, %ecx + jcxz reloc_done + cmpl $RELOC_BLOCK_SIZE, %ecx + jbe reloc_notrunc + movl $RELOC_BLOCK_SIZE, %ecx +reloc_notrunc: + subl %ecx, %edx + + movw %ax, %ds /* Where we're coming from */ + xorw %si, %si + + movw %bx, %es /* Where we're going to */ + xorw %di, %di cld rep; movsb /* Copy into place */ + addw $(RELOC_BLOCK_SIZE >> 4), %ax + addw $(RELOC_BLOCK_SIZE >> 4), %bx + + jmp reloc_loop + +reloc_done: + popl %edx jmpl $(LINKADDR >> 4), $(relocated-_start) /* Now relocate */ relocated: |