2011-03-28 02:05:40 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
|
|
|
|
*
|
|
|
|
* 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 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
|
2012-07-20 20:55:45 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301, USA.
|
2011-03-28 02:05:40 +02:00
|
|
|
*
|
2015-03-02 12:54:40 +01:00
|
|
|
* You can also choose to distribute this program under the terms of
|
|
|
|
* the Unmodified Binary Distribution Licence (as given in the file
|
|
|
|
* COPYING.UBDL), provided that you have satisfied its requirements.
|
|
|
|
*
|
2011-03-28 02:05:40 +02:00
|
|
|
*/
|
|
|
|
|
2015-03-02 12:54:40 +01:00
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
2011-03-28 02:05:40 +02:00
|
|
|
|
|
|
|
/* Initial temporary stack size */
|
|
|
|
#define EXE_STACK_SIZE 0x400
|
|
|
|
|
|
|
|
/* Temporary decompression area (avoid DOS high memory area) */
|
|
|
|
#define EXE_DECOMPRESS_ADDRESS 0x110000
|
|
|
|
|
|
|
|
/* Fields within the Program Segment Prefix */
|
|
|
|
#define PSP_CMDLINE_LEN 0x80
|
|
|
|
#define PSP_CMDLINE_START 0x81
|
|
|
|
|
|
|
|
.text
|
|
|
|
.arch i386
|
|
|
|
.org 0
|
|
|
|
.code16
|
|
|
|
.section ".prefix", "awx", @progbits
|
|
|
|
|
|
|
|
signature:
|
|
|
|
/* "MZ" signature */
|
|
|
|
.ascii "MZ"
|
|
|
|
|
|
|
|
last_block:
|
|
|
|
/* Number of bytes in last block that are really used */
|
|
|
|
.word 0
|
|
|
|
|
|
|
|
blocks:
|
|
|
|
/* Number of 512-byte blocks */
|
|
|
|
.word 0
|
|
|
|
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
|
|
|
.ascii "ADDW"
|
|
|
|
.long blocks
|
|
|
|
.long 512
|
|
|
|
.long 0
|
|
|
|
.previous
|
|
|
|
|
|
|
|
num_reloc:
|
|
|
|
/* Number of relocation entries stored after the header */
|
|
|
|
.word 0
|
|
|
|
|
|
|
|
header_pgh:
|
|
|
|
/* Number of paragraphs in the header */
|
|
|
|
.word ( ( _exe_start - signature ) / 16 )
|
|
|
|
|
|
|
|
min_bss_pgh:
|
|
|
|
/* Minimum number of paragraphs of additional (BSS) memory */
|
|
|
|
.word ( EXE_STACK_SIZE / 16 )
|
|
|
|
|
|
|
|
max_bss_pgh:
|
|
|
|
/* Maximum number of paragraphs of additional (BSS) memory */
|
|
|
|
.word ( EXE_STACK_SIZE / 16 )
|
|
|
|
|
|
|
|
init_ss:
|
|
|
|
/* Initial stack segment (relative to start of executable) */
|
|
|
|
.word -( ( _exe_start - signature ) / 16 )
|
|
|
|
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
|
|
|
|
.ascii "ADDW"
|
|
|
|
.long init_ss
|
|
|
|
.long 16
|
|
|
|
.long 0
|
|
|
|
.previous
|
|
|
|
|
|
|
|
init_sp:
|
|
|
|
/* Initial stack pointer */
|
|
|
|
.word EXE_STACK_SIZE
|
|
|
|
|
|
|
|
checksum:
|
|
|
|
/* Checksum (ignored) */
|
|
|
|
.word 0
|
|
|
|
|
|
|
|
init_ip:
|
|
|
|
/* Initial instruction pointer */
|
|
|
|
.word _exe_start
|
|
|
|
|
|
|
|
init_cs:
|
|
|
|
/* Initial code segment (relative to start of executable) */
|
|
|
|
.word -( ( _exe_start - signature ) / 16 )
|
|
|
|
|
|
|
|
reloc_table:
|
|
|
|
/* Relocation table offset */
|
|
|
|
.word 0
|
|
|
|
|
|
|
|
overlay:
|
|
|
|
/* Overlay number */
|
|
|
|
.word 0
|
|
|
|
|
|
|
|
.align 16, 0
|
|
|
|
|
|
|
|
.globl _exe_start
|
|
|
|
_exe_start:
|
|
|
|
/* Install iPXE. Use a fixed temporary decompression area to
|
|
|
|
* avoid trashing the DOS high memory area.
|
|
|
|
*/
|
|
|
|
call alloc_basemem
|
|
|
|
xorl %esi, %esi
|
|
|
|
movl $EXE_DECOMPRESS_ADDRESS, %edi
|
[pcbios] Inhibit all calls to INT 15,e820 and INT 15,e801 during POST
Many BIOSes do not construct the full system memory map until after
calling the option ROM initialisation entry points. For several
years, we have added sanity checks and workarounds to accommodate
charming quirks such as BIOSes which report the entire 32-bit address
space (including all memory-mapped PCI BARs) as being usable RAM.
The IBM x3650 takes quirky behaviour to a new extreme. Calling either
INT 15,e820 or INT 15,e801 during POST doesn't just get you invalid
data. We could cope with invalid data. Instead, these nominally
read-only API calls manage to trash some internal BIOS state, with the
result that the system memory map is _never_ constructed. This tends
to confuse subsequent bootloaders and operating systems.
[ GRUB 0.97 fails in a particularly amusing way. Someone thought it
would be a good idea for memcpy() to check that the destination memory
region is a valid part of the system memory map; if not, then memcpy()
will sulk, fail, and return NULL. This breaks pretty much every use
of memcpy() including, for example, those inserted implicitly by gcc
to copy non-const initialisers. Debugging is _fun_ when a simple call
to printf() manages to create an infinite recursion, exhaust the
available stack space, and shut down the CPU. ]
Fix by completely inhibiting calls to INT 15,e820 and INT 15,e801
during POST.
We do now allow relocation during POST up to the maximum address
returned by INT 15,88 (which seems so far to always be safe). This
allows us to continue to have a reasonable size of external heap, even
if the PMM allocation is close to the 1MB mark.
The downside of allowing relocation during POST is that we may
overwrite PMM-allocated memory in use by other option ROMs. However,
the downside of inhibiting relocation, when combined with also
inhibiting calls to INT 15,e820 and INT 15,e801, would be that we
might have no external heap available: this would make booting an OS
impossible and could prevent some devices from even completing
initialisation.
On balance, the lesser evil is probably to allow relocation during
POST (up to the limit provided by INT 15,88). Entering iPXE during
POST is a rare operation; on the even rarer systems where doing so
happens to overwrite a PMM-allocated region, then there exists a
fairly simple workaround: if the user enters iPXE during POST and
wishes to exit iPXE, then the user must reboot. This is an acceptable
cost, given the rarity of the situation and the simplicity of the
workaround.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2013-03-11 01:50:52 +01:00
|
|
|
orl $0xffffffff, %ebp /* Allow arbitrary relocation */
|
2011-03-28 02:05:40 +02:00
|
|
|
call install_prealloc
|
|
|
|
|
|
|
|
/* Set up real-mode stack */
|
|
|
|
movw %bx, %ss
|
|
|
|
movw $_estack16, %sp
|
|
|
|
|
|
|
|
/* Jump to .text16 segment */
|
|
|
|
pushw %ax
|
|
|
|
pushw $1f
|
|
|
|
lret
|
|
|
|
.section ".text16", "awx", @progbits
|
|
|
|
1:
|
|
|
|
/* Terminate command line with a NUL */
|
|
|
|
movzbw PSP_CMDLINE_LEN, %si
|
|
|
|
movb $0, PSP_CMDLINE_START(%si)
|
|
|
|
|
|
|
|
/* Calculate command line physical address */
|
|
|
|
xorl %esi, %esi
|
|
|
|
movw %ds, %si
|
|
|
|
shll $4, %esi
|
|
|
|
addl $PSP_CMDLINE_START, %esi
|
|
|
|
|
|
|
|
/* Set up %ds for access to .data16 */
|
|
|
|
movw %bx, %ds
|
|
|
|
|
|
|
|
/* Record command line address */
|
|
|
|
movl %esi, cmdline_phys
|
|
|
|
|
|
|
|
/* Run iPXE */
|
|
|
|
pushl $main
|
|
|
|
pushw %cs
|
|
|
|
call prot_call
|
|
|
|
popl %ecx /* discard */
|
|
|
|
|
|
|
|
/* Uninstall iPXE */
|
|
|
|
call uninstall
|
|
|
|
|
|
|
|
/* Exit back to DOS. This is very unlikely to work */
|
|
|
|
movw $0x4c00, %ax
|
|
|
|
int $0x21
|