NewOS revisited, applied patch 1916: now evaluates the extended BIOS
RAM size call. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6984 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4f5f1b3c0c
commit
3bba0ebe0a
@ -25,11 +25,12 @@
|
||||
; ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
; /*
|
||||
; ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
; ** Copyright 2004, The OpenBeOS Team. All rights reserved.
|
||||
; ** Distributed under the terms of the OpenBeOS License.
|
||||
; **
|
||||
; ** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.
|
||||
; ** Distributed under the terms of the NewOS License.
|
||||
; */
|
||||
|
||||
; /*
|
||||
; **
|
||||
; ** Reviewed, documented and some minor modifications and bug-fixes
|
||||
; ** applied by Michael Noisternig on 2001-09-02.
|
||||
; */
|
||||
@ -89,15 +90,17 @@ unreal:
|
||||
sti
|
||||
mov si,loadmsg
|
||||
call print
|
||||
dec cx ; TK: one sector is already read as second part of boot block
|
||||
call load_floppy ; read remaining sectors at address edi
|
||||
call disable_floppy_motor
|
||||
mov si,okmsg
|
||||
call print
|
||||
cli
|
||||
|
||||
; uncomment the next two lines to enable the VESA mode switch
|
||||
; call enable_vesa
|
||||
mov [in_vesa],al
|
||||
; mov [in_vesa],al
|
||||
|
||||
call find_mem_size_real
|
||||
|
||||
mov ebx,[dword 0x100074] ; load dword at rel. address 0x74 from read-destination-buffer
|
||||
add ebx,0x101000 ; for stage2 entry
|
||||
@ -111,7 +114,7 @@ unreal:
|
||||
jmp dword 0x8:code32 ; flush prefetch queue
|
||||
code32:
|
||||
BITS 32
|
||||
mov ax,0x10 ; load descriptor 2 in all segment selectors (except cs)
|
||||
mov ax,0x10 ; load descriptor 2 in all segment selectors (except cs)
|
||||
mov ds,ax
|
||||
mov es,ax
|
||||
mov fs,ax
|
||||
@ -120,38 +123,39 @@ BITS 32
|
||||
mov ebp,0x10000
|
||||
mov esp,ebp
|
||||
|
||||
mov eax,[vesa_info]
|
||||
mov eax,[vesa_info] ; set up arguments for _start()
|
||||
push eax
|
||||
|
||||
xor eax,eax
|
||||
mov al,[in_vesa]
|
||||
push eax
|
||||
|
||||
call find_mem_size
|
||||
xor eax,eax
|
||||
mov al,[ext_mem_count]
|
||||
push eax
|
||||
|
||||
call ebx ; jump to stage2 entry
|
||||
inf:jmp short inf
|
||||
cmp al, 0x0
|
||||
je probe_mem
|
||||
|
||||
; find memory size by testing
|
||||
; OUT: eax = memory size
|
||||
find_mem_size:
|
||||
mov eax,0x31323738 ; test value
|
||||
mov esi,0x100ff0 ; start above conventional mem + HMA = 1 MB + 1024 Byte
|
||||
_fms_loop:
|
||||
mov edx,[esi] ; read value
|
||||
mov [esi],eax ; write test value
|
||||
mov ecx,[esi] ; read it again
|
||||
mov [esi],edx ; write back old value
|
||||
cmp ecx,eax
|
||||
jnz _fms_loop_out ; read value != test value -> above mem limit
|
||||
add esi,0x1000 ; test next page (4 K)
|
||||
jmp short _fms_loop
|
||||
_fms_loop_out:
|
||||
mov eax,esi
|
||||
sub eax,0x1000
|
||||
add eax,byte +0x10
|
||||
ret
|
||||
mov eax,[ext_mem_info]
|
||||
push eax
|
||||
|
||||
xor eax,eax ; argument mem_size is loaded
|
||||
push eax ; with zero
|
||||
|
||||
jmp call_stage2
|
||||
|
||||
probe_mem:
|
||||
xor eax,eax ; argument ext_mem_info is
|
||||
push eax ; loaded with zero
|
||||
|
||||
call find_mem_size_probe
|
||||
push eax
|
||||
; falls through
|
||||
|
||||
call_stage2:
|
||||
call ebx ; jump to stage2 entry
|
||||
inf:jmp short inf
|
||||
|
||||
BITS 16
|
||||
; read sectors into memory
|
||||
@ -276,13 +280,64 @@ gdt:
|
||||
|
||||
retrycnt db 3
|
||||
in_vesa db 0
|
||||
vesa_info dw 0
|
||||
vesa_info dd 0
|
||||
ext_mem_info dd 0
|
||||
ext_mem_count db 0
|
||||
|
||||
times 510-($-$$) db 0 ; filler for boot sector
|
||||
dw 0xaa55 ; magic number for boot sector
|
||||
|
||||
; Starting here is the second sector of the boot code
|
||||
|
||||
BITS 32
|
||||
; find memory size by testing
|
||||
; OUT: eax = memory size
|
||||
find_mem_size_probe:
|
||||
mov eax,0x31323738 ; test value
|
||||
mov esi,0x100ff0 ; start above conventional mem + HMA = 1 MB + 1024 Byte
|
||||
_fms_loop:
|
||||
mov edx,[esi] ; read value
|
||||
mov [esi],eax ; write test value
|
||||
mov ecx,[esi] ; read it again
|
||||
mov [esi],edx ; write back old value
|
||||
cmp ecx,eax
|
||||
jnz _fms_loop_out ; read value != test value -> above mem limit
|
||||
add esi,0x1000 ; test next page (4 K)
|
||||
jmp short _fms_loop
|
||||
_fms_loop_out:
|
||||
mov eax,esi
|
||||
sub eax,0x1000
|
||||
add eax,byte +0x10
|
||||
ret
|
||||
|
||||
BITS 16
|
||||
find_mem_size_real:
|
||||
; use int 0x15, EAX=0xe820 to test for memory
|
||||
; assumes es is null
|
||||
|
||||
mov ebx,0
|
||||
mov edi,0x7000 ; the extended memory structures will go at 0x7000
|
||||
mov [ext_mem_info],edi
|
||||
|
||||
find_mem_next:
|
||||
mov eax,0xe820
|
||||
mov edx,'PAMS' ; 'SMAP' in the correct order
|
||||
mov ecx,0x20
|
||||
|
||||
int 0x15
|
||||
jc done_mem_real ; if carry is set, it wasn't supported
|
||||
|
||||
inc byte [ext_mem_count] ; increment the count of the number
|
||||
|
||||
cmp ebx,0x0 ; test if we're done
|
||||
je done_mem_real
|
||||
|
||||
add edi,0x20 ; increment the buffer by 0x20
|
||||
jmp find_mem_next
|
||||
|
||||
done_mem_real:
|
||||
ret
|
||||
|
||||
; fool around with vesa mode
|
||||
enable_vesa:
|
||||
; put the VBEInfo struct at 0x30000
|
||||
@ -325,6 +380,7 @@ mode_loop:
|
||||
test ax,0x1 ; test the supported bit
|
||||
jz next_mode
|
||||
test ax,0x08 ; test the linear frame mode bit
|
||||
jz next_mode
|
||||
mov ax,[es:di+18]
|
||||
cmp ax,VESA_X_TARGET ; x
|
||||
jne next_mode
|
||||
|
Binary file not shown.
@ -25,11 +25,19 @@ const unsigned kBSSSize = 0x9000;
|
||||
# define MESSAGE(x)
|
||||
#endif
|
||||
|
||||
// memory structure returned by int 0x15, ax 0xe820
|
||||
typedef struct ext_memory {
|
||||
uint64 base_addr;
|
||||
uint64 length;
|
||||
uint64 type;
|
||||
uint64 filler;
|
||||
} ext_memory;
|
||||
|
||||
// we're running out of the first 'file' contained in the bootdir, which is
|
||||
// a set of binaries and data packed back to back, described by an array
|
||||
// of boot_entry structures at the beginning. The load address is fixed.
|
||||
#define BOOTDIR_ADDR 0x100000
|
||||
static const boot_entry *bootdir = (boot_entry*)BOOTDIR_ADDR;
|
||||
static const boot_entry *bootdir = (boot_entry *)BOOTDIR_ADDR;
|
||||
|
||||
// stick the kernel arguments in a pseudo-random page that will be mapped
|
||||
// at least during the call into the kernel. The kernel should copy the
|
||||
@ -37,7 +45,7 @@ static const boot_entry *bootdir = (boot_entry*)BOOTDIR_ADDR;
|
||||
static kernel_args *ka = (kernel_args *)0x20000;
|
||||
|
||||
// needed for message
|
||||
static uint16 *kScreenBase = (unsigned short*) 0xb8000;
|
||||
static uint16 *kScreenBase = (uint16 *)0xb8000;
|
||||
static uint32 screenOffset = 0;
|
||||
|
||||
unsigned int cv_factor = 0;
|
||||
@ -50,6 +58,7 @@ static uint32 *pgdir = 0;
|
||||
static uint32 *pgtable = 0;
|
||||
|
||||
// function decls for this module
|
||||
static void sort_addr_range(addr_range *range, int count);
|
||||
static void calculate_cpu_conversion_factor(void);
|
||||
static void load_elf_image(void *data, uint32 *next_paddr, addr_range *ar0,
|
||||
addr_range *ar1, uint32 *start_addr, addr_range *dynamic_section);
|
||||
@ -58,6 +67,9 @@ static void mmu_map_page(uint32 vaddr, uint32 paddr);
|
||||
static int check_cpu(void);
|
||||
|
||||
|
||||
extern void _start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
||||
int in_vesa, uint32 vesa_ptr);
|
||||
|
||||
/* called by the stage1 bootloader.
|
||||
* State:
|
||||
* 32-bit
|
||||
@ -67,7 +79,8 @@ static int check_cpu(void);
|
||||
*/
|
||||
|
||||
void
|
||||
_start(uint32 mem, int in_vesa, uint32 vesa_ptr)
|
||||
_start(uint32 memSize, ext_memory *extMemoryBlock, uint32 extMemoryCount,
|
||||
int in_vesa, uint32 vesa_ptr)
|
||||
{
|
||||
uint32 *idt;
|
||||
segment_descriptor *gdt;
|
||||
@ -82,7 +95,8 @@ _start(uint32 mem, int in_vesa, uint32 vesa_ptr)
|
||||
clearscreen();
|
||||
|
||||
dprintf("stage2 bootloader entry.\n");
|
||||
dprintf("memsize = 0x%x, in_vesa %d, vesa_ptr 0x%x\n", mem, in_vesa, vesa_ptr);
|
||||
dprintf("args: memsize 0x%x, emem_block %p, emem_count %d, in_vesa %d, vesa = %p\n",
|
||||
memSize, extMemoryBlock, extMemoryCount, in_vesa, vesa_ptr);
|
||||
|
||||
// verify we can run on this cpu
|
||||
if (check_cpu() < 0) {
|
||||
@ -95,6 +109,16 @@ _start(uint32 mem, int in_vesa, uint32 vesa_ptr)
|
||||
for (;;);
|
||||
}
|
||||
|
||||
if (extMemoryCount > 0) {
|
||||
uint32 i;
|
||||
|
||||
dprintf("extended memory info (from 0xe820):\n");
|
||||
for (i = 0; i < extMemoryCount; i++) {
|
||||
dprintf(" base 0x%Lx, len 0x%Lx, type %Ld\n",
|
||||
extMemoryBlock[i].base_addr, extMemoryBlock[i].length, extMemoryBlock[i].type);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the conversion factor that translates rdtsc time to real microseconds
|
||||
calculate_cpu_conversion_factor();
|
||||
|
||||
@ -234,18 +258,96 @@ _start(uint32 mem, int in_vesa, uint32 vesa_ptr)
|
||||
ka->arch_args.vir_pgdir = next_vaddr;
|
||||
next_vaddr += PAGE_SIZE;
|
||||
|
||||
// save the kernel args
|
||||
ka->arch_args.system_time_cv_factor = cv_factor;
|
||||
ka->physical_memory_range[0].start = 0;
|
||||
ka->physical_memory_range[0].size = mem;
|
||||
ka->num_physical_memory_ranges = 1;
|
||||
ka->str = NULL;
|
||||
// mark memory that we know is used
|
||||
ka->physical_allocated_range[0].start = BOOTDIR_ADDR;
|
||||
ka->physical_allocated_range[0].size = next_paddr - BOOTDIR_ADDR;
|
||||
ka->num_physical_allocated_ranges = 1;
|
||||
|
||||
// figure out the memory map
|
||||
if (extMemoryCount > 0) {
|
||||
uint32 i;
|
||||
|
||||
ka->num_physical_memory_ranges = 0;
|
||||
|
||||
for (i = 0; i < extMemoryCount; i++) {
|
||||
if (extMemoryBlock[i].type == 1) {
|
||||
// round everything up to page boundaries, exclusive of pages it partially occupies
|
||||
extMemoryBlock[i].length -= (extMemoryBlock[i].base_addr % PAGE_SIZE)
|
||||
? (PAGE_SIZE - (extMemoryBlock[i].base_addr % PAGE_SIZE)) : 0;
|
||||
extMemoryBlock[i].base_addr = ROUNDUP(extMemoryBlock[i].base_addr, PAGE_SIZE);
|
||||
extMemoryBlock[i].length = ROUNDOWN(extMemoryBlock[i].length, PAGE_SIZE);
|
||||
|
||||
// this is mem we can use
|
||||
if (ka->num_physical_memory_ranges == 0) {
|
||||
ka->physical_memory_range[0].start = (addr_t)extMemoryBlock[i].base_addr;
|
||||
ka->physical_memory_range[0].size = (addr_t)extMemoryBlock[i].length;
|
||||
ka->num_physical_memory_ranges++;
|
||||
} else {
|
||||
// we might have to extend the previous hole
|
||||
addr_t previous_end = ka->physical_memory_range[ka->num_physical_memory_ranges - 1].start
|
||||
+ ka->physical_memory_range[ka->num_physical_memory_ranges - 1].size;
|
||||
|
||||
if (previous_end <= extMemoryBlock[i].base_addr
|
||||
&& ((extMemoryBlock[i].base_addr - previous_end) < 0x100000)) {
|
||||
// extend the previous buffer
|
||||
ka->physical_memory_range[ka->num_physical_memory_ranges - 1].size +=
|
||||
(extMemoryBlock[i].base_addr - previous_end) +
|
||||
extMemoryBlock[i].length;
|
||||
|
||||
// mark the gap between the two allocated ranges in use
|
||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].start = previous_end;
|
||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].size = extMemoryBlock[i].base_addr - previous_end;
|
||||
ka->num_physical_allocated_ranges++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we dont have an extended map, assume memory is contiguously mapped at 0x0
|
||||
ka->physical_memory_range[0].start = 0;
|
||||
ka->physical_memory_range[0].size = memSize;
|
||||
ka->num_physical_memory_ranges = 1;
|
||||
|
||||
// mark the bios area allocated
|
||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].start = 0x9f000; // 640k - 1 page
|
||||
ka->physical_allocated_range[ka->num_physical_allocated_ranges].size = 0x61000;
|
||||
ka->num_physical_allocated_ranges++;
|
||||
}
|
||||
|
||||
// save the memory we've virtually allocated (for the kernel and other stuff)
|
||||
ka->virtual_allocated_range[0].start = KERNEL_BASE;
|
||||
ka->virtual_allocated_range[0].size = next_vaddr - KERNEL_BASE;
|
||||
ka->num_virtual_allocated_ranges = 1;
|
||||
|
||||
// sort the address ranges
|
||||
sort_addr_range(ka->physical_memory_range, ka->num_physical_memory_ranges);
|
||||
sort_addr_range(ka->physical_allocated_range, ka->num_physical_allocated_ranges);
|
||||
sort_addr_range(ka->virtual_allocated_range, ka->num_virtual_allocated_ranges);
|
||||
|
||||
#if 1
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
dprintf("phys memory ranges:\n");
|
||||
for (i = 0; i < ka->num_physical_memory_ranges; i++) {
|
||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->physical_memory_range[i].start, ka->physical_memory_range[i].size);
|
||||
}
|
||||
|
||||
dprintf("allocated phys memory ranges:\n");
|
||||
for (i = 0; i < ka->num_physical_allocated_ranges; i++) {
|
||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->physical_allocated_range[i].start, ka->physical_allocated_range[i].size);
|
||||
}
|
||||
|
||||
dprintf("allocated virt memory ranges:\n");
|
||||
for (i = 0; i < ka->num_virtual_allocated_ranges; i++) {
|
||||
dprintf(" base 0x%08lx, length 0x%08lx\n", ka->virtual_allocated_range[i].start, ka->virtual_allocated_range[i].size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// save the kernel args
|
||||
ka->arch_args.system_time_cv_factor = cv_factor;
|
||||
ka->str = NULL;
|
||||
ka->arch_args.page_hole = 0xffc00000;
|
||||
ka->num_cpus = 1;
|
||||
#if 0
|
||||
@ -491,6 +593,27 @@ sleep(uint64 time)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sort_addr_range(addr_range *range, int count)
|
||||
{
|
||||
addr_range tempRange;
|
||||
bool done;
|
||||
int i;
|
||||
|
||||
do {
|
||||
done = true;
|
||||
for (i = 1; i < count; i++) {
|
||||
if (range[i].start < range[i - 1].start) {
|
||||
done = false;
|
||||
memcpy(&tempRange, &range[i], sizeof(addr_range));
|
||||
memcpy(&range[i], &range[i - 1], sizeof(addr_range));
|
||||
memcpy(&range[i - 1], &tempRange, sizeof(addr_range));
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
|
||||
#define outb(value,port) \
|
||||
asm("outb %%al,%%dx"::"a" (value),"d" (port))
|
||||
|
||||
@ -687,10 +810,12 @@ static void
|
||||
scrup()
|
||||
{
|
||||
int i;
|
||||
|
||||
memcpy(kScreenBase, kScreenBase + SCREEN_WIDTH,
|
||||
SCREEN_WIDTH * SCREEN_HEIGHT * 2 - SCREEN_WIDTH * 2);
|
||||
screenOffset = (SCREEN_HEIGHT - 1) * SCREEN_WIDTH;
|
||||
for(i=0; i<SCREEN_WIDTH; i++)
|
||||
|
||||
for (i = 0; i < SCREEN_WIDTH; i++)
|
||||
kScreenBase[screenOffset + i] = 0x0720;
|
||||
}
|
||||
|
||||
@ -720,7 +845,7 @@ dprintf(const char *fmt, ...)
|
||||
char temp[256];
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vsprintf(temp,fmt,args);
|
||||
ret = vsprintf(temp, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
kputs(temp);
|
||||
|
Loading…
Reference in New Issue
Block a user