mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 06:52:07 +00:00
[FREELDR][NTOSKRNL][TOOLS]
- Delete unused files. - Use extension LDS instead of LNK (Windows shortcut file) for LD linker scripts. svn path=/trunk/; revision=55868
This commit is contained in:
parent
aeac841aa8
commit
1550726927
33 changed files with 540 additions and 7742 deletions
|
@ -54,7 +54,7 @@ list(APPEND FREELDR_COMMON_SOURCE
|
|||
inifile/parse.c
|
||||
mm/meminit.c
|
||||
mm/mm.c
|
||||
mm/heap_new.c
|
||||
mm/heap.c
|
||||
reactos/registry.c
|
||||
reactos/arcname.c
|
||||
reactos/archwsup.c
|
||||
|
@ -90,11 +90,11 @@ if(ARCH MATCHES i386)
|
|||
arch/i386/i386bug.c
|
||||
arch/i386/i386disk.c
|
||||
arch/i386/i386idt.c
|
||||
arch/i386/i386pnp.cmake.S
|
||||
arch/i386/i386pnp.S
|
||||
arch/i386/i386rtl.c
|
||||
arch/i386/i386trap.S
|
||||
arch/i386/i386vid.c
|
||||
arch/i386/linux.cmake.S
|
||||
arch/i386/linux.S
|
||||
arch/i386/machpc.c
|
||||
arch/i386/mb.S
|
||||
arch/i386/miscboot.c
|
||||
|
@ -165,8 +165,8 @@ add_library(freeldr_pe SHARED ${FREELDR_BASE_SOURCE})
|
|||
add_library(freeldr_pe_dbg SHARED EXCLUDE_FROM_ALL ${FREELDR_BASE_SOURCE})
|
||||
|
||||
if(NOT MSVC)
|
||||
add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
|
||||
add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
|
||||
add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
|
||||
add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
|
||||
else()
|
||||
add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION")
|
||||
add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION")
|
||||
|
@ -228,8 +228,8 @@ add_library(setupldr_pe SHARED ${FREELDR_BASE_SOURCE} ${SETUPLDR_SOURCE})
|
|||
add_library(setupldr_pe_dbg SHARED EXCLUDE_FROM_ALL ${FREELDR_BASE_SOURCE} ${SETUPLDR_SOURCE})
|
||||
|
||||
if(NOT MSVC)
|
||||
add_target_link_flags(setupldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
|
||||
add_target_link_flags(setupldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lnk")
|
||||
add_target_link_flags(setupldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
|
||||
add_target_link_flags(setupldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
|
||||
else()
|
||||
add_target_link_flags(setupldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION")
|
||||
add_target_link_flags(setupldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text /SUBSYSTEM:BOOT_APPLICATION")
|
||||
|
|
|
@ -1,511 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.intel_syntax noprefix
|
||||
#define HEX(y) 0x##y
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
#include <multiboot.h>
|
||||
|
||||
.code16
|
||||
|
||||
EXTERN(_RealEntryPoint)
|
||||
|
||||
cli
|
||||
|
||||
/* Setup segment registers */
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
/* Setup a stack */
|
||||
mov sp, word ptr ds:stack16
|
||||
|
||||
sti
|
||||
|
||||
/* Init pmode */
|
||||
call switch_to_prot
|
||||
|
||||
.code32
|
||||
|
||||
/* Zero BootPartition */
|
||||
xor eax, eax
|
||||
mov dword ptr [_FrldrBootPartition], eax
|
||||
|
||||
/* Store the boot drive */
|
||||
mov byte ptr [_FrldrBootDrive], dl
|
||||
|
||||
/* Store the boot partition */
|
||||
mov byte ptr [_FrldrBootPartition], dh
|
||||
|
||||
call _EnableA20
|
||||
|
||||
/* Clean out bss */
|
||||
xor eax, eax
|
||||
mov edi, offset __bss_start__
|
||||
mov ecx, offset __bss_end__ + 3
|
||||
sub ecx, edi
|
||||
shr ecx, 2
|
||||
rep stosd
|
||||
|
||||
/* GO! */
|
||||
push eax
|
||||
call _BootMain
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
int HEX(19)
|
||||
|
||||
/* We should never get here */
|
||||
stop:
|
||||
jmp stop
|
||||
nop
|
||||
nop
|
||||
|
||||
/*
|
||||
* Switches the processor to protected mode
|
||||
* it destroys eax
|
||||
*/
|
||||
EXTERN(switch_to_prot)
|
||||
|
||||
.code16
|
||||
|
||||
cli /* None of these */
|
||||
|
||||
/* We don't know what values are currently */
|
||||
/* in the segment registers. So we are */
|
||||
/* going to reload them with sane values. */
|
||||
/* Of course CS has to already be valid. */
|
||||
/* We are currently in real-mode so we */
|
||||
/* need real-mode segment values. */
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
/* Get the return address off the stack */
|
||||
pop word ptr ds:[code32ret]
|
||||
|
||||
/* Save 16-bit stack pointer */
|
||||
mov word ptr ds:[stack16], sp
|
||||
|
||||
/* Load the GDT */
|
||||
lgdt gdtptr
|
||||
/* Load the IDT */
|
||||
lidt i386idtptr
|
||||
|
||||
/* Enable Protected Mode */
|
||||
mov eax, cr0
|
||||
or eax, CR0_PE_SET
|
||||
mov cr0, eax
|
||||
|
||||
/* Clear prefetch queue & correct CS */
|
||||
//ljmp PMODE_CS, inpmode
|
||||
jmp far ptr PMODE_CS:inpmode
|
||||
|
||||
.code32
|
||||
|
||||
inpmode:
|
||||
/* Setup segment selectors */
|
||||
mov ax, PMODE_DS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
mov esp, dword ptr [stack32]
|
||||
|
||||
/* Put the return address back onto the stack */
|
||||
push dword ptr [code32ret]
|
||||
|
||||
/* Now return in p-mode! */
|
||||
ret
|
||||
|
||||
/*
|
||||
* Switches the processor back to real mode
|
||||
* it destroys eax
|
||||
*/
|
||||
EXTERN(switch_to_real)
|
||||
|
||||
.code32
|
||||
|
||||
/* We don't know what values are currently */
|
||||
/* in the segment registers. So we are */
|
||||
/* going to reload them with sane values. */
|
||||
/* Of course CS has to already be valid. */
|
||||
/* We are currently in protected-mode so we */
|
||||
/* need protected-mode segment values. */
|
||||
mov ax, PMODE_DS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
/* Get the return address off the stack */
|
||||
pop dword ptr [code16ret]
|
||||
|
||||
/* Save 32-bit stack pointer */
|
||||
mov dword ptr [stack32], esp
|
||||
|
||||
/* jmp to 16-bit segment to set the limit correctly */
|
||||
ljmp RMODE_CS, switch_to_real16
|
||||
|
||||
switch_to_real16:
|
||||
.code16
|
||||
|
||||
/* Restore segment registers to correct limit */
|
||||
mov ax, RMODE_DS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
/* Disable Protected Mode */
|
||||
mov eax, cr0
|
||||
and eax, CR0_PE_CLR
|
||||
mov cr0, eax
|
||||
|
||||
/* Clear prefetch queue & correct CS */
|
||||
//ljmp $0, $inrmode
|
||||
jmp far ptr 0:inrmode
|
||||
|
||||
inrmode:
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
/* Clear out the high 16-bits of ESP */
|
||||
/* This is needed because I have one */
|
||||
/* machine that hangs when booted to dos if */
|
||||
/* anything other than 0x0000 is in the high */
|
||||
/* 16-bits of ESP. Even though real-mode */
|
||||
/* code should only use SP and not ESP. */
|
||||
xor esp, esp
|
||||
|
||||
mov sp, word ptr ds:[stack16]
|
||||
|
||||
/* Put the return address back onto the stack */
|
||||
push word ptr ds:[code16ret]
|
||||
|
||||
/* Load IDTR with real mode value */
|
||||
lidt rmode_idtptr
|
||||
|
||||
sti /* These are ok now */
|
||||
|
||||
/* Now return in r-mode! */
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* Needed for enabling the a20 address line
|
||||
*/
|
||||
.code16
|
||||
empty_8042:
|
||||
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
|
||||
in al, HEX(64)
|
||||
cmp al, HEX(ff) // legacy-free machine without keyboard
|
||||
jz empty_8042_ret // controllers on Intel Macs read back 0xFF
|
||||
test al, 2
|
||||
jnz empty_8042
|
||||
empty_8042_ret:
|
||||
ret
|
||||
|
||||
/*
|
||||
* Enable the A20 address line (to allow access to over 1mb)
|
||||
*/
|
||||
EXTERN(_EnableA20)
|
||||
.code32
|
||||
|
||||
pusha
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
call empty_8042
|
||||
mov al, HEX(D1) // command write
|
||||
out HEX(64), al
|
||||
call empty_8042
|
||||
mov al, HEX(DF) // A20 on
|
||||
out HEX(60), al
|
||||
call empty_8042
|
||||
call switch_to_prot
|
||||
.code32
|
||||
|
||||
popa
|
||||
|
||||
ret
|
||||
|
||||
/*
|
||||
* Disable the A20 address line
|
||||
*/
|
||||
EXTERN(_DisableA20)
|
||||
.code32
|
||||
|
||||
pusha
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
call empty_8042
|
||||
mov al, HEX(D1) // command write
|
||||
out HEX(64), al
|
||||
call empty_8042
|
||||
mov al, HEX(DD) // A20 off
|
||||
out HEX(60), al
|
||||
call empty_8042
|
||||
call switch_to_prot
|
||||
.code32
|
||||
|
||||
popa
|
||||
|
||||
ret
|
||||
|
||||
/* Multiboot support
|
||||
*
|
||||
* Allows freeldr to be loaded as a "multiboot kernel" by
|
||||
* other boot loaders like Grub
|
||||
*/
|
||||
|
||||
#define MB_INFO_SIZE 90
|
||||
#define MB_INFO_FLAGS_OFFSET 0
|
||||
#define MB_INFO_BOOT_DEVICE_OFFSET 12
|
||||
#define MB_INFO_COMMAND_LINE_OFFSET 16
|
||||
#define CMDLINE_SIZE 256
|
||||
|
||||
/*
|
||||
* We want to execute at 0x8000 (to be compatible with bootsector
|
||||
* loading), but Grub only allows loading of multiboot kernels
|
||||
* above 1MB. So we let Grub load us there and then relocate
|
||||
* ourself to 0x8000
|
||||
*/
|
||||
#define FREELDR_BASE HEX(8000)
|
||||
#define INITIAL_BASE HEX(200000)
|
||||
|
||||
/* Align 32 bits boundary */
|
||||
.align 4
|
||||
|
||||
/* Multiboot header */
|
||||
MultibootHeader:
|
||||
/* magic */
|
||||
.long MULTIBOOT_HEADER_MAGIC
|
||||
/* flags */
|
||||
.long MULTIBOOT_HEADER_FLAGS
|
||||
/* checksum */
|
||||
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
/* header_addr */
|
||||
.long INITIAL_BASE + MultibootHeader - FREELDR_BASE
|
||||
/* load_addr */
|
||||
.long INITIAL_BASE
|
||||
/* load_end_addr */
|
||||
.long INITIAL_BASE + __bss_start__ - FREELDR_BASE
|
||||
/* bss_end_addr */
|
||||
.long INITIAL_BASE + __bss_end__ - FREELDR_BASE
|
||||
/* entry_addr */
|
||||
.long INITIAL_BASE + MultibootEntry - FREELDR_BASE
|
||||
|
||||
MultibootEntry:
|
||||
cli /* Even after setting up the our IDT below we are
|
||||
* not ready to handle hardware interrupts (no entries
|
||||
* in IDT), so there's no sti here. Interrupts will be
|
||||
* enabled in due time */
|
||||
|
||||
/* Although the multiboot spec says we should be called with the
|
||||
* segment registers set to 4GB flat mode, let's be sure and set up
|
||||
* our own */
|
||||
lgdt gdtptrhigh + INITIAL_BASE - FREELDR_BASE
|
||||
/* Reload segment selectors */
|
||||
//ljmp $PMODE_CS, $(mb1 + INITIAL_BASE - FREELDR_BASE)
|
||||
jmp far ptr PMODE_CS: (mb1 + INITIAL_BASE - FREELDR_BASE)
|
||||
mb1:
|
||||
mov dx, PMODE_DS
|
||||
mov ds, dx
|
||||
mov es, dx
|
||||
|
||||
/* Check for valid multiboot signature */
|
||||
cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
|
||||
jne mbfail
|
||||
|
||||
/* Store multiboot info in a safe place */
|
||||
mov esi, ebx
|
||||
mov edi, offset mb_info + INITIAL_BASE - FREELDR_BASE
|
||||
mov ecx, MB_INFO_SIZE
|
||||
rep movsb
|
||||
|
||||
/* Save commandline */
|
||||
mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
|
||||
test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
|
||||
jz mb3
|
||||
mov esi, [ebx + MB_INFO_COMMAND_LINE_OFFSET]
|
||||
mov edi, offset cmdline + INITIAL_BASE - FREELDR_BASE
|
||||
mov ecx, CMDLINE_SIZE
|
||||
mb2: lodsb
|
||||
stosb
|
||||
test al, al
|
||||
jz mb3
|
||||
dec ecx
|
||||
jnz mb2
|
||||
mb3:
|
||||
|
||||
/* Copy to low mem */
|
||||
mov esi, INITIAL_BASE
|
||||
mov edi, FREELDR_BASE
|
||||
mov ecx, (offset __bss_end__ - FREELDR_BASE)
|
||||
add ecx, 3
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
|
||||
/* Load the GDT and IDT */
|
||||
lgdt gdtptr
|
||||
lidt i386idtptr
|
||||
|
||||
/* Clear prefetch queue & correct CS,
|
||||
* jump to low mem */
|
||||
//ljmp $PMODE_CS, $mb4
|
||||
jmp far ptr PMODE_CS:mb4
|
||||
mb4:
|
||||
/* Reload segment selectors */
|
||||
mov dx, PMODE_DS
|
||||
mov ds, dx
|
||||
mov es, dx
|
||||
mov fs, dx
|
||||
mov gs, dx
|
||||
mov ss, dx
|
||||
mov esp, STACK32ADDR
|
||||
|
||||
mov ebx, offset mb_info
|
||||
/* See if the boot device was passed in */
|
||||
mov edx, [ebx + MB_INFO_FLAGS_OFFSET]
|
||||
test edx, MB_INFO_FLAG_BOOT_DEVICE
|
||||
jz mb5
|
||||
/* Retrieve boot device info */
|
||||
mov eax, [ebx + MB_INFO_BOOT_DEVICE_OFFSET]
|
||||
shr eax, 16
|
||||
inc al
|
||||
mov byte ptr _FrldrBootPartition, al
|
||||
mov byte ptr _FrldrBootDrive, ah
|
||||
jmp mb6
|
||||
mb5: /* No boot device known, assume first partition of first harddisk */
|
||||
mov byte ptr _FrldrBootDrive, HEX(80)
|
||||
mov byte ptr _FrldrBootPartition, 1
|
||||
mb6:
|
||||
/* Check for command line */
|
||||
mov eax, offset cmdline
|
||||
test dword ptr [ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
|
||||
jnz mb7
|
||||
xor eax, eax
|
||||
mb7:
|
||||
|
||||
/* GO! */
|
||||
push eax
|
||||
call _BootMain
|
||||
|
||||
mbfail:
|
||||
call switch_to_real
|
||||
.code16
|
||||
int 0x19
|
||||
mbstop: jmp mbstop /* We should never get here */
|
||||
|
||||
.code32
|
||||
|
||||
/* 16-bit stack pointer */
|
||||
stack16:
|
||||
.word STACK16ADDR
|
||||
|
||||
/* 32-bit stack pointer */
|
||||
stack32:
|
||||
.long STACK32ADDR
|
||||
|
||||
/* 16-bit return address */
|
||||
code16ret:
|
||||
.long 0
|
||||
|
||||
/* 32-bit return address */
|
||||
code32ret:
|
||||
.long 0
|
||||
|
||||
|
||||
.align 4 /* force 4-byte alignment */
|
||||
gdt:
|
||||
/* NULL Descriptor */
|
||||
.word HEX(0000)
|
||||
.word HEX(0000)
|
||||
.word HEX(0000)
|
||||
.word HEX(0000)
|
||||
|
||||
/* 32-bit flat CS */
|
||||
.word HEX(FFFF)
|
||||
.word HEX(0000)
|
||||
.word HEX(9A00)
|
||||
.word HEX(00CF)
|
||||
|
||||
/* 32-bit flat DS */
|
||||
.word HEX(FFFF)
|
||||
.word HEX(0000)
|
||||
.word HEX(9200)
|
||||
.word HEX(00CF)
|
||||
|
||||
/* 16-bit real mode CS */
|
||||
.word HEX(FFFF)
|
||||
.word HEX(0000)
|
||||
.word HEX(9E00)
|
||||
.word HEX(0000)
|
||||
|
||||
/* 16-bit real mode DS */
|
||||
.word HEX(FFFF)
|
||||
.word HEX(0000)
|
||||
.word HEX(9200)
|
||||
.word HEX(0000)
|
||||
|
||||
/* GDT table pointer */
|
||||
gdtptr:
|
||||
.word HEX(27) /* Limit */
|
||||
.long gdt /* Base Address */
|
||||
|
||||
/* Initial GDT table pointer for multiboot */
|
||||
gdtptrhigh:
|
||||
.word HEX(27) /* Limit */
|
||||
.long gdt + INITIAL_BASE - FREELDR_BASE /* Base Address */
|
||||
|
||||
/* Real-mode IDT pointer */
|
||||
rmode_idtptr:
|
||||
.word HEX(3ff) /* Limit */
|
||||
.long 0 /* Base Address */
|
||||
|
||||
mb_info:
|
||||
.fill MB_INFO_SIZE, 1, 0
|
||||
|
||||
cmdline:
|
||||
.fill CMDLINE_SIZE, 1, 0
|
||||
|
||||
EXTERN(_FrldrBootDrive)
|
||||
.byte 0
|
||||
|
||||
EXTERN(_FrldrBootPartition)
|
||||
.long 0
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
EXTERN(_ChainLoadBiosBootSectorCode)
|
||||
.code32
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
/* Set the boot drive */
|
||||
movb (_FrldrBootDrive),%dl
|
||||
|
||||
/* Load segment registers */
|
||||
cli
|
||||
movw $0x0000,%bx
|
||||
movw %bx,%ds
|
||||
movw %bx,%es
|
||||
movw %bx,%fs
|
||||
movw %bx,%gs
|
||||
movw %bx,%ss
|
||||
movw $0x7C00,%sp
|
||||
|
||||
ljmpl $0x0000,$0x7C00
|
||||
|
||||
EXTERN(_SoftReboot)
|
||||
.code32
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
movw $0x40,%ax
|
||||
movw %ax,%ds
|
||||
movw $0x72,%si
|
||||
|
||||
// Set the word at location 40:72 to 1234h
|
||||
movw $0x1234,(%si)
|
||||
|
||||
// and jump to location FFFF:0 in ROM
|
||||
ljmpl $0xFFFF,$0x0000
|
|
@ -1,241 +0,0 @@
|
|||
// fathelp.S
|
||||
// FAT12/16 Boot Sector Helper Code
|
||||
// Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
//org 8000h
|
||||
|
||||
//.text
|
||||
|
||||
.code16
|
||||
|
||||
|
||||
#define BootSectorStackTop HEX(7bf2)
|
||||
#define DataAreaStartHigh 2
|
||||
#define DataAreaStartLow 4
|
||||
#define BiosCHSDriveSizeHigh 6
|
||||
#define BiosCHSDriveSizeLow 8
|
||||
#define BiosCHSDriveSize 8
|
||||
#define ReadSectorsOffset 10
|
||||
#define ReadClusterOffset 12
|
||||
#define PutCharsOffset 14
|
||||
|
||||
#define OEMName 3
|
||||
#define BytesPerSector 11
|
||||
#define SectsPerCluster 13
|
||||
#define ReservedSectors 14
|
||||
#define NumberOfFats 16
|
||||
#define MaxRootEntries 17
|
||||
#define TotalSectors 19
|
||||
#define MediaDescriptor 21
|
||||
#define SectorsPerFat 22
|
||||
#define SectorsPerTrack 24
|
||||
#define NumberOfHeads 26
|
||||
#define HiddenSectors 28
|
||||
#define TotalSectorsBig 32
|
||||
#define BootDrive 36
|
||||
#define Reserved 37
|
||||
#define ExtendSig 38
|
||||
#define SerialNumber 39
|
||||
#define VolumeLabel 43
|
||||
#define FileSystem 54
|
||||
|
||||
#define BootPartition HEX(7dfd)
|
||||
|
||||
|
||||
// This code will be stored in the first 512 bytes
|
||||
// of freeldr.sys. The first 3 bytes will be a jmp
|
||||
// instruction to skip past the FAT helper code
|
||||
// that is stored in the rest of the 512 bytes.
|
||||
//
|
||||
// This code is loaded at 0000:8000 so we have to
|
||||
// encode a jmp instruction to jump to 0000:8200
|
||||
|
||||
PUBLIC _mainCRTStartup // For Mingw32 builds where the linker looks for this symbol
|
||||
_mainCRTStartup:
|
||||
PUBLIC start
|
||||
start:
|
||||
#if 0
|
||||
.byte HEX(e9)
|
||||
.byte HEX(fd)
|
||||
.byte HEX(01)
|
||||
|
||||
// Now starts the extra boot code that we will store
|
||||
// in the first 512 bytes of freeldr.sys. This code
|
||||
// allows the FAT12/16 bootsector to navigate the
|
||||
// FAT table so that we can still load freeldr.sys
|
||||
// even if it is fragmented.
|
||||
|
||||
|
||||
FatHelperEntryPoint:
|
||||
|
||||
push ax // First save AX - the start cluster of freeldr.sys
|
||||
|
||||
|
||||
// Display "Loading FreeLoader..." message
|
||||
mov esi, offset msgLoading // Loading message
|
||||
call word ptr [bp-PutCharsOffset] // Display it
|
||||
|
||||
|
||||
call ReadFatIntoMemory
|
||||
|
||||
pop ax // Restore AX (start cluster)
|
||||
// AX has start cluster of freeldr.sys
|
||||
|
||||
mov bx, HEX(800)
|
||||
mov es,bx
|
||||
|
||||
LoadFile:
|
||||
push ax
|
||||
call IsFat12
|
||||
pop ax
|
||||
jnc LoadFile2
|
||||
cmp ax, HEX(0ff8) // Check to see if this is the last cluster in the chain
|
||||
jmp LoadFile3
|
||||
LoadFile2:
|
||||
cmp ax, HEX(0fff8)
|
||||
LoadFile3:
|
||||
jae LoadFile_Done // If so continue, if not then read then next one
|
||||
push ax
|
||||
xor bx,bx // Load ROSLDR starting at 0000:8000h
|
||||
push es
|
||||
call word ptr [bp-ReadClusterOffset]
|
||||
pop es
|
||||
|
||||
xor bx,bx
|
||||
mov bl, [bp+SectsPerCluster]
|
||||
shl bx,5 // BX = BX * 512 / 16
|
||||
mov ax,es // Increment the load address by
|
||||
add ax,bx // The size of a cluster
|
||||
mov es,ax
|
||||
|
||||
call IsFat12
|
||||
pop ax
|
||||
push es
|
||||
jnc LoadFile4
|
||||
call GetFatEntry12 // Get the next entry
|
||||
jmp LoadFile5
|
||||
LoadFile4:
|
||||
call GetFatEntry16
|
||||
LoadFile5:
|
||||
pop es
|
||||
|
||||
jmp LoadFile // Load the next cluster (if any)
|
||||
|
||||
LoadFile_Done:
|
||||
mov dl, byte ptr [bp+BootDrive] // Load the boot drive into DL
|
||||
mov dh, byte ptr ds:[BootPartition] // Load the boot partition into DH
|
||||
|
||||
push 0 // push segment (0x0000)
|
||||
mov bx, ds: [HEX(8000) + HEX(A8)] // load the RVA of the EntryPoint into eax
|
||||
add bx, HEX(8000) // RVA -> VA and skip 3 bytes (jump to fathelper code)
|
||||
push bx // push offset
|
||||
retf // Transfer control to FreeLoader
|
||||
|
||||
// Reads the entire FAT into memory at 7000:0000
|
||||
ReadFatIntoMemory:
|
||||
mov ax, [bp+HiddenSectors]
|
||||
mov dx, [bp+HiddenSectors+2]
|
||||
add ax, [bp+ReservedSectors]
|
||||
adc dx, 0
|
||||
mov cx, [bp+SectorsPerFat]
|
||||
mov bx, HEX(7000)
|
||||
mov es,bx
|
||||
xor bx,bx
|
||||
call word ptr [bp-ReadSectorsOffset]
|
||||
ret
|
||||
|
||||
|
||||
// Returns the FAT entry for a given cluster number for 16-bit FAT
|
||||
// On entry AX has cluster number
|
||||
// On return AX has FAT entry for that cluster
|
||||
GetFatEntry16:
|
||||
|
||||
mov cx,2 // AX = AX * 2 (since FAT16 entries are 2 bytes)
|
||||
mul cx
|
||||
shl dx,12
|
||||
|
||||
mov bx, HEX(7000)
|
||||
add bx,dx
|
||||
mov es,bx
|
||||
mov bx,ax // Restore FAT entry offset
|
||||
mov ax, es:[bx] // Get FAT entry
|
||||
|
||||
ret
|
||||
|
||||
|
||||
// Returns the FAT entry for a given cluster number for 12-bit FAT
|
||||
// On entry AX has cluster number
|
||||
// On return AX has FAT entry for that cluster
|
||||
GetFatEntry12:
|
||||
|
||||
push ax
|
||||
mov cx,ax
|
||||
shr ax,1
|
||||
add ax,cx // AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
|
||||
|
||||
mov bx, HEX(7000)
|
||||
mov es,bx
|
||||
mov bx,ax // Put FAT entry offset into BX
|
||||
mov ax, es:[bx] // Get FAT entry
|
||||
pop cx // Get cluster number from stack
|
||||
and cx,1
|
||||
jz UseLow12Bits
|
||||
and ax, HEX(0fff0)
|
||||
shr ax,4
|
||||
jmp GetFatEntry12_Done
|
||||
|
||||
UseLow12Bits:
|
||||
and ax, HEX(0fff)
|
||||
|
||||
GetFatEntry12_Done:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
// Returns CF = 1 if this is a FAT12 file system
|
||||
// Otherwise CF = 0 for FAT16
|
||||
IsFat12:
|
||||
|
||||
mov ebx, dword ptr [bp-DataAreaStartLow]
|
||||
// EBX now has the number of the starting sector of the data area
|
||||
// starting from the beginning of the disk, so subtrace hidden sectors
|
||||
sub ebx, dword ptr [bp+HiddenSectors]
|
||||
|
||||
|
||||
xor eax,eax
|
||||
mov ax, word ptr [bp+TotalSectors]
|
||||
cmp ax, 0
|
||||
jnz IsFat12_2
|
||||
mov eax, dword ptr [bp+TotalSectorsBig]
|
||||
|
||||
// EAX now contains the number of sectors on the volume
|
||||
|
||||
IsFat12_2:
|
||||
sub eax,ebx // Subtract data area start sector
|
||||
xor edx,edx // from total sectors of volume
|
||||
|
||||
// EDX:EAX now contains the number of data sectors on the volume
|
||||
movzx ebx, byte ptr [bp+SectsPerCluster]
|
||||
div ebx
|
||||
// EAX now has the number of clusters on the volume
|
||||
stc
|
||||
cmp eax,4085
|
||||
jb IsFat12_Done
|
||||
clc
|
||||
|
||||
IsFat12_Done:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
msgLoading: .asciz "Loading FreeLoader...\r\n"
|
||||
|
||||
.org HEX(1fe) // Pad to 510 bytes
|
||||
.word HEX(0aa55) // BootSector signature
|
||||
#endif
|
||||
|
||||
.endcode16
|
||||
|
||||
END
|
|
@ -1,235 +0,0 @@
|
|||
; FATHELP.ASM
|
||||
; FAT12/16 Boot Sector Helper Code
|
||||
; Copyright (c) 1998, 2001, 2002, 2003 Brian Palmer
|
||||
|
||||
|
||||
|
||||
;org 8000h
|
||||
|
||||
segment .text
|
||||
|
||||
bits 16
|
||||
|
||||
|
||||
BootSectorStackTop equ 0x7bf2
|
||||
DataAreaStartHigh equ 0x2
|
||||
DataAreaStartLow equ 0x4
|
||||
BiosCHSDriveSizeHigh equ 0x6
|
||||
BiosCHSDriveSizeLow equ 0x8
|
||||
BiosCHSDriveSize equ 0x8
|
||||
ReadSectorsOffset equ 0xa
|
||||
ReadClusterOffset equ 0xc
|
||||
PutCharsOffset equ 0xe
|
||||
|
||||
OEMName equ 3
|
||||
BytesPerSector equ 11
|
||||
SectsPerCluster equ 13
|
||||
ReservedSectors equ 14
|
||||
NumberOfFats equ 16
|
||||
MaxRootEntries equ 17
|
||||
TotalSectors equ 19
|
||||
MediaDescriptor equ 21
|
||||
SectorsPerFat equ 22
|
||||
SectorsPerTrack equ 24
|
||||
NumberOfHeads equ 26
|
||||
HiddenSectors equ 28
|
||||
TotalSectorsBig equ 32
|
||||
BootDrive equ 36
|
||||
Reserved equ 37
|
||||
ExtendSig equ 38
|
||||
SerialNumber equ 39
|
||||
VolumeLabel equ 43
|
||||
FileSystem equ 54
|
||||
|
||||
BootPartition equ 0x7dfd
|
||||
|
||||
|
||||
; This code will be stored in the first 512 bytes
|
||||
; of freeldr.sys. The first 3 bytes will be a jmp
|
||||
; instruction to skip past the FAT helper code
|
||||
; that is stored in the rest of the 512 bytes.
|
||||
;
|
||||
; This code is loaded at 0000:8000 so we have to
|
||||
; encode a jmp instruction to jump to 0000:8200
|
||||
|
||||
global _mainCRTStartup ; For Mingw32 builds where the linker looks for this symbol
|
||||
_mainCRTStartup:
|
||||
global start
|
||||
start:
|
||||
db 0xe9
|
||||
db 0xfd
|
||||
db 0x01
|
||||
|
||||
; Now starts the extra boot code that we will store
|
||||
; in the first 512 bytes of freeldr.sys. This code
|
||||
; allows the FAT12/16 bootsector to navigate the
|
||||
; FAT table so that we can still load freeldr.sys
|
||||
; even if it is fragmented.
|
||||
|
||||
|
||||
FatHelperEntryPoint:
|
||||
|
||||
push ax ; First save AX - the start cluster of freeldr.sys
|
||||
|
||||
|
||||
; Display "Loading FreeLoader..." message
|
||||
mov esi,msgLoading ; Loading message
|
||||
call [bp-PutCharsOffset] ; Display it
|
||||
|
||||
|
||||
call ReadFatIntoMemory
|
||||
|
||||
pop ax ; Restore AX (start cluster)
|
||||
; AX has start cluster of freeldr.sys
|
||||
|
||||
mov bx,800h
|
||||
mov es,bx
|
||||
|
||||
LoadFile:
|
||||
push ax
|
||||
call IsFat12
|
||||
pop ax
|
||||
jnc LoadFile2
|
||||
cmp ax,0ff8h ; Check to see if this is the last cluster in the chain
|
||||
jmp LoadFile3
|
||||
LoadFile2:
|
||||
cmp ax,0fff8h
|
||||
LoadFile3:
|
||||
jae LoadFile_Done ; If so continue, if not then read then next one
|
||||
push ax
|
||||
xor bx,bx ; Load ROSLDR starting at 0000:8000h
|
||||
push es
|
||||
call [bp-ReadClusterOffset]
|
||||
pop es
|
||||
|
||||
xor bx,bx
|
||||
mov bl,BYTE [BYTE bp+SectsPerCluster]
|
||||
shl bx,5 ; BX = BX * 512 / 16
|
||||
mov ax,es ; Increment the load address by
|
||||
add ax,bx ; The size of a cluster
|
||||
mov es,ax
|
||||
|
||||
call IsFat12
|
||||
pop ax
|
||||
push es
|
||||
jnc LoadFile4
|
||||
call GetFatEntry12 ; Get the next entry
|
||||
jmp LoadFile5
|
||||
LoadFile4:
|
||||
call GetFatEntry16
|
||||
LoadFile5:
|
||||
pop es
|
||||
|
||||
jmp LoadFile ; Load the next cluster (if any)
|
||||
|
||||
LoadFile_Done:
|
||||
mov dl,BYTE [BYTE bp+BootDrive] ; Load the boot drive into DL
|
||||
mov dh,[BootPartition] ; Load the boot partition into DH
|
||||
|
||||
push 0 ; push segment (0x0000)
|
||||
mov bx, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
|
||||
add bx, 0x8000 ; RVA -> VA and skip 3 bytes (jump to fathelper code)
|
||||
push bx ; push offset
|
||||
retf ; Transfer control to FreeLoader
|
||||
|
||||
; Reads the entire FAT into memory at 7000:0000
|
||||
ReadFatIntoMemory:
|
||||
mov ax,WORD [BYTE bp+HiddenSectors]
|
||||
mov dx,WORD [BYTE bp+HiddenSectors+2]
|
||||
add ax,WORD [BYTE bp+ReservedSectors]
|
||||
adc dx,byte 0
|
||||
mov cx,WORD [BYTE bp+SectorsPerFat]
|
||||
mov bx,7000h
|
||||
mov es,bx
|
||||
xor bx,bx
|
||||
call [bp-ReadSectorsOffset]
|
||||
ret
|
||||
|
||||
|
||||
; Returns the FAT entry for a given cluster number for 16-bit FAT
|
||||
; On entry AX has cluster number
|
||||
; On return AX has FAT entry for that cluster
|
||||
GetFatEntry16:
|
||||
|
||||
mov cx,2 ; AX = AX * 2 (since FAT16 entries are 2 bytes)
|
||||
mul cx
|
||||
shl dx,12
|
||||
|
||||
mov bx,7000h
|
||||
add bx,dx
|
||||
mov es,bx
|
||||
mov bx,ax ; Restore FAT entry offset
|
||||
mov ax,WORD [es:bx] ; Get FAT entry
|
||||
|
||||
ret
|
||||
|
||||
|
||||
; Returns the FAT entry for a given cluster number for 12-bit FAT
|
||||
; On entry AX has cluster number
|
||||
; On return AX has FAT entry for that cluster
|
||||
GetFatEntry12:
|
||||
|
||||
push ax
|
||||
mov cx,ax
|
||||
shr ax,1
|
||||
add ax,cx ; AX = AX * 1.5 (AX = AX + (AX / 2)) (since FAT12 entries are 12 bits)
|
||||
|
||||
mov bx,7000h
|
||||
mov es,bx
|
||||
mov bx,ax ; Put FAT entry offset into BX
|
||||
mov ax,WORD [es:bx] ; Get FAT entry
|
||||
pop cx ; Get cluster number from stack
|
||||
and cx,1
|
||||
jz UseLow12Bits
|
||||
and ax,0fff0h
|
||||
shr ax,4
|
||||
jmp GetFatEntry12_Done
|
||||
|
||||
UseLow12Bits:
|
||||
and ax,0fffh
|
||||
|
||||
GetFatEntry12_Done:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
; Returns CF = 1 if this is a FAT12 file system
|
||||
; Otherwise CF = 0 for FAT16
|
||||
IsFat12:
|
||||
|
||||
mov ebx,DWORD [BYTE bp-DataAreaStartLow]
|
||||
; EBX now has the number of the starting sector of the data area
|
||||
; starting from the beginning of the disk, so subtrace hidden sectors
|
||||
sub ebx,DWORD [BYTE bp+HiddenSectors]
|
||||
|
||||
|
||||
xor eax,eax
|
||||
mov ax,WORD [BYTE bp+TotalSectors]
|
||||
cmp ax,byte 0
|
||||
jnz IsFat12_2
|
||||
mov eax,DWORD [BYTE bp+TotalSectorsBig]
|
||||
|
||||
; EAX now contains the number of sectors on the volume
|
||||
|
||||
IsFat12_2:
|
||||
sub eax,ebx ; Subtract data area start sector
|
||||
xor edx,edx ; from total sectors of volume
|
||||
|
||||
; EDX:EAX now contains the number of data sectors on the volume
|
||||
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
|
||||
div ebx
|
||||
; EAX now has the number of clusters on the volume
|
||||
stc
|
||||
cmp eax,4085
|
||||
jb IsFat12_Done
|
||||
clc
|
||||
|
||||
IsFat12_Done:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
|
||||
|
||||
times 510-($-$$) db 0 ; Pad to 510 bytes
|
||||
dw 0aa55h ; BootSector signature
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2003 Eric Kohl
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
/*
|
||||
* U32 CpuidSupported(VOID);
|
||||
*
|
||||
* RETURNS:
|
||||
* 0x00000001: CPU supports the CPUID instruction
|
||||
* 0x00000300: Found 80386 CPU
|
||||
* 0x00000400: Found 80486 CPU without CPUID support
|
||||
*/
|
||||
|
||||
EXTERN(_CpuidSupported)
|
||||
.code32
|
||||
|
||||
pushl %ecx /* save ECX */
|
||||
|
||||
pushfl /* push original EFLAGS */
|
||||
popl %eax /* get original EFLAGS */
|
||||
movl %eax,%ecx /* save original EFLAGS */
|
||||
xorl $0x40000,%eax /* flip AC bit in EFLAGS */
|
||||
pushl %eax /* save new EFLAGS value on stack */
|
||||
popfl /* replace current EFLAGS value */
|
||||
|
||||
pushfl /* get new EFLAGS */
|
||||
popl %eax /* store new EFLAGS in EAX */
|
||||
xorl %ecx, %eax /* can't toggle AC bit, processor=80386 */
|
||||
|
||||
movl $0x300,%eax /* return processor id */
|
||||
jz NoCpuid /* jump if 80386 processor */
|
||||
|
||||
pushl %ecx
|
||||
popfl /* restore AC bit in EFLAGS first */
|
||||
|
||||
movl %ecx,%eax /* get original EFLAGS */
|
||||
xorl $0x200000,%eax /* flip ID bit in EFLAGS */
|
||||
pushl %eax /* save new EFLAGS value on stack */
|
||||
popfl /* replace current EFLAGS value */
|
||||
pushfl /* get new EFLAGS */
|
||||
popl %eax /* store new EFLAGS in EAX */
|
||||
xorl %ecx,%eax /* can't toggle ID bit, */
|
||||
|
||||
movl $0x400,%eax /* return processor id */
|
||||
je NoCpuid /* processor=80486 */
|
||||
|
||||
movl $1,%eax /* CPUID supported */
|
||||
|
||||
NoCpuid:
|
||||
pushl %ecx
|
||||
popfl /* restore EFLAGS */
|
||||
popl %ecx /* retore ECX */
|
||||
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* VOID GetCpuid(U32 Level, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx);
|
||||
*/
|
||||
|
||||
EXTERN(_GetCpuid)
|
||||
.code32
|
||||
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
pushl %eax
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
|
||||
movl 0x08(%ebp),%eax
|
||||
|
||||
cpuid
|
||||
|
||||
movl 0x0C(%ebp),%esi
|
||||
movl %eax,(%esi)
|
||||
|
||||
movl 0x10(%ebp),%esi
|
||||
movl %ebx,(%esi)
|
||||
|
||||
movl 0x14(%ebp),%esi
|
||||
movl %ecx,(%esi)
|
||||
|
||||
movl 0x18(%ebp),%esi
|
||||
movl %edx,(%esi)
|
||||
|
||||
popl %esi
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
popl %eax
|
||||
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* U64 RDTSC(VOID);
|
||||
*/
|
||||
|
||||
EXTERN(_RDTSC)
|
||||
.code32
|
||||
rdtsc
|
||||
ret
|
||||
|
||||
/* EOF */
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
EXTERN(i386idt)
|
||||
/* Exception 0 - Divide By Zero */
|
||||
.word _i386DivideByZero /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Flags, Zero Byte */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 1 - Debug Exception */
|
||||
.word _i386DebugException /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 2 - NMI */
|
||||
.word _i386NMIException /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 3 - Breakpoint (INT 3) */
|
||||
.word _i386Breakpoint /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 4 - Overflow (INTO with EFLAGS[OF] set) */
|
||||
.word _i386Overflow /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 5 - Bound Exception */
|
||||
.word _i386BoundException /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 6 - Invalid Opcode */
|
||||
.word _i386InvalidOpcode /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 7 - FPU Not Available */
|
||||
.word _i386FPUNotAvailable /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 8 - Double Fault */
|
||||
.word _i386DoubleFault /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 9 - Coprocessor Segment Overrun */
|
||||
.word _i386CoprocessorSegment /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 10 (0x0A) - Invalid TSS */
|
||||
.word _i386InvalidTSS /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 11 (0x0B) - Segment Not Present */
|
||||
.word _i386SegmentNotPresent /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 12 (0x0C) - Stack Exception */
|
||||
.word _i386StackException /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 13 (0x0D) - General Protection Fault */
|
||||
.word _i386GeneralProtectionFault /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 14 (0x0E) - Page Fault */
|
||||
.word _i386PageFault /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 15 (0x0F) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 16 (0x10) - Coprocessor Error */
|
||||
.word _i386CoprocessorError /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 17 (0x11) - Alignment Check */
|
||||
.word _i386AlignmentCheck /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 18 (0x12) - Machine Check */
|
||||
.word _i386MachineCheck /* Offset 0 - 15 */
|
||||
.word 0x0008 /* Selector */
|
||||
.word 0x8e00 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 19 (0x13) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 20 (0x14) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 21 (0x15) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 22 (0x16) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 23 (0x17) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 24 (0x18) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 25 (0x19) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 26 (0x1A) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 27 (0x1B) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 28 (0x1C) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 29 (0x1D) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 30 (0x1E) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* Exception 31 (0x1F) - Reserved */
|
||||
.word 0x0000 /* Offset 0 - 15 */
|
||||
.word 0x0000 /* Selector */
|
||||
.word 0x0000 /* Zero byte, flags */
|
||||
.word 0x0000 /* Offset 16 - 31 */
|
||||
|
||||
/* IDT table pointer */
|
||||
EXTERN(i386idtptr)
|
||||
.word (i386idtptr - i386idt - 1) /* Limit */
|
||||
.long i386idt /* Base Address */
|
|
@ -20,19 +20,15 @@
|
|||
#include <asm.inc>
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
.code32
|
||||
EXTERN i386CallRealMode:PROC
|
||||
|
||||
.code32
|
||||
|
||||
/*
|
||||
* U32 PnpBiosSupported(VOID);
|
||||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
_pnp_bios_entry_point:
|
||||
.long 0
|
||||
_pnp_bios_data_segment:
|
||||
.word 0
|
||||
|
||||
PUBLIC _PnpBiosSupported
|
||||
_PnpBiosSupported:
|
||||
|
||||
|
@ -79,14 +75,14 @@ pnp_loop:
|
|||
|
||||
/* Calculate the bios entry point (far pointer) */
|
||||
xor eax, eax
|
||||
mov ax, [esi + 15]
|
||||
mov ax, [esi + HEX(0F)]
|
||||
shl eax, 16
|
||||
mov ax, [esi + 0x0D]
|
||||
mov _pnp_bios_entry_point, eax
|
||||
mov ax, [esi + HEX(0D)]
|
||||
mov dword ptr ds:[BSS_PnpBiosEntryPoint], eax
|
||||
|
||||
/* Store bios data segment */
|
||||
mov ax, [esi + 0x1B]
|
||||
mov _pnp_bios_data_segment, ax
|
||||
mov ax, [esi + HEX(1B)]
|
||||
mov word ptr ds:[BSS_PnpBiosDataSegment], ax
|
||||
|
||||
pnp_not_found:
|
||||
mov eax, edi
|
||||
|
@ -104,13 +100,6 @@ pnp_not_found:
|
|||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
_pnp_result:
|
||||
.long 0
|
||||
_pnp_node_size:
|
||||
.word 0
|
||||
_pnp_node_count:
|
||||
.word 0
|
||||
|
||||
PUBLIC _PnpBiosGetDeviceNodeCount
|
||||
_PnpBiosGetDeviceNodeCount:
|
||||
|
||||
|
@ -120,41 +109,18 @@ _PnpBiosGetDeviceNodeCount:
|
|||
pusha
|
||||
push es
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
mov ax, word ptr [_pnp_bios_data_segment]
|
||||
push ax
|
||||
|
||||
push cs
|
||||
mov ax, offset _pnp_node_size
|
||||
push ax
|
||||
|
||||
push cs
|
||||
mov ax, offset _pnp_node_count
|
||||
push ax
|
||||
|
||||
push 0
|
||||
|
||||
call dword ptr [_pnp_bios_entry_point]
|
||||
add sp, 12
|
||||
|
||||
movzx ecx, ax
|
||||
mov _pnp_result, ecx
|
||||
|
||||
|
||||
call switch_to_prot
|
||||
.code32
|
||||
mov bx, FNID_PnpBiosGetDeviceNodeCount
|
||||
call i386CallRealMode
|
||||
|
||||
mov esi, [ebp + 8]
|
||||
mov ax, _pnp_node_size
|
||||
mov ax, [BSS_PnpNodeSize]
|
||||
movzx ecx, ax
|
||||
mov [esi], ecx
|
||||
|
||||
mov esi, [ebp + 12]
|
||||
mov ax, _pnp_node_count
|
||||
mov ax, [BSS_PnpNodeCount]
|
||||
movzx ecx, ax
|
||||
mov [esi], eax
|
||||
mov [esi], ecx
|
||||
|
||||
pop es
|
||||
popa
|
||||
|
@ -162,7 +128,7 @@ _PnpBiosGetDeviceNodeCount:
|
|||
mov esp, ebp
|
||||
pop ebp
|
||||
|
||||
mov eax, _pnp_result
|
||||
mov eax, dword ptr [BSS_PnpResult]
|
||||
|
||||
ret
|
||||
|
||||
|
@ -172,16 +138,8 @@ _PnpBiosGetDeviceNodeCount:
|
|||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
_pnp_buffer_segment:
|
||||
.word 0
|
||||
_pnp_buffer_offset:
|
||||
.word 0
|
||||
|
||||
_pnp_node_number:
|
||||
.byte 0
|
||||
|
||||
EXTERN(_PnpBiosGetDeviceNode)
|
||||
.code32
|
||||
PUBLIC _PnpBiosGetDeviceNode
|
||||
_PnpBiosGetDeviceNode:
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
@ -192,54 +150,23 @@ EXTERN(_PnpBiosGetDeviceNode)
|
|||
/* get current node number */
|
||||
mov esi, [ebp + 8]
|
||||
mov al, [esi]
|
||||
mov _pnp_node_number, al
|
||||
mov byte ptr ds:[BSS_PnpNodeNumber], al
|
||||
|
||||
/* convert pointer to node buffer to segment/offset */
|
||||
mov eax, [ebp + 12]
|
||||
shr eax, 4
|
||||
and eax, 0xf000
|
||||
mov _pnp_buffer_segment, ax
|
||||
and eax, HEX(0f000)
|
||||
mov word ptr ds:[BSS_PnpBiosBufferSegment], ax
|
||||
mov eax, [ebp + 12]
|
||||
and eax, 0xffff
|
||||
mov _pnp_buffer_offset, ax
|
||||
and eax, HEX(0ffff)
|
||||
mov word ptr ds:[BSS_PnpBiosBufferOffset], ax
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
/* push bios segment */
|
||||
mov ax, word ptr [_pnp_bios_data_segment]
|
||||
push ax
|
||||
|
||||
/* push control flag */
|
||||
push 1
|
||||
|
||||
/* push pointer to node buffer (segment/offset) */
|
||||
mov ax, word ptr [_pnp_buffer_segment]
|
||||
push ax
|
||||
mov ax, word ptr [_pnp_buffer_offset]
|
||||
push ax
|
||||
|
||||
/* push pointer to node number (segment/offset) */
|
||||
push cs
|
||||
mov ax, offset _pnp_node_number
|
||||
push ax
|
||||
|
||||
/* push function number */
|
||||
push 1
|
||||
|
||||
/* call entry point */
|
||||
call dword ptr [_pnp_bios_entry_point]
|
||||
add sp, 14
|
||||
|
||||
movzx ecx, ax
|
||||
mov _pnp_result, ecx
|
||||
|
||||
call switch_to_prot
|
||||
.code32
|
||||
mov bx, FNID_PnpBiosGetDeviceNode
|
||||
call i386CallRealMode
|
||||
|
||||
/* update node number */
|
||||
mov esi, [ebp + 8]
|
||||
mov al, _pnp_node_number
|
||||
mov al, byte ptr ds:[BSS_PnpNodeNumber]
|
||||
mov [esi], al
|
||||
|
||||
pop es
|
||||
|
@ -248,8 +175,9 @@ EXTERN(_PnpBiosGetDeviceNode)
|
|||
mov esp, ebp
|
||||
pop ebp
|
||||
|
||||
mov eax, _pnp_result
|
||||
mov eax, [BSS_PnpResult]
|
||||
|
||||
ret
|
||||
|
||||
END
|
||||
/* EOF */
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2003 Eric Kohl
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
EXTERN i386CallRealMode:PROC
|
||||
|
||||
.code32
|
||||
|
||||
/*
|
||||
* U32 PnpBiosSupported(VOID);
|
||||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
PUBLIC _PnpBiosSupported
|
||||
_PnpBiosSupported:
|
||||
|
||||
push edi
|
||||
push esi
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
xor edi, edi
|
||||
|
||||
/* init esi */
|
||||
mov esi, HEX(0F0000)
|
||||
|
||||
pnp_again:
|
||||
mov eax, [esi]
|
||||
cmp eax, HEX(506E5024) /* "$PnP" */
|
||||
je pnp_found
|
||||
|
||||
cmp esi, HEX(0FFFF0)
|
||||
je pnp_not_found
|
||||
|
||||
pnp_add:
|
||||
add esi, 16
|
||||
jmp pnp_again
|
||||
|
||||
pnp_found:
|
||||
/* first calculate the checksum */
|
||||
push esi
|
||||
|
||||
push HEX(21)
|
||||
pop ecx
|
||||
xor edx, edx
|
||||
|
||||
pnp_loop:
|
||||
lodsb
|
||||
add dl, al
|
||||
loop pnp_loop
|
||||
|
||||
test dl, dl
|
||||
pop esi
|
||||
jnz pnp_add
|
||||
|
||||
mov edi, esi
|
||||
|
||||
/* Calculate the bios entry point (far pointer) */
|
||||
xor eax, eax
|
||||
mov ax, [esi + HEX(0F)]
|
||||
shl eax, 16
|
||||
mov ax, [esi + HEX(0D)]
|
||||
mov dword ptr ds:[BSS_PnpBiosEntryPoint], eax
|
||||
|
||||
/* Store bios data segment */
|
||||
mov ax, [esi + HEX(1B)]
|
||||
mov word ptr ds:[BSS_PnpBiosDataSegment], ax
|
||||
|
||||
pnp_not_found:
|
||||
mov eax, edi
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop esi
|
||||
pop edi
|
||||
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* U32 PnpBiosGetDeviceNodeCount(U32 *NodeSize, U32 *NodeCount);
|
||||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
PUBLIC _PnpBiosGetDeviceNodeCount
|
||||
_PnpBiosGetDeviceNodeCount:
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
pusha
|
||||
push es
|
||||
|
||||
mov bx, FNID_PnpBiosGetDeviceNodeCount
|
||||
call i386CallRealMode
|
||||
|
||||
mov esi, [ebp + 8]
|
||||
mov ax, [BSS_PnpNodeSize]
|
||||
movzx ecx, ax
|
||||
mov [esi], ecx
|
||||
|
||||
mov esi, [ebp + 12]
|
||||
mov ax, [BSS_PnpNodeCount]
|
||||
movzx ecx, ax
|
||||
mov [esi], ecx
|
||||
|
||||
pop es
|
||||
popa
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
|
||||
mov eax, dword ptr [BSS_PnpResult]
|
||||
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* U32 PnpBiosGetDeviceNode(U8 *NodeId, U8 *NodeBuffer);
|
||||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
PUBLIC _PnpBiosGetDeviceNode
|
||||
_PnpBiosGetDeviceNode:
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
pusha
|
||||
push es
|
||||
|
||||
/* get current node number */
|
||||
mov esi, [ebp + 8]
|
||||
mov al, [esi]
|
||||
mov byte ptr ds:[BSS_PnpNodeNumber], al
|
||||
|
||||
/* convert pointer to node buffer to segment/offset */
|
||||
mov eax, [ebp + 12]
|
||||
shr eax, 4
|
||||
and eax, HEX(0f000)
|
||||
mov word ptr ds:[BSS_PnpBiosBufferSegment], ax
|
||||
mov eax, [ebp + 12]
|
||||
and eax, HEX(0ffff)
|
||||
mov word ptr ds:[BSS_PnpBiosBufferOffset], ax
|
||||
|
||||
mov bx, FNID_PnpBiosGetDeviceNode
|
||||
call i386CallRealMode
|
||||
|
||||
/* update node number */
|
||||
mov esi, [ebp + 8]
|
||||
mov al, byte ptr ds:[BSS_PnpNodeNumber]
|
||||
mov [esi], al
|
||||
|
||||
pop es
|
||||
popa
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
|
||||
mov eax, [BSS_PnpResult]
|
||||
|
||||
ret
|
||||
|
||||
END
|
||||
/* EOF */
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2011 Hervé Poussineau
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
|
||||
/*
|
||||
* U16 PxeCallApi(U16 Segment, U16 Offset, U16 Service, VOID *Parameter);
|
||||
*
|
||||
* RETURNS:
|
||||
*/
|
||||
_pxe_function:
|
||||
.word 0
|
||||
_pxe_entry_point:
|
||||
.long 0
|
||||
_pxe_buffer_segment:
|
||||
.word 0
|
||||
_pxe_buffer_offset:
|
||||
.word 0
|
||||
_pxe_result:
|
||||
.word 0
|
||||
|
||||
EXTERN(_PxeCallApi)
|
||||
.code32
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
pushal
|
||||
push %es
|
||||
|
||||
/* copy entry point */
|
||||
movl 0x08(%ebp),%eax
|
||||
shll $16,%eax
|
||||
movw 0x0C(%ebp),%ax
|
||||
movl %eax,_pxe_entry_point
|
||||
|
||||
/* copy function */
|
||||
movw 0x10(%ebp),%ax
|
||||
movw %ax,_pxe_function
|
||||
|
||||
/* convert pointer to data buffer to segment/offset */
|
||||
movl 0x14(%ebp),%eax
|
||||
shrl $4,%eax
|
||||
andl $0xf000,%eax
|
||||
movw %ax,_pxe_buffer_segment
|
||||
movl 0x14(%ebp),%eax
|
||||
andl $0xffff,%eax
|
||||
movw %ax,_pxe_buffer_offset
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
movw _pxe_buffer_segment,%ax
|
||||
push %ax
|
||||
movw _pxe_buffer_offset,%ax
|
||||
push %ax
|
||||
movw _pxe_function,%ax
|
||||
push %ax
|
||||
lcall *_pxe_entry_point
|
||||
addw $6,%sp
|
||||
movw %ax,_pxe_result
|
||||
|
||||
call switch_to_prot
|
||||
.code32
|
||||
|
||||
pop %es
|
||||
popal
|
||||
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
|
||||
movw _pxe_result,%ax
|
||||
|
||||
ret
|
||||
|
||||
/* EOF */
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
#define I386FLAG_CF HEX(0001) // Carry Flag
|
||||
#define I386FLAG_ZF HEX(0040) // Zero Flag
|
||||
#define I386FLAG_SF HEX(0080) // Sign Flag
|
||||
/* Only these flags are propagated into Int386() */
|
||||
#define FLAGS_PROP (I386FLAG_CF | \
|
||||
I386FLAG_ZF | \
|
||||
I386FLAG_SF)
|
||||
|
||||
Int386_REGS:
|
||||
|
||||
Int386_eax:
|
||||
.long 0
|
||||
Int386_ebx:
|
||||
.long 0
|
||||
Int386_ecx:
|
||||
.long 0
|
||||
Int386_edx:
|
||||
.long 0
|
||||
|
||||
Int386_esi:
|
||||
.long 0
|
||||
Int386_edi:
|
||||
.long 0
|
||||
Int386_ebp:
|
||||
.long 0
|
||||
|
||||
Int386_ds:
|
||||
.word 0
|
||||
Int386_es:
|
||||
.word 0
|
||||
Int386_fs:
|
||||
.word 0
|
||||
Int386_gs:
|
||||
.word 0
|
||||
|
||||
Int386_eflags:
|
||||
.long 0
|
||||
|
||||
Int386_vector:
|
||||
.long 0
|
||||
Int386_regsin:
|
||||
.long 0
|
||||
Int386_regsout:
|
||||
.long 0
|
||||
|
||||
/*
|
||||
* int Int386(int ivec, REGS* in, REGS* out);
|
||||
*/
|
||||
EXTERN(_Int386)
|
||||
.code32
|
||||
|
||||
/* Get the function parameters */
|
||||
movl 0x04(%esp),%eax
|
||||
movl %eax,Int386_vector
|
||||
movb %al,Int386_vector_opcode
|
||||
movl 0x08(%esp),%eax
|
||||
movl %eax,Int386_regsin
|
||||
movl 0x0c(%esp),%eax
|
||||
movl %eax,Int386_regsout
|
||||
|
||||
/* Save all registers + segment registers */
|
||||
pushw %ds
|
||||
pushw %es
|
||||
pushw %fs
|
||||
pushw %gs
|
||||
pushal
|
||||
|
||||
/* Copy the input regs to our variables */
|
||||
movl $Int386_REGS,%edi
|
||||
movl Int386_regsin,%esi
|
||||
movl $0x28,%ecx
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
|
||||
/* Setup the registers */
|
||||
movw %cs:Int386_ds,%ax
|
||||
movw %ax,%ds /* DS register */
|
||||
movw %cs:Int386_es,%ax
|
||||
movw %ax,%es /* ES register */
|
||||
movw %cs:Int386_fs,%ax
|
||||
movw %ax,%fs /* FS register */
|
||||
movw %cs:Int386_gs,%ax
|
||||
movw %ax,%gs /* GS register */
|
||||
|
||||
/* Prepare EFLAGS for recover */
|
||||
pushf
|
||||
movw %cs:Int386_eflags, %ax
|
||||
popw %cx
|
||||
andw $FLAGS_PROP, %ax
|
||||
andw $~FLAGS_PROP, %cx
|
||||
orw %cx, %ax
|
||||
pushw %ax
|
||||
|
||||
/* Recover general purpose registers */
|
||||
movl %cs:Int386_eax,%eax /* EAX register */
|
||||
movl %cs:Int386_ebx,%ebx /* EBX register */
|
||||
movl %cs:Int386_ecx,%ecx /* ECX register */
|
||||
movl %cs:Int386_edx,%edx /* EDX register */
|
||||
|
||||
movl %cs:Int386_esi,%esi /* ESI register */
|
||||
movl %cs:Int386_edi,%edi /* EDI register */
|
||||
|
||||
/* Recover previously prepared flags */
|
||||
popf
|
||||
|
||||
/* Do not set the flags register */
|
||||
/* only return its value in regsout */
|
||||
//pushl Int386_eflags
|
||||
//popfl /* EFLAGS register */
|
||||
|
||||
/* Call the interrupt vector */
|
||||
/*int Int386_vector*/
|
||||
Int386_int_opcode:
|
||||
.byte 0xcd
|
||||
Int386_vector_opcode:
|
||||
.byte 0x00
|
||||
|
||||
/* Save the registers */
|
||||
movl %eax,%cs:Int386_eax /* EAX register */
|
||||
movl %ebx,%cs:Int386_ebx /* EBX register */
|
||||
movl %ecx,%cs:Int386_ecx /* ECX register */
|
||||
movl %edx,%cs:Int386_edx /* EDX register */
|
||||
|
||||
movl %esi,%cs:Int386_esi /* ESI register */
|
||||
movl %edi,%cs:Int386_edi /* EDI register */
|
||||
|
||||
movw %ds,%ax /* DS register */
|
||||
movw %ax,%cs:Int386_ds
|
||||
movw %es,%ax /* ES register */
|
||||
movw %ax,%cs:Int386_es
|
||||
movw %fs,%ax /* FS register */
|
||||
movw %ax,%cs:Int386_fs
|
||||
movw %gs,%ax /* GS register */
|
||||
movw %ax,%cs:Int386_gs
|
||||
|
||||
pushf
|
||||
popw %cs:Int386_eflags /* EFLAGS register */
|
||||
|
||||
call switch_to_prot
|
||||
.code32
|
||||
|
||||
/* Copy the variables to the output regs */
|
||||
movl $Int386_REGS,%esi
|
||||
movl Int386_regsout,%edi
|
||||
movl $0x28,%ecx
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
|
||||
/* Restore segment and all other registers */
|
||||
|
||||
|
||||
popal
|
||||
popw %gs
|
||||
popw %fs
|
||||
popw %es
|
||||
popw %ds
|
||||
|
||||
/* Get return value */
|
||||
movl Int386_eax,%eax
|
||||
|
||||
ret
|
|
@ -17,37 +17,18 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
|
||||
#include <asm.inc>
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
.code32
|
||||
EXTERN(_BootNewLinuxKernel)
|
||||
call switch_to_real
|
||||
.code16
|
||||
EXTERN i386CallRealMode:PROC
|
||||
|
||||
/* Set the boot drive */
|
||||
movb (_FrldrBootDrive),%dl
|
||||
.code32
|
||||
|
||||
/* Load segment registers */
|
||||
cli
|
||||
movw $0x9000,%bx
|
||||
movw %bx,%ds
|
||||
movw %bx,%es
|
||||
movw %bx,%fs
|
||||
movw %bx,%gs
|
||||
movw %bx,%ss
|
||||
movw $0x9000,%sp
|
||||
|
||||
ljmpl $0x9020,$0x0000
|
||||
|
||||
|
||||
.code32
|
||||
/*
|
||||
* VOID BootOldLinuxKernel(ULONG KernelSize);
|
||||
*/
|
||||
EXTERN(_BootOldLinuxKernel)
|
||||
PUBLIC _BootOldLinuxKernel
|
||||
_BootOldLinuxKernel:
|
||||
|
||||
/* First we have to copy the kernel down from 0x100000 to 0x10000 */
|
||||
/* The reason we can overwrite low memory is because this code */
|
||||
|
@ -55,25 +36,20 @@ EXTERN(_BootOldLinuxKernel)
|
|||
/* 32k of code before we start interfering with Linux kernel address space. */
|
||||
|
||||
/* Get KernelSize in ECX and move the kernel down */
|
||||
movl 0x04(%esp),%ecx
|
||||
movl $0x100000,%esi
|
||||
movl $0x10000,%edi
|
||||
mov ecx, [esp + 4]
|
||||
mov esi, HEX(100000)
|
||||
mov edi, HEX(10000)
|
||||
rep movsb
|
||||
|
||||
call switch_to_real
|
||||
.code16
|
||||
/* Fall through */
|
||||
|
||||
/* Set the boot drive */
|
||||
movb (_FrldrBootDrive),%dl
|
||||
PUBLIC _BootNewLinuxKernel
|
||||
_BootNewLinuxKernel:
|
||||
|
||||
/* Load segment registers */
|
||||
cli
|
||||
movw $0x9000,%bx
|
||||
movw %bx,%ds
|
||||
movw %bx,%es
|
||||
movw %bx,%fs
|
||||
movw %bx,%gs
|
||||
movw %bx,%ss
|
||||
movw $0x9000,%sp
|
||||
mov bx, FNID_BootLinuxKernel
|
||||
call i386CallRealMode
|
||||
|
||||
ljmpl $0x9020,$0x0000
|
||||
/* We should never get here */
|
||||
int 3
|
||||
|
||||
END
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <arch/pc/x86common.h>
|
||||
|
||||
EXTERN i386CallRealMode:PROC
|
||||
|
||||
.code32
|
||||
|
||||
/*
|
||||
* VOID BootOldLinuxKernel(ULONG KernelSize);
|
||||
*/
|
||||
PUBLIC _BootOldLinuxKernel
|
||||
_BootOldLinuxKernel:
|
||||
|
||||
/* First we have to copy the kernel down from 0x100000 to 0x10000 */
|
||||
/* The reason we can overwrite low memory is because this code */
|
||||
/* executes between 0000:8000 and 0000:FFFF. That leaves space for */
|
||||
/* 32k of code before we start interfering with Linux kernel address space. */
|
||||
|
||||
/* Get KernelSize in ECX and move the kernel down */
|
||||
mov ecx, [esp + 4]
|
||||
mov esi, HEX(100000)
|
||||
mov edi, HEX(10000)
|
||||
rep movsb
|
||||
|
||||
/* Fall through */
|
||||
|
||||
PUBLIC _BootNewLinuxKernel
|
||||
_BootNewLinuxKernel:
|
||||
|
||||
mov bx, FNID_BootLinuxKernel
|
||||
call i386CallRealMode
|
||||
|
||||
/* We should never get here */
|
||||
int 3
|
||||
|
||||
END
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
|
||||
#include <asm.inc>
|
||||
|
||||
.code32
|
||||
|
||||
|
||||
END
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
|
||||
Interface definitions for bget.c, the memory management package.
|
||||
|
||||
*/
|
||||
|
||||
typedef long bufsize;
|
||||
void bpool (void *buffer, bufsize len);
|
||||
void *bget (bufsize size);
|
||||
void *bgetz (bufsize size);
|
||||
void *bgetr (void *buffer, bufsize newsize);
|
||||
void brel (void *buf);
|
||||
void bectl (int (*compact)(bufsize sizereq, int sequence),
|
||||
void *(*acquire)(bufsize size),
|
||||
void (*release)(void *buf), bufsize pool_incr);
|
||||
void bstats (bufsize *curalloc, bufsize *totfree, bufsize *maxfree,
|
||||
long *nget, long *nrel);
|
||||
void bstatse (bufsize *pool_incr, long *npool, long *npget,
|
||||
long *nprel, long *ndget, long *ndrel);
|
||||
void bufdump (void *buf);
|
||||
void bpoold (void *pool, int dumpalloc, int dumpfree);
|
||||
int bpoolv (void *pool);
|
|
@ -56,7 +56,6 @@
|
|||
|
||||
/* internal headers */
|
||||
#include <arcemul.h>
|
||||
#include <bget.h>
|
||||
#include <bytesex.h>
|
||||
#include <cache.h>
|
||||
#include <cmdline.h>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org>
|
||||
* Copyright (C) 2011 Timo Kreuzer (timo.kreuzer@reactos.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
|
||||
|
@ -20,84 +20,494 @@
|
|||
#include <freeldr.h>
|
||||
#include <debug.h>
|
||||
|
||||
//#define MM_DBG 1 // needs #define BufStats 1 in bget.c
|
||||
#define FREELDR_HEAP_VERIFIER
|
||||
|
||||
ULONG MmMaximumHeapAlloc;
|
||||
DBG_DEFAULT_CHANNEL(HEAP);
|
||||
|
||||
DBG_DEFAULT_CHANNEL(MEMORY);
|
||||
#define DEFAULT_HEAP_SIZE (1024 * 1024)
|
||||
#define TEMP_HEAP_SIZE (1024 * 1024)
|
||||
|
||||
VOID MmInitializeHeap(PVOID PageLookupTable)
|
||||
#define REDZONE_MARK 0xCCCCCCCCCCCCCCCCULL
|
||||
#define REDZONE_ALLOCATION 24
|
||||
#define REDZONE_LOW_OFFSET 16
|
||||
#define REDZONE_SIZE(Block) ((ULONG64*)Block->Data)
|
||||
#define REDZONE_LOW(Block) ((ULONG64*)Block->Data + 1)
|
||||
#define REDZONE_HI(Block) ((ULONG64*)((PUCHAR)Block->Data + 16 + *REDZONE_SIZE(Block)))
|
||||
|
||||
PVOID FrLdrDefaultHeap;
|
||||
PVOID FrLdrTempHeap;
|
||||
|
||||
typedef struct _BLOCK_DATA
|
||||
{
|
||||
ULONG PagesNeeded = 0;
|
||||
ULONG HeapStart = 0;
|
||||
ULONG_PTR Flink:32;
|
||||
ULONG_PTR Blink:32;
|
||||
} BLOCK_DATA, *PBLOCK_DATA;
|
||||
|
||||
// Find contigious memory block for HEAP:STACK
|
||||
PagesNeeded = HEAP_PAGES + STACK_PAGES;
|
||||
HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE);
|
||||
|
||||
if (HeapStart == 0)
|
||||
{
|
||||
UiMessageBox("Critical error: Can't allocate heap!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize BGET
|
||||
bpool((PVOID)(HeapStart << MM_PAGE_SHIFT), PagesNeeded << MM_PAGE_SHIFT);
|
||||
|
||||
// Mark those pages as used
|
||||
MmMarkPagesInLookupTable(PageLookupTableAddress, HeapStart, PagesNeeded, LoaderOsloaderHeap);
|
||||
|
||||
TRACE("Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded);
|
||||
}
|
||||
|
||||
PVOID MmHeapAlloc(ULONG MemorySize)
|
||||
typedef struct _HEAP_BLOCK
|
||||
{
|
||||
PVOID Result;
|
||||
USHORT Size;
|
||||
USHORT PreviousSize;
|
||||
ULONG Tag;
|
||||
BLOCK_DATA Data[];
|
||||
} HEAP_BLOCK, *PHEAP_BLOCK;
|
||||
|
||||
if (MemorySize > MM_PAGE_SIZE)
|
||||
{
|
||||
WARN("Consider using other functions to allocate %d bytes of memory!\n", MemorySize);
|
||||
}
|
||||
|
||||
// Get the buffer from BGET pool
|
||||
Result = bget(MemorySize);
|
||||
|
||||
if (Result == NULL)
|
||||
{
|
||||
ERR("Heap allocation for %d bytes failed\n", MemorySize);
|
||||
}
|
||||
#ifdef MM_DBG
|
||||
{
|
||||
LONG CurAlloc, TotalFree, MaxFree, NumberOfGets, NumberOfRels;
|
||||
|
||||
// Gather some stats
|
||||
bstats(&CurAlloc, &TotalFree, &MaxFree, &NumberOfGets, &NumberOfRels);
|
||||
if (CurAlloc > MmMaximumHeapAlloc) MmMaximumHeapAlloc = CurAlloc;
|
||||
|
||||
TRACE("Current alloc %d, free %d, max alloc %lx, allocs %d, frees %d\n",
|
||||
CurAlloc, TotalFree, MmMaximumHeapAlloc, NumberOfGets, NumberOfRels);
|
||||
}
|
||||
#endif
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID MmHeapFree(PVOID MemoryPointer)
|
||||
typedef struct _HEAP
|
||||
{
|
||||
// Release the buffer to the pool
|
||||
brel(MemoryPointer);
|
||||
}
|
||||
|
||||
SIZE_T MaximumSize;
|
||||
SIZE_T CurrentAllocBytes;
|
||||
SIZE_T MaxAllocBytes;
|
||||
ULONG NumAllocs;
|
||||
ULONG NumFrees;
|
||||
SIZE_T LargestAllocation;
|
||||
ULONGLONG AllocationTime;
|
||||
ULONGLONG FreeTime;
|
||||
ULONG_PTR TerminatingBlock;
|
||||
HEAP_BLOCK Blocks;
|
||||
} HEAP, *PHEAP;
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
ExAllocatePool(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
HeapCreate(
|
||||
SIZE_T MaximumSize,
|
||||
TYPE_OF_MEMORY MemoryType)
|
||||
{
|
||||
return MmHeapAlloc(NumberOfBytes);
|
||||
PHEAP Heap;
|
||||
PHEAP_BLOCK Block;
|
||||
SIZE_T Remaining;
|
||||
USHORT PreviousSize;
|
||||
TRACE("HeapCreate(MemoryType=%ld)\n", MemoryType);
|
||||
|
||||
/* Allocate some memory for the heap */
|
||||
MaximumSize = ALIGN_UP_BY(MaximumSize, MM_PAGE_SIZE);
|
||||
Heap = MmAllocateMemoryWithType(MaximumSize, MemoryType);
|
||||
if (!Heap)
|
||||
{
|
||||
ERR("HEAP: Failed to allocate heap of size 0x%lx, Type\n",
|
||||
MaximumSize, MemoryType);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the heap header */
|
||||
Heap->MaximumSize = MaximumSize;
|
||||
Heap->CurrentAllocBytes = 0;
|
||||
Heap->MaxAllocBytes = 0;
|
||||
Heap->NumAllocs = 0;
|
||||
Heap->NumFrees = 0;
|
||||
Heap->LargestAllocation = 0;
|
||||
|
||||
/* Calculate what's left to process */
|
||||
Remaining = (MaximumSize - sizeof(HEAP)) / sizeof(HEAP_BLOCK);
|
||||
TRACE("Remaining = %ld\n", Remaining);
|
||||
|
||||
/* Substract 2 for the terminating entry (header + free entry) */
|
||||
Remaining -= 2;
|
||||
|
||||
Block = &Heap->Blocks;
|
||||
PreviousSize = 0;
|
||||
|
||||
/* Create free blocks */
|
||||
while (Remaining > 1)
|
||||
{
|
||||
/* Initialize this free block */
|
||||
Block->Size = (USHORT)min(MAXUSHORT, Remaining - 1);
|
||||
Block->PreviousSize = PreviousSize;
|
||||
Block->Tag = 0;
|
||||
Block->Data[0].Flink = (Block - &Heap->Blocks) + Block->Size + 1;
|
||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||
|
||||
/* Substract current block size from remainder */
|
||||
Remaining -= (Block->Size + 1);
|
||||
|
||||
/* Go to next block */
|
||||
PreviousSize = Block->Size;
|
||||
Block = Block + Block->Size + 1;
|
||||
|
||||
TRACE("Remaining = %ld\n", Remaining);
|
||||
}
|
||||
|
||||
/* Now finish with a terminating block */
|
||||
Heap->TerminatingBlock = Block - &Heap->Blocks;
|
||||
Block->Size = 0;
|
||||
Block->PreviousSize = PreviousSize;
|
||||
Block->Tag = 'dnE#';
|
||||
Block->Data[0].Flink = 0;
|
||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||
Heap->Blocks.Data[0].Blink = Heap->TerminatingBlock;
|
||||
|
||||
return Heap;
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapDestroy(
|
||||
PVOID HeapHandle)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
|
||||
/* Mark all pages as firmware temporary, so they are free for the kernel */
|
||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||
(ULONG_PTR)Heap / MM_PAGE_SIZE,
|
||||
(PFN_COUNT)(Heap->MaximumSize / MM_PAGE_SIZE),
|
||||
LoaderFirmwareTemporary);
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapRelease(
|
||||
PVOID HeapHandle)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block;
|
||||
PUCHAR StartAddress, EndAddress;
|
||||
PFN_COUNT FreePages, AllFreePages = 0;
|
||||
TRACE("HeapRelease(%p)\n", HeapHandle);
|
||||
|
||||
/* Loop all heap chunks */
|
||||
for (Block = &Heap->Blocks;
|
||||
Block->Size != 0;
|
||||
Block = Block + 1 + Block->Size)
|
||||
{
|
||||
/* Continue, if its not free */
|
||||
if (Block->Tag != 0)
|
||||
{
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Verify size and redzones */
|
||||
ASSERT(*REDZONE_SIZE(Block) <= Block->Size * sizeof(HEAP_BLOCK));
|
||||
ASSERT(*REDZONE_LOW(Block) == REDZONE_MARK);
|
||||
ASSERT(*REDZONE_HI(Block) == REDZONE_MARK);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate page aligned start address of the free region */
|
||||
StartAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
|
||||
/* Walk over adjacent free blocks */
|
||||
while (Block->Tag == 0) Block = Block + Block->Size + 1;
|
||||
|
||||
/* Check if this was the last block */
|
||||
if (Block->Size == 0)
|
||||
{
|
||||
/* Align the end address up to cover the end of the heap */
|
||||
EndAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Align the end address down to not cover any allocations */
|
||||
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Check if we have free pages */
|
||||
if (EndAddress > StartAddress)
|
||||
{
|
||||
/* Calculate the size of the free region in pages */
|
||||
FreePages = (PFN_COUNT)((EndAddress - StartAddress) / MM_PAGE_SIZE);
|
||||
AllFreePages += FreePages;
|
||||
|
||||
/* Now mark the pages free */
|
||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||
(ULONG_PTR)StartAddress / MM_PAGE_SIZE,
|
||||
FreePages,
|
||||
LoaderFree);
|
||||
}
|
||||
|
||||
/* bail out, if it was the last block */
|
||||
if (Block->Size == 0) break;
|
||||
}
|
||||
|
||||
TRACE("HeapRelease() done, freed %ld pages\n", AllFreePages);
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapCleanupAll(VOID)
|
||||
{
|
||||
PHEAP Heap;
|
||||
|
||||
Heap = FrLdrDefaultHeap;
|
||||
TRACE("Heap statistics for default heap:\n"
|
||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||
Heap->NumAllocs, Heap->NumFrees);
|
||||
TRACE("AllocTime = %I64d, FreeTime = %I64d, sum = %I64d\n",
|
||||
Heap->AllocationTime, Heap->FreeTime, Heap->AllocationTime + Heap->FreeTime);
|
||||
|
||||
|
||||
/* Release fre pages */
|
||||
HeapRelease(FrLdrDefaultHeap);
|
||||
|
||||
Heap = FrLdrTempHeap;
|
||||
TRACE("Heap statistics for temp heap:\n"
|
||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||
Heap->NumAllocs, Heap->NumFrees);
|
||||
|
||||
/* Destroy the heap */
|
||||
HeapDestroy(FrLdrTempHeap);
|
||||
}
|
||||
|
||||
static VOID
|
||||
HeapRemoveFreeList(
|
||||
PHEAP Heap,
|
||||
PHEAP_BLOCK Block)
|
||||
{
|
||||
PHEAP_BLOCK Previous, Next;
|
||||
|
||||
Next = &Heap->Blocks + Block->Data[0].Flink;
|
||||
Previous = &Heap->Blocks + Block->Data[0].Blink;
|
||||
ASSERT((Next->Tag == 0) || (Next->Tag == 'dnE#'));
|
||||
ASSERT(Next->Data[0].Blink == Block - &Heap->Blocks);
|
||||
ASSERT((Previous->Tag == 0) || (Previous->Tag == 'dnE#'));
|
||||
ASSERT(Previous->Data[0].Flink == Block - &Heap->Blocks);
|
||||
|
||||
Next->Data[0].Blink = Previous - &Heap->Blocks;
|
||||
Previous->Data[0].Flink = Next - &Heap->Blocks;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HeapInsertFreeList(
|
||||
PHEAP Heap,
|
||||
PHEAP_BLOCK FreeBlock)
|
||||
{
|
||||
PHEAP_BLOCK ListHead, NextBlock;
|
||||
ASSERT(FreeBlock->Tag == 0);
|
||||
|
||||
/* Terminating block serves as free list head */
|
||||
ListHead = &Heap->Blocks + Heap->TerminatingBlock;
|
||||
|
||||
for (NextBlock = &Heap->Blocks + ListHead->Data[0].Flink;
|
||||
NextBlock < FreeBlock;
|
||||
NextBlock = &Heap->Blocks + NextBlock->Data[0].Flink);
|
||||
|
||||
FreeBlock->Data[0].Flink = NextBlock - &Heap->Blocks;
|
||||
FreeBlock->Data[0].Blink = NextBlock->Data[0].Blink;
|
||||
NextBlock->Data[0].Blink = FreeBlock - &Heap->Blocks;
|
||||
NextBlock = &Heap->Blocks + FreeBlock->Data[0].Blink;
|
||||
NextBlock->Data[0].Flink = FreeBlock - &Heap->Blocks;
|
||||
}
|
||||
|
||||
PVOID
|
||||
HeapAllocate(
|
||||
PVOID HeapHandle,
|
||||
SIZE_T ByteSize,
|
||||
ULONG Tag)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block, NextBlock;
|
||||
USHORT BlockSize, Remaining;
|
||||
ULONGLONG Time = __rdtsc();
|
||||
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Add space for a size field and 2 redzones */
|
||||
ByteSize += REDZONE_ALLOCATION;
|
||||
#endif
|
||||
|
||||
/* Check if the allocation is too large */
|
||||
if ((ByteSize + sizeof(HEAP_BLOCK)) > MAXUSHORT * sizeof(HEAP_BLOCK))
|
||||
{
|
||||
ERR("HEAP: Allocation of 0x%lx bytes too large\n", ByteSize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need a proper tag */
|
||||
if (Tag == 0) Tag = 'enoN';
|
||||
|
||||
/* Calculate alloc size */
|
||||
BlockSize = (USHORT)((ByteSize + sizeof(HEAP_BLOCK) - 1) / sizeof(HEAP_BLOCK));
|
||||
|
||||
/* Walk the free block list */
|
||||
Block = &Heap->Blocks + Heap->TerminatingBlock;
|
||||
for (Block = &Heap->Blocks + Block->Data[0].Flink;
|
||||
Block->Size != 0;
|
||||
Block = &Heap->Blocks + Block->Data[0].Flink)
|
||||
{
|
||||
ASSERT(Block->Tag == 0);
|
||||
|
||||
/* Continue, if its too small */
|
||||
if (Block->Size < BlockSize) continue;
|
||||
|
||||
/* This block is just fine, use it */
|
||||
Block->Tag = Tag;
|
||||
|
||||
/* Remove this entry from the free list */
|
||||
HeapRemoveFreeList(Heap, Block);
|
||||
|
||||
/* Calculate the remaining size */
|
||||
Remaining = Block->Size - BlockSize;
|
||||
|
||||
/* Check if the remaining space is large enough for a new block */
|
||||
if (Remaining > 1)
|
||||
{
|
||||
/* Make the allocated block as large as neccessary */
|
||||
Block->Size = BlockSize;
|
||||
|
||||
/* Get pointer to the new block */
|
||||
NextBlock = Block + 1 + BlockSize;
|
||||
|
||||
/* Make it a free block */
|
||||
NextBlock->Tag = 0;
|
||||
NextBlock->Size = Remaining - 1;
|
||||
NextBlock->PreviousSize = BlockSize;
|
||||
BlockSize = NextBlock->Size;
|
||||
HeapInsertFreeList(Heap, NextBlock);
|
||||
|
||||
/* Advance to the next block */
|
||||
NextBlock = NextBlock + 1 + BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not enough left, use the full block */
|
||||
BlockSize = Block->Size;
|
||||
|
||||
/* Get the next block */
|
||||
NextBlock = Block + 1 + BlockSize;
|
||||
}
|
||||
|
||||
/* Update the next blocks back link */
|
||||
NextBlock->PreviousSize = BlockSize;
|
||||
|
||||
/* Update heap usage */
|
||||
Heap->NumAllocs++;
|
||||
Heap->CurrentAllocBytes += Block->Size * sizeof(HEAP_BLOCK);
|
||||
Heap->MaxAllocBytes = max(Heap->MaxAllocBytes, Heap->CurrentAllocBytes);
|
||||
Heap->LargestAllocation = max(Heap->LargestAllocation,
|
||||
Block->Size * sizeof(HEAP_BLOCK));
|
||||
Heap->AllocationTime += (__rdtsc() - Time);
|
||||
|
||||
TRACE("HeapAllocate(%p, %ld, %.4s) -> return %p\n",
|
||||
HeapHandle, ByteSize, &Tag, Block->Data);
|
||||
|
||||
/* HACK: zero out the allocation */
|
||||
RtlZeroMemory(Block->Data, Block->Size * sizeof(HEAP_BLOCK));
|
||||
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Write size and redzones */
|
||||
*REDZONE_SIZE(Block) = ByteSize - REDZONE_ALLOCATION;
|
||||
*REDZONE_LOW(Block) = REDZONE_MARK;
|
||||
*REDZONE_HI(Block) = REDZONE_MARK;
|
||||
|
||||
/* Allcoation starts after size field and redzone */
|
||||
return (PUCHAR)Block->Data + REDZONE_LOW_OFFSET;
|
||||
#endif
|
||||
/* Return pointer to the data */
|
||||
return Block->Data;
|
||||
}
|
||||
|
||||
/* We found nothing */
|
||||
WARN("HEAP: nothing suitable found for 0x%lx bytes\n", ByteSize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapFree(
|
||||
PVOID HeapHandle,
|
||||
PVOID Pointer,
|
||||
ULONG Tag)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block, PrevBlock, NextBlock;
|
||||
ULONGLONG Time = __rdtsc();
|
||||
TRACE("HeapFree(%p, %p)\n", HeapHandle, Pointer);
|
||||
ASSERT(Tag != 'dnE#');
|
||||
|
||||
/* Check if the block is really inside this heap */
|
||||
if ((Pointer < (PVOID)(Heap + 1)) ||
|
||||
(Pointer > (PVOID)((PUCHAR)Heap + Heap->MaximumSize)))
|
||||
{
|
||||
ERR("HEAP: trying to free %p outside of heap %p\n", Pointer, Heap);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
Block = ((PHEAP_BLOCK)Pointer) - 1;
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
Block = (PHEAP_BLOCK)((PUCHAR)Block - REDZONE_LOW_OFFSET);
|
||||
|
||||
/* Verify size and redzones */
|
||||
ASSERT(*REDZONE_SIZE(Block) <= Block->Size * sizeof(HEAP_BLOCK));
|
||||
ASSERT(*REDZONE_LOW(Block) == REDZONE_MARK);
|
||||
ASSERT(*REDZONE_HI(Block) == REDZONE_MARK);
|
||||
#endif
|
||||
|
||||
/* Check if the tag matches */
|
||||
if ((Tag && (Block->Tag != Tag)) || (Block->Tag == 0))
|
||||
{
|
||||
ERR("HEAP: Bad tag! Pointer=%p: block tag '%.4s', requested '%.4s', size=0x%lx\n",
|
||||
Pointer, &Block->Tag, &Tag, Block->Size);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Mark as free */
|
||||
Block->Tag = 0;
|
||||
|
||||
/* Update heap usage */
|
||||
Heap->NumFrees++;
|
||||
Heap->CurrentAllocBytes -= Block->Size * sizeof(HEAP_BLOCK);
|
||||
|
||||
/* Get pointers to the next and previous block */
|
||||
PrevBlock = Block - Block->PreviousSize - 1;
|
||||
NextBlock = Block + Block->Size + 1;
|
||||
|
||||
/* Check if next block is free */
|
||||
if ((NextBlock->Tag == 0) &&
|
||||
((Block->Size + NextBlock->Size + 1) <= MAXUSHORT))
|
||||
{
|
||||
/* Merge next block into current */
|
||||
Block->Size += NextBlock->Size + 1;
|
||||
HeapRemoveFreeList(Heap, NextBlock);
|
||||
|
||||
NextBlock = Block + Block->Size + 1;
|
||||
}
|
||||
|
||||
/* Check if there is a block before and it's free */
|
||||
if ((Block->PreviousSize != 0) && (PrevBlock->Tag == 0) &&
|
||||
((PrevBlock->Size + Block->Size + 1) <= MAXUSHORT))
|
||||
{
|
||||
/* Merge current block into previous */
|
||||
PrevBlock->Size += Block->Size + 1;
|
||||
Block = PrevBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert the entry into the free list */
|
||||
HeapInsertFreeList(Heap, Block);
|
||||
}
|
||||
|
||||
/* Update the next block's back link */
|
||||
NextBlock->PreviousSize = Block->Size;
|
||||
|
||||
Heap->FreeTime += (__rdtsc() - Time);
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper functions *********************************************************/
|
||||
|
||||
VOID
|
||||
MmInitializeHeap(PVOID PageLookupTable)
|
||||
{
|
||||
TRACE("MmInitializeHeap()\n");
|
||||
|
||||
/* Create the default heap */
|
||||
FrLdrDefaultHeap = HeapCreate(DEFAULT_HEAP_SIZE, LoaderOsloaderHeap);
|
||||
ASSERT(FrLdrDefaultHeap);
|
||||
|
||||
/* Create a temporary heap */
|
||||
FrLdrTempHeap = HeapCreate(TEMP_HEAP_SIZE, LoaderFirmwareTemporary);
|
||||
ASSERT(FrLdrTempHeap);
|
||||
|
||||
TRACE("MmInitializeHeap() done, default heap %p, temp heap %p\n",
|
||||
FrLdrDefaultHeap, FrLdrTempHeap);
|
||||
}
|
||||
|
||||
PVOID
|
||||
MmHeapAlloc(SIZE_T MemorySize)
|
||||
{
|
||||
return HeapAllocate(FrLdrDefaultHeap, MemorySize, 'pHmM');
|
||||
}
|
||||
|
||||
VOID
|
||||
MmHeapFree(PVOID MemoryPointer)
|
||||
{
|
||||
HeapFree(FrLdrDefaultHeap, MemoryPointer, 'pHmM');
|
||||
}
|
||||
|
||||
#undef ExAllocatePoolWithTag
|
||||
PVOID
|
||||
NTAPI
|
||||
ExAllocatePoolWithTag(
|
||||
|
@ -105,26 +515,33 @@ ExAllocatePoolWithTag(
|
|||
IN SIZE_T NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
return MmHeapAlloc(NumberOfBytes);
|
||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, Tag);
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
ExAllocatePool(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
{
|
||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, 0);
|
||||
}
|
||||
|
||||
#undef ExFreePool
|
||||
VOID
|
||||
NTAPI
|
||||
ExFreePool(
|
||||
IN PVOID P)
|
||||
{
|
||||
MmHeapFree(P);
|
||||
HeapFree(FrLdrDefaultHeap, P, 0);
|
||||
}
|
||||
|
||||
#undef ExFreePoolWithTag
|
||||
VOID
|
||||
NTAPI
|
||||
ExFreePoolWithTag(
|
||||
IN PVOID P,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
ExFreePool(P);
|
||||
HeapFree(FrLdrDefaultHeap, P, Tag);
|
||||
}
|
||||
|
||||
PVOID
|
||||
|
@ -136,7 +553,7 @@ RtlAllocateHeap(
|
|||
{
|
||||
PVOID ptr;
|
||||
|
||||
ptr = MmHeapAlloc(Size);
|
||||
ptr = HeapAllocate(FrLdrDefaultHeap, Size, ' ltR');
|
||||
if (ptr && (Flags & HEAP_ZERO_MEMORY))
|
||||
{
|
||||
RtlZeroMemory(ptr, Size);
|
||||
|
@ -152,6 +569,7 @@ RtlFreeHeap(
|
|||
IN ULONG Flags,
|
||||
IN PVOID HeapBase)
|
||||
{
|
||||
MmHeapFree(HeapBase);
|
||||
HeapFree(FrLdrDefaultHeap, HeapBase, ' ltR');
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,575 +0,0 @@
|
|||
/*
|
||||
* FreeLoader
|
||||
* Copyright (C) 2011 Timo Kreuzer (timo.kreuzer@reactos.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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <freeldr.h>
|
||||
#include <debug.h>
|
||||
|
||||
#define FREELDR_HEAP_VERIFIER
|
||||
|
||||
DBG_DEFAULT_CHANNEL(HEAP);
|
||||
|
||||
#define DEFAULT_HEAP_SIZE (1024 * 1024)
|
||||
#define TEMP_HEAP_SIZE (1024 * 1024)
|
||||
|
||||
#define REDZONE_MARK 0xCCCCCCCCCCCCCCCCULL
|
||||
#define REDZONE_ALLOCATION 24
|
||||
#define REDZONE_LOW_OFFSET 16
|
||||
#define REDZONE_SIZE(Block) ((ULONG64*)Block->Data)
|
||||
#define REDZONE_LOW(Block) ((ULONG64*)Block->Data + 1)
|
||||
#define REDZONE_HI(Block) ((ULONG64*)((PUCHAR)Block->Data + 16 + *REDZONE_SIZE(Block)))
|
||||
|
||||
PVOID FrLdrDefaultHeap;
|
||||
PVOID FrLdrTempHeap;
|
||||
|
||||
typedef struct _BLOCK_DATA
|
||||
{
|
||||
ULONG_PTR Flink:32;
|
||||
ULONG_PTR Blink:32;
|
||||
} BLOCK_DATA, *PBLOCK_DATA;
|
||||
|
||||
typedef struct _HEAP_BLOCK
|
||||
{
|
||||
USHORT Size;
|
||||
USHORT PreviousSize;
|
||||
ULONG Tag;
|
||||
BLOCK_DATA Data[];
|
||||
} HEAP_BLOCK, *PHEAP_BLOCK;
|
||||
|
||||
typedef struct _HEAP
|
||||
{
|
||||
SIZE_T MaximumSize;
|
||||
SIZE_T CurrentAllocBytes;
|
||||
SIZE_T MaxAllocBytes;
|
||||
ULONG NumAllocs;
|
||||
ULONG NumFrees;
|
||||
SIZE_T LargestAllocation;
|
||||
ULONGLONG AllocationTime;
|
||||
ULONGLONG FreeTime;
|
||||
ULONG_PTR TerminatingBlock;
|
||||
HEAP_BLOCK Blocks;
|
||||
} HEAP, *PHEAP;
|
||||
|
||||
PVOID
|
||||
HeapCreate(
|
||||
SIZE_T MaximumSize,
|
||||
TYPE_OF_MEMORY MemoryType)
|
||||
{
|
||||
PHEAP Heap;
|
||||
PHEAP_BLOCK Block;
|
||||
SIZE_T Remaining;
|
||||
USHORT PreviousSize;
|
||||
TRACE("HeapCreate(MemoryType=%ld)\n", MemoryType);
|
||||
|
||||
/* Allocate some memory for the heap */
|
||||
MaximumSize = ALIGN_UP_BY(MaximumSize, MM_PAGE_SIZE);
|
||||
Heap = MmAllocateMemoryWithType(MaximumSize, MemoryType);
|
||||
if (!Heap)
|
||||
{
|
||||
ERR("HEAP: Failed to allocate heap of size 0x%lx, Type\n",
|
||||
MaximumSize, MemoryType);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the heap header */
|
||||
Heap->MaximumSize = MaximumSize;
|
||||
Heap->CurrentAllocBytes = 0;
|
||||
Heap->MaxAllocBytes = 0;
|
||||
Heap->NumAllocs = 0;
|
||||
Heap->NumFrees = 0;
|
||||
Heap->LargestAllocation = 0;
|
||||
|
||||
/* Calculate what's left to process */
|
||||
Remaining = (MaximumSize - sizeof(HEAP)) / sizeof(HEAP_BLOCK);
|
||||
TRACE("Remaining = %ld\n", Remaining);
|
||||
|
||||
/* Substract 2 for the terminating entry (header + free entry) */
|
||||
Remaining -= 2;
|
||||
|
||||
Block = &Heap->Blocks;
|
||||
PreviousSize = 0;
|
||||
|
||||
/* Create free blocks */
|
||||
while (Remaining > 1)
|
||||
{
|
||||
/* Initialize this free block */
|
||||
Block->Size = (USHORT)min(MAXUSHORT, Remaining - 1);
|
||||
Block->PreviousSize = PreviousSize;
|
||||
Block->Tag = 0;
|
||||
Block->Data[0].Flink = (Block - &Heap->Blocks) + Block->Size + 1;
|
||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||
|
||||
/* Substract current block size from remainder */
|
||||
Remaining -= (Block->Size + 1);
|
||||
|
||||
/* Go to next block */
|
||||
PreviousSize = Block->Size;
|
||||
Block = Block + Block->Size + 1;
|
||||
|
||||
TRACE("Remaining = %ld\n", Remaining);
|
||||
}
|
||||
|
||||
/* Now finish with a terminating block */
|
||||
Heap->TerminatingBlock = Block - &Heap->Blocks;
|
||||
Block->Size = 0;
|
||||
Block->PreviousSize = PreviousSize;
|
||||
Block->Tag = 'dnE#';
|
||||
Block->Data[0].Flink = 0;
|
||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||
Heap->Blocks.Data[0].Blink = Heap->TerminatingBlock;
|
||||
|
||||
return Heap;
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapDestroy(
|
||||
PVOID HeapHandle)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
|
||||
/* Mark all pages as firmware temporary, so they are free for the kernel */
|
||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||
(ULONG_PTR)Heap / MM_PAGE_SIZE,
|
||||
(PFN_COUNT)(Heap->MaximumSize / MM_PAGE_SIZE),
|
||||
LoaderFirmwareTemporary);
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapRelease(
|
||||
PVOID HeapHandle)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block;
|
||||
PUCHAR StartAddress, EndAddress;
|
||||
PFN_COUNT FreePages, AllFreePages = 0;
|
||||
TRACE("HeapRelease(%p)\n", HeapHandle);
|
||||
|
||||
/* Loop all heap chunks */
|
||||
for (Block = &Heap->Blocks;
|
||||
Block->Size != 0;
|
||||
Block = Block + 1 + Block->Size)
|
||||
{
|
||||
/* Continue, if its not free */
|
||||
if (Block->Tag != 0)
|
||||
{
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Verify size and redzones */
|
||||
ASSERT(*REDZONE_SIZE(Block) <= Block->Size * sizeof(HEAP_BLOCK));
|
||||
ASSERT(*REDZONE_LOW(Block) == REDZONE_MARK);
|
||||
ASSERT(*REDZONE_HI(Block) == REDZONE_MARK);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate page aligned start address of the free region */
|
||||
StartAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
|
||||
/* Walk over adjacent free blocks */
|
||||
while (Block->Tag == 0) Block = Block + Block->Size + 1;
|
||||
|
||||
/* Check if this was the last block */
|
||||
if (Block->Size == 0)
|
||||
{
|
||||
/* Align the end address up to cover the end of the heap */
|
||||
EndAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Align the end address down to not cover any allocations */
|
||||
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Check if we have free pages */
|
||||
if (EndAddress > StartAddress)
|
||||
{
|
||||
/* Calculate the size of the free region in pages */
|
||||
FreePages = (PFN_COUNT)((EndAddress - StartAddress) / MM_PAGE_SIZE);
|
||||
AllFreePages += FreePages;
|
||||
|
||||
/* Now mark the pages free */
|
||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||
(ULONG_PTR)StartAddress / MM_PAGE_SIZE,
|
||||
FreePages,
|
||||
LoaderFree);
|
||||
}
|
||||
|
||||
/* bail out, if it was the last block */
|
||||
if (Block->Size == 0) break;
|
||||
}
|
||||
|
||||
TRACE("HeapRelease() done, freed %ld pages\n", AllFreePages);
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapCleanupAll(VOID)
|
||||
{
|
||||
PHEAP Heap;
|
||||
|
||||
Heap = FrLdrDefaultHeap;
|
||||
TRACE("Heap statistics for default heap:\n"
|
||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||
Heap->NumAllocs, Heap->NumFrees);
|
||||
TRACE("AllocTime = %I64d, FreeTime = %I64d, sum = %I64d\n",
|
||||
Heap->AllocationTime, Heap->FreeTime, Heap->AllocationTime + Heap->FreeTime);
|
||||
|
||||
|
||||
/* Release fre pages */
|
||||
HeapRelease(FrLdrDefaultHeap);
|
||||
|
||||
Heap = FrLdrTempHeap;
|
||||
TRACE("Heap statistics for temp heap:\n"
|
||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||
Heap->NumAllocs, Heap->NumFrees);
|
||||
|
||||
/* Destroy the heap */
|
||||
HeapDestroy(FrLdrTempHeap);
|
||||
}
|
||||
|
||||
static VOID
|
||||
HeapRemoveFreeList(
|
||||
PHEAP Heap,
|
||||
PHEAP_BLOCK Block)
|
||||
{
|
||||
PHEAP_BLOCK Previous, Next;
|
||||
|
||||
Next = &Heap->Blocks + Block->Data[0].Flink;
|
||||
Previous = &Heap->Blocks + Block->Data[0].Blink;
|
||||
ASSERT((Next->Tag == 0) || (Next->Tag == 'dnE#'));
|
||||
ASSERT(Next->Data[0].Blink == Block - &Heap->Blocks);
|
||||
ASSERT((Previous->Tag == 0) || (Previous->Tag == 'dnE#'));
|
||||
ASSERT(Previous->Data[0].Flink == Block - &Heap->Blocks);
|
||||
|
||||
Next->Data[0].Blink = Previous - &Heap->Blocks;
|
||||
Previous->Data[0].Flink = Next - &Heap->Blocks;
|
||||
}
|
||||
|
||||
static VOID
|
||||
HeapInsertFreeList(
|
||||
PHEAP Heap,
|
||||
PHEAP_BLOCK FreeBlock)
|
||||
{
|
||||
PHEAP_BLOCK ListHead, NextBlock;
|
||||
ASSERT(FreeBlock->Tag == 0);
|
||||
|
||||
/* Terminating block serves as free list head */
|
||||
ListHead = &Heap->Blocks + Heap->TerminatingBlock;
|
||||
|
||||
for (NextBlock = &Heap->Blocks + ListHead->Data[0].Flink;
|
||||
NextBlock < FreeBlock;
|
||||
NextBlock = &Heap->Blocks + NextBlock->Data[0].Flink);
|
||||
|
||||
FreeBlock->Data[0].Flink = NextBlock - &Heap->Blocks;
|
||||
FreeBlock->Data[0].Blink = NextBlock->Data[0].Blink;
|
||||
NextBlock->Data[0].Blink = FreeBlock - &Heap->Blocks;
|
||||
NextBlock = &Heap->Blocks + FreeBlock->Data[0].Blink;
|
||||
NextBlock->Data[0].Flink = FreeBlock - &Heap->Blocks;
|
||||
}
|
||||
|
||||
PVOID
|
||||
HeapAllocate(
|
||||
PVOID HeapHandle,
|
||||
SIZE_T ByteSize,
|
||||
ULONG Tag)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block, NextBlock;
|
||||
USHORT BlockSize, Remaining;
|
||||
ULONGLONG Time = __rdtsc();
|
||||
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Add space for a size field and 2 redzones */
|
||||
ByteSize += REDZONE_ALLOCATION;
|
||||
#endif
|
||||
|
||||
/* Check if the allocation is too large */
|
||||
if ((ByteSize + sizeof(HEAP_BLOCK)) > MAXUSHORT * sizeof(HEAP_BLOCK))
|
||||
{
|
||||
ERR("HEAP: Allocation of 0x%lx bytes too large\n", ByteSize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need a proper tag */
|
||||
if (Tag == 0) Tag = 'enoN';
|
||||
|
||||
/* Calculate alloc size */
|
||||
BlockSize = (USHORT)((ByteSize + sizeof(HEAP_BLOCK) - 1) / sizeof(HEAP_BLOCK));
|
||||
|
||||
/* Walk the free block list */
|
||||
Block = &Heap->Blocks + Heap->TerminatingBlock;
|
||||
for (Block = &Heap->Blocks + Block->Data[0].Flink;
|
||||
Block->Size != 0;
|
||||
Block = &Heap->Blocks + Block->Data[0].Flink)
|
||||
{
|
||||
ASSERT(Block->Tag == 0);
|
||||
|
||||
/* Continue, if its too small */
|
||||
if (Block->Size < BlockSize) continue;
|
||||
|
||||
/* This block is just fine, use it */
|
||||
Block->Tag = Tag;
|
||||
|
||||
/* Remove this entry from the free list */
|
||||
HeapRemoveFreeList(Heap, Block);
|
||||
|
||||
/* Calculate the remaining size */
|
||||
Remaining = Block->Size - BlockSize;
|
||||
|
||||
/* Check if the remaining space is large enough for a new block */
|
||||
if (Remaining > 1)
|
||||
{
|
||||
/* Make the allocated block as large as neccessary */
|
||||
Block->Size = BlockSize;
|
||||
|
||||
/* Get pointer to the new block */
|
||||
NextBlock = Block + 1 + BlockSize;
|
||||
|
||||
/* Make it a free block */
|
||||
NextBlock->Tag = 0;
|
||||
NextBlock->Size = Remaining - 1;
|
||||
NextBlock->PreviousSize = BlockSize;
|
||||
BlockSize = NextBlock->Size;
|
||||
HeapInsertFreeList(Heap, NextBlock);
|
||||
|
||||
/* Advance to the next block */
|
||||
NextBlock = NextBlock + 1 + BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not enough left, use the full block */
|
||||
BlockSize = Block->Size;
|
||||
|
||||
/* Get the next block */
|
||||
NextBlock = Block + 1 + BlockSize;
|
||||
}
|
||||
|
||||
/* Update the next blocks back link */
|
||||
NextBlock->PreviousSize = BlockSize;
|
||||
|
||||
/* Update heap usage */
|
||||
Heap->NumAllocs++;
|
||||
Heap->CurrentAllocBytes += Block->Size * sizeof(HEAP_BLOCK);
|
||||
Heap->MaxAllocBytes = max(Heap->MaxAllocBytes, Heap->CurrentAllocBytes);
|
||||
Heap->LargestAllocation = max(Heap->LargestAllocation,
|
||||
Block->Size * sizeof(HEAP_BLOCK));
|
||||
Heap->AllocationTime += (__rdtsc() - Time);
|
||||
|
||||
TRACE("HeapAllocate(%p, %ld, %.4s) -> return %p\n",
|
||||
HeapHandle, ByteSize, &Tag, Block->Data);
|
||||
|
||||
/* HACK: zero out the allocation */
|
||||
RtlZeroMemory(Block->Data, Block->Size * sizeof(HEAP_BLOCK));
|
||||
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
/* Write size and redzones */
|
||||
*REDZONE_SIZE(Block) = ByteSize - REDZONE_ALLOCATION;
|
||||
*REDZONE_LOW(Block) = REDZONE_MARK;
|
||||
*REDZONE_HI(Block) = REDZONE_MARK;
|
||||
|
||||
/* Allcoation starts after size field and redzone */
|
||||
return (PUCHAR)Block->Data + REDZONE_LOW_OFFSET;
|
||||
#endif
|
||||
/* Return pointer to the data */
|
||||
return Block->Data;
|
||||
}
|
||||
|
||||
/* We found nothing */
|
||||
WARN("HEAP: nothing suitable found for 0x%lx bytes\n", ByteSize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
HeapFree(
|
||||
PVOID HeapHandle,
|
||||
PVOID Pointer,
|
||||
ULONG Tag)
|
||||
{
|
||||
PHEAP Heap = HeapHandle;
|
||||
PHEAP_BLOCK Block, PrevBlock, NextBlock;
|
||||
ULONGLONG Time = __rdtsc();
|
||||
TRACE("HeapFree(%p, %p)\n", HeapHandle, Pointer);
|
||||
ASSERT(Tag != 'dnE#');
|
||||
|
||||
/* Check if the block is really inside this heap */
|
||||
if ((Pointer < (PVOID)(Heap + 1)) ||
|
||||
(Pointer > (PVOID)((PUCHAR)Heap + Heap->MaximumSize)))
|
||||
{
|
||||
ERR("HEAP: trying to free %p outside of heap %p\n", Pointer, Heap);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
Block = ((PHEAP_BLOCK)Pointer) - 1;
|
||||
#ifdef FREELDR_HEAP_VERIFIER
|
||||
Block = (PHEAP_BLOCK)((PUCHAR)Block - REDZONE_LOW_OFFSET);
|
||||
|
||||
/* Verify size and redzones */
|
||||
ASSERT(*REDZONE_SIZE(Block) <= Block->Size * sizeof(HEAP_BLOCK));
|
||||
ASSERT(*REDZONE_LOW(Block) == REDZONE_MARK);
|
||||
ASSERT(*REDZONE_HI(Block) == REDZONE_MARK);
|
||||
#endif
|
||||
|
||||
/* Check if the tag matches */
|
||||
if ((Tag && (Block->Tag != Tag)) || (Block->Tag == 0))
|
||||
{
|
||||
ERR("HEAP: Bad tag! Pointer=%p: block tag '%.4s', requested '%.4s', size=0x%lx\n",
|
||||
Pointer, &Block->Tag, &Tag, Block->Size);
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Mark as free */
|
||||
Block->Tag = 0;
|
||||
|
||||
/* Update heap usage */
|
||||
Heap->NumFrees++;
|
||||
Heap->CurrentAllocBytes -= Block->Size * sizeof(HEAP_BLOCK);
|
||||
|
||||
/* Get pointers to the next and previous block */
|
||||
PrevBlock = Block - Block->PreviousSize - 1;
|
||||
NextBlock = Block + Block->Size + 1;
|
||||
|
||||
/* Check if next block is free */
|
||||
if ((NextBlock->Tag == 0) &&
|
||||
((Block->Size + NextBlock->Size + 1) <= MAXUSHORT))
|
||||
{
|
||||
/* Merge next block into current */
|
||||
Block->Size += NextBlock->Size + 1;
|
||||
HeapRemoveFreeList(Heap, NextBlock);
|
||||
|
||||
NextBlock = Block + Block->Size + 1;
|
||||
}
|
||||
|
||||
/* Check if there is a block before and it's free */
|
||||
if ((Block->PreviousSize != 0) && (PrevBlock->Tag == 0) &&
|
||||
((PrevBlock->Size + Block->Size + 1) <= MAXUSHORT))
|
||||
{
|
||||
/* Merge current block into previous */
|
||||
PrevBlock->Size += Block->Size + 1;
|
||||
Block = PrevBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert the entry into the free list */
|
||||
HeapInsertFreeList(Heap, Block);
|
||||
}
|
||||
|
||||
/* Update the next block's back link */
|
||||
NextBlock->PreviousSize = Block->Size;
|
||||
|
||||
Heap->FreeTime += (__rdtsc() - Time);
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper functions *********************************************************/
|
||||
|
||||
VOID
|
||||
MmInitializeHeap(PVOID PageLookupTable)
|
||||
{
|
||||
TRACE("MmInitializeHeap()\n");
|
||||
|
||||
/* Create the default heap */
|
||||
FrLdrDefaultHeap = HeapCreate(DEFAULT_HEAP_SIZE, LoaderOsloaderHeap);
|
||||
ASSERT(FrLdrDefaultHeap);
|
||||
|
||||
/* Create a temporary heap */
|
||||
FrLdrTempHeap = HeapCreate(TEMP_HEAP_SIZE, LoaderFirmwareTemporary);
|
||||
ASSERT(FrLdrTempHeap);
|
||||
|
||||
TRACE("MmInitializeHeap() done, default heap %p, temp heap %p\n",
|
||||
FrLdrDefaultHeap, FrLdrTempHeap);
|
||||
}
|
||||
|
||||
PVOID
|
||||
MmHeapAlloc(SIZE_T MemorySize)
|
||||
{
|
||||
return HeapAllocate(FrLdrDefaultHeap, MemorySize, 'pHmM');
|
||||
}
|
||||
|
||||
VOID
|
||||
MmHeapFree(PVOID MemoryPointer)
|
||||
{
|
||||
HeapFree(FrLdrDefaultHeap, MemoryPointer, 'pHmM');
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
ExAllocatePoolWithTag(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, Tag);
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
ExAllocatePool(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN SIZE_T NumberOfBytes)
|
||||
{
|
||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, 0);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExFreePool(
|
||||
IN PVOID P)
|
||||
{
|
||||
HeapFree(FrLdrDefaultHeap, P, 0);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExFreePoolWithTag(
|
||||
IN PVOID P,
|
||||
IN ULONG Tag)
|
||||
{
|
||||
HeapFree(FrLdrDefaultHeap, P, Tag);
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
RtlAllocateHeap(
|
||||
IN PVOID HeapHandle,
|
||||
IN ULONG Flags,
|
||||
IN SIZE_T Size)
|
||||
{
|
||||
PVOID ptr;
|
||||
|
||||
ptr = HeapAllocate(FrLdrDefaultHeap, Size, ' ltR');
|
||||
if (ptr && (Flags & HEAP_ZERO_MEMORY))
|
||||
{
|
||||
RtlZeroMemory(ptr, Size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
RtlFreeHeap(
|
||||
IN PVOID HeapHandle,
|
||||
IN ULONG Flags,
|
||||
IN PVOID HeapBase)
|
||||
{
|
||||
HeapFree(FrLdrDefaultHeap, HeapBase, ' ltR');
|
||||
return TRUE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,70 +0,0 @@
|
|||
.file "longjmp.S"
|
||||
/*
|
||||
* Copyright (C) 1998, 1999, Jonathan S. Shapiro.
|
||||
*
|
||||
* This file is part of the EROS Operating System.
|
||||
*
|
||||
* 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,
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* unsigned long ebx, esi, edi;
|
||||
* unsigned long ebp;
|
||||
* unsigned long sp;
|
||||
* unsigned long pc;
|
||||
* } jmp_buf[1];
|
||||
*/
|
||||
|
||||
/*
|
||||
* On entry, the stack to longjmp looks like:
|
||||
*
|
||||
* value
|
||||
* ptr to jmp_buf
|
||||
* return PC
|
||||
*/
|
||||
|
||||
.globl _longjmp
|
||||
_longjmp:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
movl 8(%ebp),%ecx /* address of jmp_buf to ecx */
|
||||
movl 12(%ebp),%eax /* return value to %eax */
|
||||
testl %eax,%eax
|
||||
jne 1f
|
||||
incl %eax /* return 1 if handed 0 */
|
||||
|
||||
1:
|
||||
movl (%ecx),%ebx /* restore %ebx */
|
||||
movl 4(%ecx),%esi /* restore %esi */
|
||||
movl 8(%ecx),%edi /* restore %edi */
|
||||
|
||||
/*
|
||||
* From this instant on we are not running in a valid frame
|
||||
*/
|
||||
|
||||
movl 12(%ecx),%ebp /* restore %ebp */
|
||||
movl 16(%ecx),%esp /* restore %esp */
|
||||
/* movl 20(%ecx),%eax return PC */
|
||||
|
||||
/*
|
||||
* Since we are abandoning the stack in any case,
|
||||
* there isn't much point in doing the usual return
|
||||
* discipline.
|
||||
*/
|
||||
|
||||
jmpl *20(%ecx)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
.file "setjmp.S"
|
||||
/*
|
||||
* Copyright (C) 1998, 1999, Jonathan S. Shapiro.
|
||||
*
|
||||
* This file is part of the EROS Operating System.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* #include <eros/i486/asm.h> */
|
||||
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* unsigned long ebx, esi, edi;
|
||||
* unsigned long ebp;
|
||||
* unsigned long sp;
|
||||
* unsigned long pc;
|
||||
* } jmp_buf[1];
|
||||
*/
|
||||
|
||||
/*
|
||||
* On entry, the stack to setjmp looks like:
|
||||
*
|
||||
* ptr to jmp_buf
|
||||
* return PC
|
||||
*/
|
||||
.globl _setjmp
|
||||
.globl __setjmp
|
||||
_setjmp:
|
||||
__setjmp:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
|
||||
movl 0x8(%ebp),%eax /* address of jmp_buf to eax */
|
||||
movl %ebx,(%eax) /* save %ebx */
|
||||
movl %esi,4(%eax) /* save %esi */
|
||||
movl %edi,8(%eax) /* save %edi */
|
||||
leal 8(%ebp),%edx /* calling proc's esp, not ours! */
|
||||
movl %edx,16(%eax)
|
||||
movl 4(%ebp), %edx /* save return PC */
|
||||
movl %edx,20(%eax)
|
||||
movl 0(%ebp),%edx /* calling proc's ebp, not ours! */
|
||||
movl %edx,12(%eax)
|
||||
|
||||
xorl %eax,%eax /* return 0 the first time */
|
||||
leave
|
||||
ret
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char ch;
|
||||
int cnt = 0;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("usage: bin2c infile.bin outfile.h array_name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((in = fopen(argv[1], "rb")) == NULL)
|
||||
{
|
||||
printf("Couldn't open data file.\n");
|
||||
return -1;
|
||||
}
|
||||
if ((out = fopen(argv[2], "wb")) == NULL)
|
||||
{
|
||||
printf("Couldn't open output file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(out, "unsigned char %s[] = {\n", argv[3]);
|
||||
|
||||
ch = fgetc(in);
|
||||
while (!feof(in))
|
||||
{
|
||||
if (cnt != 0)
|
||||
fprintf(out, ", ");
|
||||
if (!(cnt % 16))
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, "0x%02x", (int)ch);
|
||||
cnt++;
|
||||
ch = fgetc(in);
|
||||
}
|
||||
|
||||
fprintf(out, "\n};\n");
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
namespace std {
|
||||
typedef basic_string<wchar_t> wstring;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string ssprintf ( const char* fmt, ... );
|
||||
std::string ssvprintf ( const char* fmt, va_list args );
|
||||
|
||||
std::wstring sswprintf ( const wchar_t* fmt, ... );
|
||||
std::wstring sswvprintf ( const wchar_t* fmt, va_list args );
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define sstprintf sswprintf
|
||||
#define sstvprintf sswvprintf
|
||||
#else
|
||||
#define sstprintf ssprintf
|
||||
#define sstvprintf ssvprintf
|
||||
#endif
|
|
@ -1,966 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Casper S. Hornstrup
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning ( disable : 4786 )
|
||||
#endif//_MSC_VER
|
||||
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Some hosts don't define PATH_MAX in unistd.h
|
||||
#if !defined(PATH_MAX)
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#define MAX_PATH PATH_MAX
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "xml.h"
|
||||
#include "ssprintf.h"
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH _MAX_PATH
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
#ifdef WIN32
|
||||
#define getcwd _getcwd
|
||||
#endif//WIN32
|
||||
|
||||
static const char* WS = " \t\r\n";
|
||||
static const char* WSEQ = " =\t\r\n";
|
||||
|
||||
string working_directory;
|
||||
|
||||
std::vector<char> vectorize(const std::string &str)
|
||||
{
|
||||
std::vector<char> result( str.size() + 1 );
|
||||
strcpy( &result[0], str.c_str() );
|
||||
return result;
|
||||
}
|
||||
|
||||
void vectappend(std::vector<char> &strvec, const char *str)
|
||||
{
|
||||
if (*str) { strvec[strlen(&strvec[0])] = *str; str++; }
|
||||
while (*str)
|
||||
{
|
||||
strvec.push_back(*str);
|
||||
str++;
|
||||
}
|
||||
strvec.push_back(0);
|
||||
}
|
||||
|
||||
void vectappend(std::vector<char> &strvec, const std::string &str)
|
||||
{
|
||||
vectappend(strvec, str.c_str());
|
||||
}
|
||||
|
||||
void vectappend(std::vector<char> &strvec, char ch)
|
||||
{
|
||||
strvec[strlen(&strvec[0])] = ch;
|
||||
strvec.push_back(0);
|
||||
}
|
||||
|
||||
XMLException::XMLException (
|
||||
const std::string& location,
|
||||
const char* format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start ( args, format );
|
||||
SetExceptionV ( location, format, args );
|
||||
va_end ( args );
|
||||
}
|
||||
|
||||
void XMLException::SetExceptionV ( const std::string& location, const char* format, va_list args )
|
||||
{
|
||||
_e = location + ": " + ssvprintf(format,args);
|
||||
}
|
||||
|
||||
void XMLException::SetException ( const std::string& location, const char* format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start ( args, format );
|
||||
SetExceptionV ( location, format, args );
|
||||
va_end ( args );
|
||||
}
|
||||
|
||||
XMLIncludes::~XMLIncludes()
|
||||
{
|
||||
for ( size_t i = 0; i < this->size(); i++ )
|
||||
delete (*this)[i];
|
||||
}
|
||||
|
||||
void
|
||||
InitWorkingDirectory()
|
||||
{
|
||||
// store the current directory for path calculations
|
||||
working_directory.resize ( MAX_PATH );
|
||||
working_directory[0] = 0;
|
||||
getcwd ( &working_directory[0], working_directory.size() );
|
||||
working_directory.resize ( strlen ( working_directory.c_str() ) );
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
unsigned __int64
|
||||
#else
|
||||
unsigned long long
|
||||
#endif
|
||||
filelen ( FILE* f )
|
||||
{
|
||||
#ifdef WIN32
|
||||
return _filelengthi64 ( _fileno(f) );
|
||||
#else
|
||||
# if defined(__FreeBSD__) || defined(__APPLE__) || defined(__CYGWIN__)
|
||||
struct stat file_stat;
|
||||
if ( fstat(fileno(f), &file_stat) != 0 )
|
||||
# else
|
||||
struct stat64 file_stat;
|
||||
if ( fstat64(fileno(f), &file_stat) != 0 )
|
||||
# endif // __FreeBSD__
|
||||
return 0;
|
||||
return file_stat.st_size;
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
Path::Path()
|
||||
{
|
||||
if ( !working_directory.size() )
|
||||
InitWorkingDirectory();
|
||||
string s ( working_directory );
|
||||
const char* p = strtok ( &s[0], "/\\" );
|
||||
while ( p )
|
||||
{
|
||||
if ( *p )
|
||||
path.push_back ( p );
|
||||
p = strtok ( NULL, "/\\" );
|
||||
}
|
||||
}
|
||||
|
||||
Path::Path ( const Path& cwd, const string& file )
|
||||
{
|
||||
string s ( cwd.Fixup ( file, false ) );
|
||||
const char* p = strtok ( &s[0], "/\\" );
|
||||
while ( p )
|
||||
{
|
||||
if ( *p )
|
||||
path.push_back ( p );
|
||||
p = strtok ( NULL, "/\\" );
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
Path::Fixup ( const string& file, bool include_filename ) const
|
||||
{
|
||||
if ( strchr ( "/\\", file[0] )
|
||||
#ifdef WIN32
|
||||
// this squirreliness is b/c win32 has drive letters and *nix doesn't...
|
||||
|| file[1] == ':'
|
||||
#endif//WIN32
|
||||
)
|
||||
{
|
||||
return file;
|
||||
}
|
||||
vector<string> pathtmp ( path );
|
||||
vector<char> tmp = vectorize( file );
|
||||
const char* prev = strtok ( &tmp[0], "/\\" );
|
||||
const char* p = strtok ( NULL, "/\\" );
|
||||
while ( p )
|
||||
{
|
||||
if ( !strcmp ( prev, "." ) )
|
||||
; // do nothing
|
||||
else if ( !strcmp ( prev, ".." ) )
|
||||
{
|
||||
// this squirreliness is b/c win32 has drive letters and *nix doesn't...
|
||||
#ifdef WIN32
|
||||
if ( pathtmp.size() > 1 )
|
||||
#else
|
||||
if ( pathtmp.size() )
|
||||
#endif
|
||||
pathtmp.resize ( pathtmp.size() - 1 );
|
||||
}
|
||||
else
|
||||
pathtmp.push_back ( prev );
|
||||
prev = p;
|
||||
p = strtok ( NULL, "/\\" );
|
||||
}
|
||||
if ( include_filename )
|
||||
pathtmp.push_back ( prev );
|
||||
|
||||
// reuse tmp variable to return recombined path
|
||||
tmp = vectorize("");
|
||||
for ( size_t i = 0; i < pathtmp.size(); i++ )
|
||||
{
|
||||
// this squirreliness is b/c win32 has drive letters and *nix doesn't...
|
||||
#ifdef WIN32
|
||||
if ( i ) vectappend(tmp, "/");
|
||||
#else
|
||||
vectappend(tmp, "/");
|
||||
#endif
|
||||
vectappend(tmp, pathtmp[i]);
|
||||
}
|
||||
return &tmp[0];
|
||||
}
|
||||
|
||||
string
|
||||
Path::RelativeFromWorkingDirectory ()
|
||||
{
|
||||
string out = "";
|
||||
for ( size_t i = 0; i < path.size(); i++ )
|
||||
{
|
||||
out += "/" + path[i];
|
||||
}
|
||||
return RelativeFromWorkingDirectory ( out );
|
||||
}
|
||||
|
||||
string
|
||||
Path::RelativeFromWorkingDirectory ( const string& path )
|
||||
{
|
||||
return Path::RelativeFromDirectory ( path, working_directory );
|
||||
}
|
||||
|
||||
string
|
||||
Path::RelativeFromDirectory (
|
||||
const string& path,
|
||||
const string& base_directory )
|
||||
{
|
||||
vector<string> vbase, vpath, vout;
|
||||
Path::Split ( vbase, base_directory, true );
|
||||
Path::Split ( vpath, path, true );
|
||||
#ifdef WIN32
|
||||
// this squirreliness is b/c win32 has drive letters and *nix doesn't...
|
||||
// not possible to do relative across different drive letters
|
||||
{
|
||||
char path_driveletter = (path[1] == ':') ? toupper(path[0]) : 0;
|
||||
char base_driveletter = (base_directory[1] == ':') ? toupper(base_directory[0]) : 0;
|
||||
if ( path_driveletter != base_driveletter )
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
size_t i = 0;
|
||||
while ( i < vbase.size() && i < vpath.size() && vbase[i] == vpath[i] )
|
||||
++i;
|
||||
|
||||
// did we go through all of the path?
|
||||
if ( vbase.size() == vpath.size() && i == vpath.size() )
|
||||
return ".";
|
||||
|
||||
if ( i < vbase.size() )
|
||||
{
|
||||
// path goes above our base directory, we will need some ..'s
|
||||
for ( size_t j = i; j < vbase.size(); j++ )
|
||||
vout.push_back ( ".." );
|
||||
}
|
||||
|
||||
while ( i < vpath.size() )
|
||||
vout.push_back ( vpath[i++] );
|
||||
|
||||
// now merge vout into a string again
|
||||
string out = vout[0];
|
||||
for ( i = 1; i < vout.size(); i++ )
|
||||
{
|
||||
out += "/" + vout[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void
|
||||
Path::Split (
|
||||
vector<string>& out,
|
||||
const string& path,
|
||||
bool include_last )
|
||||
{
|
||||
string s ( path );
|
||||
const char* prev = strtok ( &s[0], "/\\" );
|
||||
const char* p = strtok ( NULL, "/\\" );
|
||||
out.resize ( 0 );
|
||||
while ( p )
|
||||
{
|
||||
if ( strcmp ( prev, "." ) )
|
||||
out.push_back ( prev );
|
||||
prev = p;
|
||||
p = strtok ( NULL, "/\\" );
|
||||
}
|
||||
if ( include_last && strcmp ( prev, "." ) )
|
||||
out.push_back ( prev );
|
||||
// special-case where path only has "."
|
||||
// don't move this check up higher as it might miss
|
||||
// some funny paths...
|
||||
if ( !out.size() && !strcmp ( prev, "." ) )
|
||||
out.push_back ( "." );
|
||||
}
|
||||
|
||||
XMLFile::XMLFile()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
XMLFile::close()
|
||||
{
|
||||
_buf.resize(0);
|
||||
_p = _end = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
XMLFile::open ( const string& filename_ )
|
||||
{
|
||||
close();
|
||||
FILE* f = fopen ( filename_.c_str(), "rb" );
|
||||
if ( !f )
|
||||
return false;
|
||||
unsigned long len = (unsigned long)filelen(f);
|
||||
_buf.resize ( len );
|
||||
fread ( &_buf[0], 1, len, f );
|
||||
fclose ( f );
|
||||
_p = _buf.c_str();
|
||||
_end = _p + len;
|
||||
_filename = filename_;
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
// next_token() moves the pointer to next token, which may be
|
||||
// an xml element or a text element, basically it's a glorified
|
||||
// skipspace, normally the user of this class won't need to call
|
||||
// this function
|
||||
void
|
||||
XMLFile::next_token()
|
||||
{
|
||||
_p += strspn ( _p, WS );
|
||||
}
|
||||
|
||||
bool
|
||||
XMLFile::next_is_text()
|
||||
{
|
||||
return *_p != '<';
|
||||
}
|
||||
|
||||
bool
|
||||
XMLFile::more_tokens ()
|
||||
{
|
||||
return _p != _end;
|
||||
}
|
||||
|
||||
// get_token() is used to return a token, and move the pointer
|
||||
// past the token
|
||||
bool
|
||||
XMLFile::get_token ( string& token )
|
||||
{
|
||||
const char* tokend;
|
||||
if ( !strncmp ( _p, "<!--", 4 ) )
|
||||
{
|
||||
tokend = strstr ( _p, "-->" );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
else
|
||||
tokend += 3;
|
||||
}
|
||||
else if ( !strncmp ( _p, "<?", 2 ) )
|
||||
{
|
||||
tokend = strstr ( _p, "?>" );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
else
|
||||
tokend += 2;
|
||||
}
|
||||
else if ( *_p == '<' )
|
||||
{
|
||||
tokend = strchr ( _p, '>' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
else
|
||||
++tokend;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokend = strchr ( _p, '<' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
while ( tokend > _p && isspace(tokend[-1]) )
|
||||
--tokend;
|
||||
}
|
||||
if ( tokend == _p )
|
||||
return false;
|
||||
token = string ( _p, tokend-_p );
|
||||
_p = tokend;
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XMLFile::get_token ( string& token, string& location )
|
||||
{
|
||||
location = Location();
|
||||
return get_token ( token );
|
||||
}
|
||||
|
||||
string
|
||||
XMLFile::Location() const
|
||||
{
|
||||
int line = 1;
|
||||
const char* p = strchr ( _buf.c_str(), '\n' );
|
||||
while ( p && p < _p )
|
||||
{
|
||||
++line;
|
||||
p = strchr ( p+1, '\n' );
|
||||
}
|
||||
return ssprintf ( "%s(%i)",_filename.c_str(), line );
|
||||
}
|
||||
|
||||
XMLAttribute::XMLAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
XMLAttribute::XMLAttribute(
|
||||
const string& name_,
|
||||
const string& value_ )
|
||||
: name(name_), value(value_)
|
||||
{
|
||||
}
|
||||
|
||||
XMLAttribute::XMLAttribute ( const XMLAttribute& src )
|
||||
: name(src.name), value(src.value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XMLAttribute& XMLAttribute::operator = ( const XMLAttribute& src )
|
||||
{
|
||||
name = src.name;
|
||||
value = src.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
XMLElement::XMLElement (
|
||||
XMLFile* xmlFile,
|
||||
const string& location )
|
||||
: xmlFile ( xmlFile ),
|
||||
location ( location ),
|
||||
parentElement ( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
XMLElement::~XMLElement()
|
||||
{
|
||||
size_t i;
|
||||
for ( i = 0; i < attributes.size(); i++ )
|
||||
delete attributes[i];
|
||||
for ( i = 0; i < subElements.size(); i++ )
|
||||
delete subElements[i];
|
||||
}
|
||||
|
||||
void
|
||||
XMLElement::AddSubElement ( XMLElement* e )
|
||||
{
|
||||
subElements.push_back ( e );
|
||||
e->parentElement = this;
|
||||
}
|
||||
|
||||
// Parse()
|
||||
// This function takes a single xml tag ( i.e. beginning with '<' and
|
||||
// ending with '>', and parses out it's tag name and constituent
|
||||
// attributes.
|
||||
// Return Value: returns true if you need to look for a </tag> for
|
||||
// the one it just parsed...
|
||||
bool
|
||||
XMLElement::Parse (
|
||||
const string& token,
|
||||
bool& end_tag )
|
||||
{
|
||||
const char* p = token.c_str();
|
||||
assert ( *p == '<' );
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
|
||||
// check if this is a comment
|
||||
if ( !strncmp ( p, "!--", 3 ) )
|
||||
{
|
||||
name = "!--";
|
||||
end_tag = false;
|
||||
return false; // never look for end tag to a comment
|
||||
}
|
||||
|
||||
end_tag = ( *p == '/' );
|
||||
if ( end_tag )
|
||||
{
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
}
|
||||
const char* end = strpbrk ( p, WS );
|
||||
if ( !end )
|
||||
{
|
||||
end = strpbrk ( p, "/>" );
|
||||
assert ( end );
|
||||
}
|
||||
name = string ( p, end-p );
|
||||
p = end;
|
||||
p += strspn ( p, WS );
|
||||
while ( *p != '>' && *p != '/' )
|
||||
{
|
||||
end = strpbrk ( p, WSEQ );
|
||||
if ( !end )
|
||||
{
|
||||
end = strpbrk ( p, "/>" );
|
||||
assert ( end );
|
||||
}
|
||||
string attribute ( p, end-p ), value;
|
||||
p = end;
|
||||
p += strspn ( p, WS );
|
||||
if ( *p == '=' )
|
||||
{
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
char quote = 0;
|
||||
if ( strchr ( "\"'", *p ) )
|
||||
{
|
||||
quote = *p++;
|
||||
end = strchr ( p, quote );
|
||||
}
|
||||
else
|
||||
{
|
||||
end = strpbrk ( p, WS );
|
||||
}
|
||||
if ( !end )
|
||||
{
|
||||
end = strchr ( p, '>' );
|
||||
assert(end);
|
||||
if ( end[-1] == '/' )
|
||||
end--;
|
||||
}
|
||||
value = string ( p, end-p );
|
||||
p = end;
|
||||
if ( quote && *p == quote )
|
||||
p++;
|
||||
p += strspn ( p, WS );
|
||||
}
|
||||
else if ( name[0] != '!' )
|
||||
{
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"attributes must have values" );
|
||||
}
|
||||
attributes.push_back ( new XMLAttribute ( attribute, value ) );
|
||||
}
|
||||
return !( *p == '/' ) && !end_tag;
|
||||
}
|
||||
|
||||
XMLAttribute*
|
||||
XMLElement::GetAttribute (
|
||||
const string& attribute,
|
||||
bool required )
|
||||
{
|
||||
// this would be faster with a tree-based container, but our attribute
|
||||
// lists are likely to stay so short as to not be an issue.
|
||||
for ( size_t i = 0; i < attributes.size(); i++ )
|
||||
{
|
||||
if ( attribute == attributes[i]->name )
|
||||
return attributes[i];
|
||||
}
|
||||
if ( required )
|
||||
{
|
||||
throw XMLRequiredAttributeNotFoundException (
|
||||
location,
|
||||
attribute,
|
||||
name );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const XMLAttribute*
|
||||
XMLElement::GetAttribute (
|
||||
const string& attribute,
|
||||
bool required ) const
|
||||
{
|
||||
// this would be faster with a tree-based container, but our attribute
|
||||
// lists are likely to stay so short as to not be an issue.
|
||||
for ( size_t i = 0; i < attributes.size(); i++ )
|
||||
{
|
||||
if ( attribute == attributes[i]->name )
|
||||
return attributes[i];
|
||||
}
|
||||
if ( required )
|
||||
{
|
||||
throw XMLRequiredAttributeNotFoundException (
|
||||
location,
|
||||
attribute,
|
||||
name );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
XMLElement::FindElement ( const std::string& type, int prev ) const
|
||||
{
|
||||
int done = subElements.size();
|
||||
while ( ++prev < done )
|
||||
{
|
||||
XMLElement* e = subElements[prev];
|
||||
if ( e->name == type )
|
||||
return prev;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
XMLElement::GetElements (
|
||||
const std::string& type,
|
||||
std::vector<XMLElement*>& v )
|
||||
{
|
||||
int find = FindElement ( type );
|
||||
v.resize ( 0 );
|
||||
while ( find != -1 )
|
||||
{
|
||||
v.push_back ( subElements[find] );
|
||||
find = FindElement ( type, find );
|
||||
}
|
||||
return v.size();
|
||||
}
|
||||
|
||||
int
|
||||
XMLElement::GetElements (
|
||||
const std::string& type,
|
||||
std::vector<const XMLElement*>& v ) const
|
||||
{
|
||||
int find = FindElement ( type );
|
||||
v.resize ( 0 );
|
||||
while ( find != -1 )
|
||||
{
|
||||
v.push_back ( subElements[find] );
|
||||
find = FindElement ( type, find );
|
||||
}
|
||||
return v.size();
|
||||
}
|
||||
|
||||
// XMLParse()
|
||||
// This function reads a "token" from the file loaded in XMLFile
|
||||
// if it finds a tag that is non-singular, it parses sub-elements and/or
|
||||
// inner text into the XMLElement that it is building to return.
|
||||
// Return Value: an XMLElement allocated via the new operator that contains
|
||||
// it's parsed data. Keep calling this function until it returns NULL
|
||||
// (no more data)
|
||||
XMLElement*
|
||||
XMLParse (
|
||||
XMLFile& f,
|
||||
XMLIncludes* includes,
|
||||
const Path& path,
|
||||
bool* pend_tag = NULL )
|
||||
{
|
||||
string token, location;
|
||||
if ( !f.get_token(token,location) )
|
||||
return NULL;
|
||||
bool end_tag, is_include = false;
|
||||
|
||||
while
|
||||
(
|
||||
token[0] != '<'
|
||||
|| !strncmp ( token.c_str (), "<!--", 4 )
|
||||
|| !strncmp ( token.c_str (), "<?", 2 )
|
||||
)
|
||||
{
|
||||
if ( token[0] != '<' )
|
||||
{
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"expecting xml tag, not '%s'",
|
||||
token.c_str () );
|
||||
}
|
||||
if ( !f.get_token ( token, location ) )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XMLElement* e = new XMLElement (
|
||||
&f,
|
||||
location );
|
||||
bool bNeedEnd = e->Parse ( token, end_tag );
|
||||
|
||||
if ( e->name == "xi:include" && includes )
|
||||
{
|
||||
XMLAttribute* att;
|
||||
att = e->GetAttribute ( "href", true );
|
||||
assert ( att );
|
||||
string includeFile ( path.Fixup ( att->value, true ) );
|
||||
string topIncludeFile (
|
||||
Path::RelativeFromWorkingDirectory ( includeFile ) );
|
||||
includes->push_back (
|
||||
new XMLInclude ( e, path, topIncludeFile ) );
|
||||
is_include = true;
|
||||
}
|
||||
|
||||
if ( !bNeedEnd )
|
||||
{
|
||||
if ( pend_tag )
|
||||
*pend_tag = end_tag;
|
||||
else if ( end_tag )
|
||||
{
|
||||
delete e;
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"end tag '%s' not expected",
|
||||
token.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
bool bThisMixingErrorReported = false;
|
||||
while ( f.more_tokens () )
|
||||
{
|
||||
if ( f.next_is_text () )
|
||||
{
|
||||
if ( !f.get_token ( token, location ) || token.size () == 0 )
|
||||
{
|
||||
throw XMLInvalidBuildFileException (
|
||||
location,
|
||||
"internal tool error - get_token() failed when more_tokens() returned true" );
|
||||
break;
|
||||
}
|
||||
if ( e->subElements.size() && !bThisMixingErrorReported )
|
||||
{
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"mixing of inner text with sub elements" );
|
||||
bThisMixingErrorReported = true;
|
||||
}
|
||||
if ( strchr ( token.c_str (), '>' ) )
|
||||
{
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"invalid symbol '>'" );
|
||||
}
|
||||
if ( e->value.size() > 0 )
|
||||
{
|
||||
throw XMLSyntaxErrorException (
|
||||
location,
|
||||
"multiple instances of inner text" );
|
||||
e->value += " " + token;
|
||||
}
|
||||
else
|
||||
e->value = token;
|
||||
}
|
||||
else
|
||||
{
|
||||
XMLElement* e2 = XMLParse (
|
||||
f, is_include ? NULL : includes, path, &end_tag );
|
||||
if ( !e2 )
|
||||
{
|
||||
string e_location = e->location;
|
||||
string e_name = e->name;
|
||||
delete e;
|
||||
throw XMLInvalidBuildFileException (
|
||||
e_location,
|
||||
"end of file found looking for end tag: </%s>",
|
||||
e_name.c_str() );
|
||||
break;
|
||||
}
|
||||
if ( end_tag )
|
||||
{
|
||||
if ( e->name != e2->name )
|
||||
{
|
||||
string e2_location = e2->location;
|
||||
string e_name = e->name;
|
||||
string e2_name = e2->name;
|
||||
delete e;
|
||||
delete e2;
|
||||
throw XMLSyntaxErrorException (
|
||||
e2_location,
|
||||
"end tag name mismatch - found </%s> but was expecting </%s>",
|
||||
e2_name.c_str(),
|
||||
e_name.c_str() );
|
||||
break;
|
||||
}
|
||||
delete e2;
|
||||
break;
|
||||
}
|
||||
if ( e->value.size () > 0 && !bThisMixingErrorReported )
|
||||
{
|
||||
string e_location = e->location;
|
||||
delete e;
|
||||
throw XMLSyntaxErrorException (
|
||||
e_location,
|
||||
"mixing of inner text with sub elements" );
|
||||
bThisMixingErrorReported = true;
|
||||
}
|
||||
e->AddSubElement ( e2 );
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void
|
||||
XMLReadFile (
|
||||
XMLFile& f,
|
||||
XMLElement& head,
|
||||
XMLIncludes& includes,
|
||||
const Path& path )
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
XMLElement* e = XMLParse ( f, &includes, path );
|
||||
if ( !e )
|
||||
return;
|
||||
head.AddSubElement ( e );
|
||||
}
|
||||
}
|
||||
|
||||
XMLElement*
|
||||
XMLLoadInclude (
|
||||
XMLInclude& include,
|
||||
XMLIncludes& includes )
|
||||
{
|
||||
XMLAttribute* att;
|
||||
att = include.e->GetAttribute("href", true);
|
||||
assert(att);
|
||||
|
||||
string file ( include.path.Fixup(att->value, true) );
|
||||
string top_file ( Path::RelativeFromWorkingDirectory ( file ) );
|
||||
include.e->attributes.push_back ( new XMLAttribute ( "top_href", top_file ) );
|
||||
XMLFile* fInc = new XMLFile();
|
||||
if ( !fInc->open ( file ) )
|
||||
{
|
||||
include.fileExists = false;
|
||||
// look for xi:fallback element
|
||||
for ( size_t i = 0; i < include.e->subElements.size (); i++ )
|
||||
{
|
||||
XMLElement* e2 = include.e->subElements[i];
|
||||
if ( e2->name == "xi:fallback" )
|
||||
{
|
||||
// now look for xi:include below...
|
||||
for ( i = 0; i < e2->subElements.size (); i++ )
|
||||
{
|
||||
XMLElement* e3 = e2->subElements[i];
|
||||
if ( e3->name == "xi:include" )
|
||||
{
|
||||
att = e3->GetAttribute ( "href", true );
|
||||
assert ( att );
|
||||
string includeFile (
|
||||
include.path.Fixup ( att->value, true ) );
|
||||
string topIncludeFile (
|
||||
Path::RelativeFromWorkingDirectory ( includeFile ) );
|
||||
XMLInclude* fallbackInclude =
|
||||
new XMLInclude ( e3, include.path, topIncludeFile );
|
||||
|
||||
XMLElement* value = XMLLoadInclude (*fallbackInclude, includes );
|
||||
delete fallbackInclude;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
throw XMLInvalidBuildFileException (
|
||||
e2->location,
|
||||
"<xi:fallback> must have a <xi:include> sub-element" );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
include.fileExists = true;
|
||||
XMLElement* new_e = new XMLElement (
|
||||
fInc,
|
||||
include.e->location );
|
||||
new_e->name = "xi:included";
|
||||
Path path2 ( include.path, att->value );
|
||||
XMLReadFile ( *fInc, *new_e, includes, path2 );
|
||||
return new_e;
|
||||
}
|
||||
}
|
||||
|
||||
XMLElement*
|
||||
XMLLoadFile (
|
||||
const string& filename,
|
||||
const Path& path,
|
||||
XMLIncludes& includes )
|
||||
{
|
||||
XMLFile* f = new XMLFile();
|
||||
|
||||
if ( !f->open ( filename ) )
|
||||
{
|
||||
delete f;
|
||||
throw XMLFileNotFoundException ( "(virtual)", filename );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XMLElement* head = new XMLElement ( f, "(virtual)" );
|
||||
|
||||
XMLReadFile ( *f, *head, includes, path );
|
||||
|
||||
for ( size_t i = 0; i < includes.size (); i++ )
|
||||
{
|
||||
XMLElement* e = includes[i]->e;
|
||||
XMLElement* e2 = XMLLoadInclude ( *includes[i], includes );
|
||||
if ( !e2 )
|
||||
{
|
||||
throw XMLFileNotFoundException (
|
||||
f->Location(),
|
||||
e->GetAttribute ( "top_href", true )->value );
|
||||
}
|
||||
XMLElement* parent = e->parentElement;
|
||||
XMLElement** parent_container = NULL;
|
||||
if ( !parent )
|
||||
{
|
||||
string location = e->location;
|
||||
delete e;
|
||||
delete f;
|
||||
throw XMLException ( location, "internal tool error: xi:include doesn't have a parent" );
|
||||
return NULL;
|
||||
}
|
||||
for ( size_t j = 0; j < parent->subElements.size (); j++ )
|
||||
{
|
||||
if ( parent->subElements[j] == e )
|
||||
{
|
||||
parent_container = &parent->subElements[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !parent_container )
|
||||
{
|
||||
string location = e->location;
|
||||
delete e;
|
||||
delete f;
|
||||
throw XMLException ( location, "internal tool error: couldn't find xi:include in parent's sub-elements" );
|
||||
return NULL;
|
||||
}
|
||||
// replace inclusion tree with the imported tree
|
||||
e2->parentElement = e->parentElement;
|
||||
e2->name = e->name;
|
||||
e2->attributes = e->attributes;
|
||||
*parent_container = e2;
|
||||
e->attributes.resize ( 0 );
|
||||
delete e;
|
||||
}
|
||||
delete f;
|
||||
return head;
|
||||
}
|
||||
|
||||
XMLElement*
|
||||
XMLLoadFile ( const string& filename )
|
||||
{
|
||||
Path path;
|
||||
XMLIncludes includes;
|
||||
return XMLLoadFile ( filename, path, includes );
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Casper S. Hornstrup
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdarg.h>
|
||||
|
||||
class XMLElement;
|
||||
|
||||
extern std::string working_directory;
|
||||
|
||||
void
|
||||
InitWorkingDirectory();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
unsigned __int64
|
||||
#else
|
||||
unsigned long long
|
||||
#endif
|
||||
filelen ( FILE* f );
|
||||
|
||||
class XMLException
|
||||
{
|
||||
public:
|
||||
XMLException ( const std::string& location, const char* format, ... );
|
||||
const std::string& operator *() { return _e; }
|
||||
|
||||
protected:
|
||||
XMLException() {}
|
||||
void SetExceptionV ( const std::string& location, const char* format, va_list args );
|
||||
void SetException ( const std::string& location, const char* format, ... );
|
||||
|
||||
private:
|
||||
std::string _e;
|
||||
};
|
||||
|
||||
class XMLSyntaxErrorException : public XMLException
|
||||
{
|
||||
public:
|
||||
XMLSyntaxErrorException (
|
||||
const std::string& location,
|
||||
const char* format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start ( args, format );
|
||||
SetExceptionV ( location, format, args );
|
||||
va_end ( args );
|
||||
}
|
||||
};
|
||||
|
||||
class XMLRequiredAttributeNotFoundException : public XMLException
|
||||
{
|
||||
public:
|
||||
XMLRequiredAttributeNotFoundException (
|
||||
const std::string& location,
|
||||
const std::string& attributeName,
|
||||
const std::string& elementName )
|
||||
{
|
||||
SetException ( location, "Required attribute '%s' not found in element '%s'",
|
||||
attributeName.c_str(),
|
||||
elementName.c_str() );
|
||||
}
|
||||
};
|
||||
|
||||
class XMLInvalidBuildFileException : public XMLException
|
||||
{
|
||||
public:
|
||||
XMLInvalidBuildFileException (
|
||||
const std::string& location,
|
||||
const char* format,
|
||||
... )
|
||||
{
|
||||
va_list args;
|
||||
va_start ( args, format );
|
||||
SetExceptionV ( location, format, args );
|
||||
va_end ( args );
|
||||
}
|
||||
};
|
||||
|
||||
class XMLFileNotFoundException : public XMLException
|
||||
{
|
||||
public:
|
||||
XMLFileNotFoundException (
|
||||
const std::string& location,
|
||||
const std::string& filename )
|
||||
{
|
||||
SetException ( location, "Can't open file '%s'", filename.c_str() );
|
||||
}
|
||||
};
|
||||
|
||||
class Path
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
public:
|
||||
Path(); // initializes path to getcwd();
|
||||
Path ( const Path& cwd, const std::string& filename );
|
||||
std::string Fixup ( const std::string& filename, bool include_filename ) const;
|
||||
|
||||
std::string RelativeFromWorkingDirectory ();
|
||||
static std::string RelativeFromWorkingDirectory ( const std::string& path );
|
||||
static std::string RelativeFromDirectory ( const std::string& path, const std::string& base_directory);
|
||||
|
||||
static void Split (
|
||||
std::vector<std::string>& out,
|
||||
const std::string& path,
|
||||
bool include_last );
|
||||
};
|
||||
|
||||
class XMLInclude
|
||||
{
|
||||
public:
|
||||
XMLElement *e;
|
||||
Path path;
|
||||
std::string topIncludeFilename;
|
||||
bool fileExists;
|
||||
|
||||
XMLInclude (
|
||||
XMLElement* e_,
|
||||
const Path& path_,
|
||||
const std::string topIncludeFilename_ )
|
||||
: e ( e_ ),
|
||||
path ( path_ ),
|
||||
topIncludeFilename ( topIncludeFilename_ )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class XMLIncludes : public std::vector<XMLInclude*>
|
||||
{
|
||||
public:
|
||||
~XMLIncludes();
|
||||
};
|
||||
|
||||
class XMLFile
|
||||
{
|
||||
friend class XMLElement;
|
||||
public:
|
||||
XMLFile();
|
||||
void close();
|
||||
bool open(const std::string& filename);
|
||||
void next_token();
|
||||
bool next_is_text();
|
||||
bool more_tokens();
|
||||
bool get_token ( std::string& token );
|
||||
bool get_token ( std::string& token, std::string& location );
|
||||
const std::string& filename() { return _filename; }
|
||||
std::string Location() const;
|
||||
|
||||
private:
|
||||
std::string _buf, _filename;
|
||||
|
||||
const char *_p, *_end;
|
||||
};
|
||||
|
||||
|
||||
class XMLAttribute
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
std::string value;
|
||||
|
||||
XMLAttribute();
|
||||
XMLAttribute ( const std::string& name_, const std::string& value_ );
|
||||
XMLAttribute ( const XMLAttribute& );
|
||||
XMLAttribute& operator = ( const XMLAttribute& );
|
||||
};
|
||||
|
||||
|
||||
class XMLElement
|
||||
{
|
||||
public:
|
||||
XMLFile* xmlFile;
|
||||
std::string location;
|
||||
std::string name;
|
||||
std::vector<XMLAttribute*> attributes;
|
||||
XMLElement* parentElement;
|
||||
std::vector<XMLElement*> subElements;
|
||||
std::string value;
|
||||
|
||||
XMLElement (
|
||||
XMLFile* xmlFile,
|
||||
const std::string& location );
|
||||
|
||||
~XMLElement();
|
||||
|
||||
bool Parse (
|
||||
const std::string& token,
|
||||
bool& end_tag);
|
||||
|
||||
void AddSubElement ( XMLElement* e );
|
||||
|
||||
XMLAttribute* GetAttribute (
|
||||
const std::string& attribute,
|
||||
bool required);
|
||||
|
||||
const XMLAttribute* GetAttribute (
|
||||
const std::string& attribute,
|
||||
bool required ) const;
|
||||
|
||||
int FindElement (
|
||||
const std::string& type,
|
||||
int prev = -1 ) const;
|
||||
|
||||
int GetElements (
|
||||
const std::string& type,
|
||||
std::vector<XMLElement*>& v );
|
||||
|
||||
int GetElements (
|
||||
const std::string& type,
|
||||
std::vector<const XMLElement*>& v ) const;
|
||||
};
|
||||
|
||||
XMLElement*
|
||||
XMLLoadFile (
|
||||
const std::string& filename,
|
||||
const Path& path,
|
||||
XMLIncludes& includes );
|
||||
|
||||
XMLElement*
|
||||
XMLLoadFile ( const std::string& filename );
|
||||
|
||||
std::vector<char> vectorize(const std::string &str);
|
||||
void vectappend(std::vector<char> &strvec, char ch);
|
||||
void vectappend(std::vector<char> &strvec, const char *charstr);
|
||||
void vectappend(std::vector<char> &strvec, const std::string &str);
|
Loading…
Add table
Add a link
Reference in a new issue