342 lines
6.2 KiB
ArmAsm
Executable File
342 lines
6.2 KiB
ArmAsm
Executable File
.section .multiboot
|
|
|
|
/*
|
|
* Define constants for the multiboot header. See Multiboot 2 Specifications for details.
|
|
*/
|
|
.set align, 1<<0
|
|
.set meminfo, 1<<1
|
|
.set magic, 0xE85250D6
|
|
.set arch, 0
|
|
.set headerLength, _multibootHeaderEnd - _multibootHeaderStart
|
|
.set checksum, -(magic + arch + headerLength)
|
|
|
|
.set tagNotOptional, 0
|
|
|
|
.set tagInfoRequestType, 1
|
|
.set tagInfoRequestSize, _multibootInfoTagEnd - _multibootInfoTagStart
|
|
.set requestBootCommand, 1
|
|
.set requestBootLoaderName, 2
|
|
.set requestBootModules, 3
|
|
.set requestMemoryInfo, 4
|
|
.set requestBootDevice, 5
|
|
.set requestMemoryMap, 6
|
|
|
|
.set tagAddressType, 2
|
|
.set tagAddressSize, 24
|
|
.set tagAddressHeaderLocation, LOAD_START
|
|
.set tagAddressLoadStart, LOAD_START
|
|
.set tagAddressLoadEnd, LOAD_END
|
|
.set tagAddressBSSEnd, BSS_END
|
|
|
|
.set tagEntryType, 3
|
|
.set tagEntrySize, 12
|
|
.set tagEntryAddress, _start - (0xFF900000 - 0x100000)
|
|
|
|
.set tagModuleAlignType, 6
|
|
.set tagModuleAlignSize, 8
|
|
|
|
/*
|
|
* Each multiboot tag must be 8-byte aligned, or GRUB will not be able to read the header.
|
|
*/
|
|
.align 8
|
|
_multibootHeaderStart:
|
|
|
|
.long magic
|
|
.long arch
|
|
.long headerLength
|
|
.long checksum
|
|
|
|
.align 8
|
|
|
|
_multibootInfoTagStart:
|
|
.short tagInfoRequestType
|
|
.short tagNotOptional
|
|
.long tagInfoRequestSize
|
|
.long requestBootCommand
|
|
.long requestBootLoaderName
|
|
.long requestBootModules
|
|
.long requestMemoryInfo
|
|
.long requestBootDevice
|
|
.long requestMemoryMap
|
|
_multibootInfoTagEnd:
|
|
|
|
.align 8
|
|
|
|
.short tagAddressType
|
|
.short tagNotOptional
|
|
.long tagAddressSize
|
|
.long tagAddressHeaderLocation
|
|
.long tagAddressLoadStart
|
|
.long tagAddressLoadEnd
|
|
.long tagAddressBSSEnd
|
|
|
|
.align 8
|
|
|
|
.short tagEntryType
|
|
.short tagNotOptional
|
|
.long tagEntrySize
|
|
.long tagEntryAddress
|
|
|
|
.align 8
|
|
|
|
.short tagModuleAlignType
|
|
.short tagNotOptional
|
|
.long tagModuleAlignSize
|
|
|
|
.align 8
|
|
|
|
/*
|
|
* Terminate list of multiboot header tags.
|
|
* Ending tag has type = 0, flags = 0, size = 8
|
|
*/
|
|
.long 0
|
|
.long 8
|
|
|
|
_multibootHeaderEnd:
|
|
|
|
.section .rodata
|
|
|
|
gdt:
|
|
.long 0, 0
|
|
.short 0xFFFF
|
|
.short 0x0000
|
|
.short 0x9A00
|
|
.short 0x00CF
|
|
.short 0xFFFF
|
|
.short 0x0000
|
|
.short 0x9200
|
|
.short 0x00CF
|
|
|
|
gdt_info:
|
|
.short 23
|
|
.long gdt
|
|
|
|
.section .bss
|
|
|
|
.align 16
|
|
stackBottom:
|
|
.skip 8192
|
|
stackTop:
|
|
|
|
.align 4096
|
|
_tempPgDir:
|
|
.skip 4096
|
|
_tempIdentityMap:
|
|
.skip 4096
|
|
_tempPgTable:
|
|
.skip 8192
|
|
|
|
_bootCmdLine:
|
|
.skip 64
|
|
|
|
.align 64
|
|
.global system_info
|
|
system_info:
|
|
.skip 16
|
|
|
|
.align 64
|
|
.global memory_map
|
|
memory_map:
|
|
.skip 16 * 16
|
|
|
|
.section .text
|
|
.global _start
|
|
.type _start, @function
|
|
_start:
|
|
cmp $0x36d76289, %eax
|
|
jne _err
|
|
|
|
movb $64, 0xB8000
|
|
|
|
mov $system_info, %edi
|
|
sub $BASE_DIFF, %edi
|
|
add $8, %ebx
|
|
|
|
switch:
|
|
mov (%ebx), %eax
|
|
cmp $0, %eax
|
|
je s_end
|
|
cmp $1, %eax
|
|
je tag_1
|
|
cmp $3, %eax
|
|
je tag_3
|
|
cmp $4, %eax
|
|
je tag_4
|
|
cmp $6, %eax
|
|
je tag_6
|
|
cmp $21, %eax
|
|
je tag_21
|
|
jmp def
|
|
|
|
# Boot command line
|
|
tag_1:
|
|
mov 4(%ebx), %ecx
|
|
sub $8, %ecx
|
|
mov %ebx, %esi
|
|
add $8, %esi
|
|
mov $_bootCmdLine, %edi
|
|
sub $BASE_DIFF, %edi
|
|
rep movsb
|
|
mov $system_info, %edi
|
|
sub $BASE_DIFF, %edi
|
|
jmp def
|
|
|
|
tag_3:
|
|
mov 8(%ebx), %esi
|
|
mov (%esi), %eax
|
|
mov %al, (0xB8004)
|
|
mov %ah, (0xB8006)
|
|
shr $16, %eax
|
|
mov %al, (0xB8008)
|
|
mov %ah, (0xB800a)
|
|
jmp def
|
|
|
|
# Basic memory info
|
|
tag_4:
|
|
mov 8(%ebx), %eax
|
|
mov %eax, (%edi)
|
|
mov 12(%ebx), %eax
|
|
mov %eax, 4(%edi)
|
|
jmp def
|
|
|
|
# Memory map
|
|
tag_6:
|
|
mov $memory_map, %esi
|
|
sub $BASE_DIFF, %esi # set esi to point to the table in the kernel image
|
|
mov 4(%ebx), %ecx
|
|
sub $16, %ecx # set ecx to store the size of the table provided by the bootloader
|
|
mov 8(%ebx), %edx # set edx to store the size of each table entry
|
|
add $16, %ebx # move ebx up to the first entry
|
|
1: mov (%ebx), %eax
|
|
mov %eax, (%esi) # save the address of that region in memory
|
|
mov 8(%ebx), %eax
|
|
mov %eax, 4(%esi) # save the size of that region in memory
|
|
mov 16(%ebx), %eax
|
|
mov %eax, 8(%esi) # save the type of memory in that region
|
|
add $12, %esi # move esi to the next entry in the kernel's array
|
|
add %edx, %ebx # move ebx to the next entry in the bootloader's array
|
|
sub %edx, %ecx # subtract the size of an entry from ecx.
|
|
jnz 1b # loop if there are entries left
|
|
mov $0, %eax
|
|
mov %eax, (%esi)
|
|
mov %eax, 4(%esi)
|
|
mov %eax, 8(%esi)
|
|
jmp switch
|
|
|
|
# Program image location
|
|
tag_21:
|
|
mov 8(%ebx), %eax
|
|
mov %eax, 8(%edi)
|
|
jmp def
|
|
|
|
def:
|
|
mov 4(%ebx), %eax
|
|
add $7, %eax
|
|
and $0xFFFFFFF8, %eax
|
|
add %eax, %ebx
|
|
jmp switch
|
|
s_end:
|
|
|
|
movb $64, 0xB8002
|
|
|
|
mov $0, %ecx
|
|
1:
|
|
# Generate a page table entry pointing to a page in the kernel binary
|
|
mov %ecx, %eax
|
|
mov $4096, %edx
|
|
mul %edx
|
|
or $3, %eax
|
|
|
|
# Load the address of the temporary page table and translate it to a physical address
|
|
mov $_tempPgTable, %edi
|
|
sub $BASE_DIFF, %edi
|
|
|
|
# Save the PTE into an entry in the temporary page table
|
|
mov %eax, (%edi, %ecx, 4)
|
|
|
|
# Load the address of the identity map and translate it to a physical address
|
|
mov $_tempIdentityMap, %edi
|
|
sub $BASE_DIFF, %edi
|
|
|
|
# Save the PTE into an entry in the identity map
|
|
mov %eax, (%edi, %ecx, 4)
|
|
|
|
# Increment count and loop
|
|
inc %ecx
|
|
mov $IMAGE_SIZE, %edx
|
|
add $256, %edx
|
|
cmp %edx, %ecx
|
|
jne 1b
|
|
|
|
# Load the physical address of the identity map, and generate a PDE
|
|
mov $_tempIdentityMap, %eax
|
|
sub $BASE_DIFF, %eax
|
|
or $3, %eax
|
|
|
|
# Load the physical address of the page directory
|
|
mov $_tempPgDir, %edi
|
|
sub $BASE_DIFF, %edi
|
|
|
|
# Save the PDE to the first element in the page directory
|
|
mov %eax, (%edi)
|
|
|
|
# Load the physical address of the temporary page table, and generate a PDE
|
|
mov $_tempPgTable, %eax
|
|
sub $BASE_DIFF, %eax
|
|
or $3, %eax
|
|
|
|
# Save the PDE to the entry corresponding to 0xC0000000
|
|
mov %eax, 4088(%edi)
|
|
|
|
# Set the last entry in the page directory to point to the page directory itself
|
|
mov %edi, %eax
|
|
or $3, %eax
|
|
mov %eax, 4092(%edi)
|
|
|
|
# Load the physical address of the page directory into CR3
|
|
mov $_tempPgDir, %edi
|
|
sub $BASE_DIFF, %edi
|
|
mov %edi, %cr3
|
|
|
|
# Enable paging
|
|
mov %cr0, %eax
|
|
or $0x80010000, %eax
|
|
mov %eax, %cr0
|
|
|
|
# Jump into mapped kernel binary
|
|
lea 2f, %eax
|
|
jmp *%eax
|
|
2:
|
|
# Delete PDE corresponding to identity map. We shouldn't need it anymore.
|
|
movl $0, (_tempIdentityMap)
|
|
|
|
# Reload page tables
|
|
mov %cr3, %eax
|
|
mov %eax, %cr3
|
|
|
|
# Initialize stack
|
|
mov $stackTop, %esp
|
|
lgdt gdt_info
|
|
|
|
jmp $8, $.ldcs
|
|
.ldcs:
|
|
mov $16, %ax
|
|
mov %ax, %ds
|
|
mov %ax, %es
|
|
mov %ax, %gs
|
|
mov %ax, %fs
|
|
mov %ax, %ss
|
|
|
|
mov $_bootCmdLine, %eax
|
|
push %eax
|
|
|
|
# Call main function
|
|
call main
|
|
|
|
_err:
|
|
cli
|
|
3: hlt
|
|
jmp 3b
|
|
|
|
.size _start, . - _start
|