Page 3 of 3

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 8:47 am
by ThisMayWork
After the MB Info is pushed. Should it be the opposite way?

Sidenote: I just realised that I could simply specify an address and have the kernel read from it to get the MB info. Is this in any way worse that passing it in the function?

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 8:49 am
by Octocontrabass
ThisMayWork wrote:After the MB Info is pushed.
I don't see it anywhere in the code you posted earlier, and you haven't posted any updated code.

Re: mmap_addr and mmap_length constant?

Posted: Wed Jun 17, 2015 9:06 am
by ThisMayWork
I just realised I changed that to try and track down the error. From stage 2 to stage 3 it is a normal jump so it should not modify the stack. That means that MB Info is still at the correct place. Then, on stage 3 I call kernel_entry. The new values are 0x0 for length and addr of mmap and 0x985 for the multiboot address.

Re: mmap_addr and mmap_length constant?

Posted: Wed Aug 05, 2015 2:16 pm
by ThisMayWork
Update: Instead of pushing the pointer for multiboot info on the stack and receiving it as a parameter in my main function, I decided to just copy it to a constant memory address and retrieve it as a double pointer in C code but it still isn't giving me correct values. Any ideas? Code:

Code: Select all

        call	BiosGetMemorySize64MB ;Here I fill my boot_info struct

	mov		word [boot_info+multiboot_info.memoryHi], bx
	mov		word [boot_info+multiboot_info.memoryLo], ax

	mov		eax, 0x0
	mov		ds, ax
	mov		di, 0x1000
	call	BiosGetMemoryMap

Code: Select all

        mov eax, 10000h ;Here I copy it in 0x10000
	mov dword [eax], boot_info

Code: Select all

     struct multiboot_info* mboot = *(struct multiboot_info**)0x10000;
    //Here I retrieve it in C kernel code and print it out. (putun is my kernels way of outputting unsigned numbers, the third parameter is the radix)
    putun("MB Address:", mboot, 16);
    putun("Flags:", mboot->m_flags, 16);
    putun("Mem Lo:", mboot->m_memoryLo, 16);
    putun("Mem Hi:", mboot->m_memoryHi, 16);
    putun("Memory Map Address:", mboot->m_mmap_addr, 16);

Code: Select all

BiosGetMemoryMap:
	pushad
	xor		ebx, ebx
	xor		bp, bp									; number of entries stored here
	mov		edx, 'PAMS'								; 'SMAP'
	mov		eax, 0xe820
	mov		ecx, 24									; memory map entry struct is 24 bytes
	int		0x15									; get first entry
	jc		.error	
	cmp		eax, 'PAMS'								; bios returns SMAP in eax
	jne		.error
	test	ebx, ebx								; if ebx=0 then list is one entry long; bail out
	je		.error
	jmp		.start
.next_entry:
	mov		edx, 'PAMS'								; some bios's trash this register
	mov		ecx, 24									; entry is 24 bytes
	mov		eax, 0xe820
	int		0x15									; get next entry
.start:
	jcxz	.skip_entry								; if actual returned bytes is 0, skip entry
.notext:
	mov		ecx, [es:di + MemoryMapEntry.length]	; get length (low dword)
	test	ecx, ecx								; if length is 0 skip it
	jne		short .good_entry
	mov		ecx, [es:di + MemoryMapEntry.length + 4]; get length (upper dword)
	jecxz	.skip_entry								; if length is 0 skip it
.good_entry:
	inc		bp										; increment entry count
	add		di, 24									; point di to next entry in buffer
.skip_entry:
	cmp		ebx, 0									; if ebx return is 0, list is done
	jne		.next_entry								; get next entry
	jmp		.done
.error:
	stc
.done:
	popad
	ret

;---------------------------------------------
;	Get memory size for >64M configuations (32 bit)
;	ret\ ax=KB between 1MB and 16MB
;	ret\ bx=number of 64K blocks above 16MB
;	ret\ bx=0 and ax= -1 on error
;---------------------------------------------

BiosGetMemorySize64MB_32Bit:
	push	ecx
	push	edx
	xor		ecx, ecx
	xor		edx, edx
	mov		ax, 0xe881
	int		0x15	
	jc		.error
	cmp		ah, 0x86		;unsupported function
	je		.error
	cmp		ah, 0x80		;invalid command
	je		.error
	jcxz	.use_ax			;bios may have stored it in ax,bx or cx,dx. test if cx is 0
	mov		ax, cx			;its not, so it should contain mem size; store it
	mov		bx, dx

.use_ax:
	pop		edx				;mem size is in ax and bx already, return it
	pop		ecx
	ret

.error:
	mov		ax, -1
	mov		bx, 0
	pop		edx
	pop		ecx
	ret
	
;---------------------------------------------
;	Get memory size for >64M configuations
;	ret\ ax=KB between 1MB and 16MB
;	ret\ bx=number of 64K blocks above 16MB
;	ret\ bx=0 and ax= -1 on error
;---------------------------------------------

BiosGetMemorySize64MB:
	push	ecx
	push	edx
	xor		ecx, ecx
	xor		edx, edx
	mov		ax, 0xe801
	int		0x15	
	jc		.error
	cmp		ah, 0x86		;unsupported function
	je		.error
	cmp		ah, 0x80		;invalid command
	je		.error
	jcxz	.use_ax			;bios may have stored it in ax,bx or cx,dx. test if cx is 0
	mov		ax, cx			;its not, so it should contain mem size; store it
	mov		bx, dx

.use_ax:
	pop		edx				;mem size is in ax and bx already, return it
	pop		ecx
	ret

.error:
	mov		ax, -1
	mov		bx, 0
	pop		edx
	pop		ecx
	ret
;Here are my memory functions. I tried both variants for GetMemorySize with no result. 

Re: mmap_addr and mmap_length constant?

Posted: Thu Aug 06, 2015 1:26 am
by Combuster
I see "multiboot" and "int 0x15" in the same code.

I think you forgot the point about using multiboot in the first place... :shock:

Re: mmap_addr and mmap_length constant?

Posted: Thu Aug 06, 2015 1:32 am
by ThisMayWork
I am sorry, but I didn't quite understand what you said. My goal here is to provide the kernel with the exact same multiboot info GRUB and other bootloaders give. Since I do not do any module loading, I do not need to worry about that part, so all I am doing is gathering memory size and map data and pass it to the kernel. Am I thinking wrong here?

Re: mmap_addr and mmap_length constant?

Posted: Thu Aug 06, 2015 9:03 am
by Combuster
Have you ever tried running your kernel against a real multiboot loader and even try to isolate the problem?

Re: mmap_addr and mmap_length constant?

Posted: Thu Aug 06, 2015 12:14 pm
by ThisMayWork
Never thought of that. I'll try it out, thanks Combuster :)