rework project structure, base on uefi4kos

This commit is contained in:
rgimad
2025-01-19 17:24:20 +03:00
parent 28d8d0bcfb
commit 654cdefb7f
8 changed files with 1309 additions and 154 deletions

View File

@@ -1,150 +0,0 @@
format pe64 dll efi
entry main
section '.text' code executable readable
;for 32/64 portability and automatic natural align in structure definitions
struc int8 {
. db ?
}
struc int16 {
align 2
. dw ?
}
struc int32 {
align 4
. dd ?
}
struc int64 {
align 8
. dq ?
}
struc intn {
align 8
. dq ?
}
struc dptr {
align 8
. dq ?
}
;symbols
EFIERR = 0x8000000000000000
EFI_SUCCESS = 0
EFI_LOAD_ERROR = EFIERR or 1
EFI_INVALID_PARAMETER = EFIERR or 2
EFI_UNSUPPORTED = EFIERR or 3
EFI_BAD_BUFFER_SIZE = EFIERR or 4
EFI_BUFFER_TOO_SMALL = EFIERR or 5
EFI_NOT_READY = EFIERR or 6
EFI_DEVICE_ERROR = EFIERR or 7
EFI_WRITE_PROTECTED = EFIERR or 8
EFI_OUT_OF_RESOURCES = EFIERR or 9
EFI_VOLUME_CORRUPTED = EFIERR or 10
EFI_VOLUME_FULL = EFIERR or 11
EFI_NO_MEDIA = EFIERR or 12
EFI_MEDIA_CHANGED = EFIERR or 13
EFI_NOT_FOUND = EFIERR or 14
EFI_ACCESS_DENIED = EFIERR or 15
EFI_NO_RESPONSE = EFIERR or 16
EFI_NO_MAPPING = EFIERR or 17
EFI_TIMEOUT = EFIERR or 18
EFI_NOT_STARTED = EFIERR or 19
EFI_ALREADY_STARTED = EFIERR or 20
EFI_ABORTED = EFIERR or 21
EFI_ICMP_ERROR = EFIERR or 22
EFI_TFTP_ERROR = EFIERR or 23
EFI_PROTOCOL_ERROR = EFIERR or 24
;helper macro for definition of relative structure member offsets
macro struct name
{
virtual at 0
name name
end virtual
}
;structures
struc EFI_TABLE_HEADER {
.Signature int64
.Revision int32
.HeaderSize int32
.CRC32 int32
.Reserved int32
}
struct EFI_TABLE_HEADER
struc EFI_SYSTEM_TABLE {
.Hdr EFI_TABLE_HEADER
.FirmwareVendor dptr
.FirmwareRevision int32
.ConsoleInHandle dptr
.ConIn dptr
.ConsoleOutHandle dptr
.ConOut dptr
.StandardErrorHandle dptr
.StdErr dptr
.RuntimeServices dptr
.BootServices dptr
.NumberOfTableEntries intn
.ConfigurationTable dptr
}
struct EFI_SYSTEM_TABLE
struc SIMPLE_TEXT_OUTPUT_INTERFACE {
.Reset dptr
.OutputString dptr
.TestString dptr
.QueryMode dptr
.SetMode dptr
.SetAttribute dptr
.ClearScreen dptr
.SetCursorPosition dptr
.EnableCursor dptr
.Mode dptr
}
struct SIMPLE_TEXT_OUTPUT_INTERFACE
main:
sub rsp, 4*8 ; reserve space for 4 arguments
mov [Handle], rcx ; ImageHandle
mov [SystemTable], rdx ; pointer to SystemTable
lea rdx, [_hello]
mov rcx, [SystemTable]
mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
push rcx rdx
call [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.ClearScreen] ;; TODO : what calling convention? clobbers rcx, what else?
; TODO: use more modern UEFI.inc like stuff
; TODO: update scripts build run. maybe makefile, also generating iso?
; TODO: what is NvVars who generates it why it need
; TODO: print some info provided by eufi like versions etc..
; TODO: print memory map
; TODO: how to load kernel . See https://github.com/BrianOtto/nasm-uefi
pop rdx rcx
call [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.OutputString]
jmp $
add rsp, 4*8
mov eax, EFI_SUCCESS
retn
section '.data' data readable writeable
Handle dq ?
SystemTable dq ?
_hello du 'Hello World',13,10,0
section '.reloc' fixups data discardable

View File

@@ -1,4 +1,7 @@
fasm bootx64.asm
mkdir -p image/EFI/BOOT
cp bootx64.efi image/EFI/BOOT
qemu-system-x86_64 -cpu qemu64 -bios OVMF.fd -drive driver=vvfat,rw=on,dir=image/
if fasm kernel/boot/bootx64.asm; then
mkdir -p image/EFI/BOOT
cp kernel/boot/bootx64.efi image/EFI/BOOT
qemu-system-x86_64 -cpu qemu64 -bios OVMF.fd -drive driver=vvfat,rw=on,dir=image/
else
echo "build failed"
fi

47
kernel/boot/bootx64.asm Normal file
View File

@@ -0,0 +1,47 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2025-2025. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format pe64 efi
entry main
section '.text' code executable readable
include '../struct.inc'
; include '../macros.inc'
; include '../kglobals.inc'
fastcall fix fstcall
include '../proc64.inc'
include '../const.inc'
purge DQ ; because of some struct DQ in const.inc
include 'uefi64.inc'
proc main _efi_handle, _efi_table
mov [efi_handle], rcx
mov [efi_table], rdx
mov rbx, rdx
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset], rcx, 1
test eax, eax
jnz $ ; what can I do here?
mov rcx, [rbx+EFI_SYSTEM_TABLE.ConOut]
fstcall [rcx+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString], rcx, msg_hello_k64_loader
jmp $
endp
section '.data' data readable writeable
efi_handle dq 0
efi_table dq 0
section '.rodata' data readable
msg_hello_k64_loader du "Hello from Kolibri64 efi loader",13,10,0
section '.reloc' fixups data discardable

323
kernel/boot/uefi.inc Normal file
View File

@@ -0,0 +1,323 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2020-2021. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Version 2, or (at your option) any later version. ;;
;; ;;
;; Written by Ivan Baravy ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Based on UEFI library for fasm by bzt, Public Domain. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EFI_LOCATE_SEARCH_TYPE:
.AllHandles = 0
.ByRegisterNotify = 1
.ByProtocol = 2
; EFI_MEMORY_TYPE
EFI_RESERVED_MEMORY_TYPE = 0
EFI_LOADER_CODE = 1
EFI_LOADER_DATA = 2
EFI_BOOT_SERVICES_CODE = 3
EFI_BOOT_SERVICES_DATA = 4
EFI_RUNTIME_SERVICES_CODE = 5
EFI_RUNTIME_SERVICES_DATA = 6
EFI_CONVENTIONAL_MEMORY = 7
EFI_UNUSABLE_MEMORY = 8
EFI_ACPI_RECLAIM_MEMORY = 9
EFI_ACPI_MEMORY_NVS = 10
EFI_MEMORY_MAPPED_IO = 11
EFI_MEMORY_MAPPED_IO_PORT_SPACE = 12
EFI_PAL_CODE = 13
EFI_PERSISTENT_MEMORY = 14
EFI_MAX_MEMORY_TYPE = 15
; EFI_ALLOCATE_TYPE
EFI_ALLOCATE_ANY_PAGES = 0
EFI_ALLOCATE_MAX_ADDRESS = 1
EFI_ALLOCATE_ADDRESS = 2
EFI_MEMORY_UC = 0x00000001
EFI_MEMORY_WC = 0x00000002
EFI_MEMORY_WT = 0x00000004
EFI_MEMORY_WB = 0x00000008
EFI_MEMORY_UCE = 0x00000010
EFI_MEMORY_WP = 0x00001000
EFI_MEMORY_RP = 0x00002000
EFI_MEMORY_XP = 0x00004000
EFI_MEMORY_NV = 0x00008000
EFI_MEMORY_MORE_RELIABLE = 0x00010000
EFI_MEMORY_RO = 0x00020000
EFI_SUCCESS = 0
EFI_LOAD_ERROR = EFIERR or 1
EFI_INVALID_PARAMETER = EFIERR or 2
EFI_UNSUPPORTED = EFIERR or 3
EFI_BAD_BUFFER_SIZE = EFIERR or 4
EFI_BUFFER_TOO_SMALL = EFIERR or 5
EFI_NOT_READY = EFIERR or 6
EFI_DEVICE_ERROR = EFIERR or 7
EFI_WRITE_PROTECTED = EFIERR or 8
EFI_OUT_OF_RESOURCES = EFIERR or 9
EFI_VOLUME_CORRUPTED = EFIERR or 10
EFI_VOLUME_FULL = EFIERR or 11
EFI_NO_MEDIA = EFIERR or 12
EFI_MEDIA_CHANGED = EFIERR or 13
EFI_NOT_FOUND = EFIERR or 14
EFI_ACCESS_DENIED = EFIERR or 15
EFI_NO_RESPONSE = EFIERR or 16
EFI_NO_MAPPING = EFIERR or 17
EFI_TIMEOUT = EFIERR or 18
EFI_NOT_STARTED = EFIERR or 19
EFI_ALREADY_STARTED = EFIERR or 20
EFI_ABORTED = EFIERR or 21
EFI_ICMP_ERROR = EFIERR or 22
EFI_TFTP_ERROR = EFIERR or 23
EFI_PROTOCOL_ERROR = EFIERR or 24
EFI_FILE_SYSTEM_INFO_ID equ 0x93,0x6e,0x57,0x09,0x3f,0x6d,0xd2,0x11, \
0x39,0x8e,0x00,0xa0,0xc9,0x69,0x72,0x3b
EFI_SYSTEM_TABLE_SIGNATURE equ 0x49,0x42,0x49,0x20,0x53,0x59,0x53,0x54
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID equ 0x22,0x5b,0x4e,0x96, \
0x59,0x64,0xd2,0x11, \
0x8e,0x39,0x00,0xa0, \
0xc9,0x69,0x72,0x3b
EFI_LOADED_IMAGE_PROTOCOL_GUID equ 0xA1,0x31,0x1b,0x5b,0x62,0x95,0xd2,0x11, \
0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B
EFI_BLOCK_IO_PROTOCOL_GUID equ 0x21,0x5b,0x4e,0x96,0x59,0x64,0xd2,0x11, \
0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b
EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID equ 0xde,0xa9,0x42,0x90,0xdc,0x23,0x38,0x4a, \
0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID equ 0xBB, 0x7E, 0x70, 0x2F, \
0x1A, 0x4A, 0xd4, 0x11, \
0x9A, 0x38, 0x00, 0x90, \
0x27, 0x3F, 0xC1, 0x4D
EFI_FILE_MODE_READ = 1
EFI_FILE_MODE_WRITE = 2
EFI_FILE_MODE_CREATE = 0x8000000000000000
struct EFI_MEMORY_DESCRIPTOR
Type dd ?
dd ? ; align
PhysicalStart DQ ?
VirtualStart DQ ?
NumberOfPages DQ ?
Attribute DQ ?
ends
struct EFI_FILE_SYSTEM_INFO
Size DQ ?
ReadOnly db ?
rb 7
VolumeSize DQ ?
FreeSpace DQ ?
BlockSize dd ?
VolumeLabel rw 32
ends
struct EFI_TABLE_HEADER
Signature DQ ?
Revision dd ?
HeaderSize dd ?
CRC32 dd ?
Reserved dd ?
ends
struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
Reset DN ?
OutputString DN ?
TestString DN ?
QueryMode DN ?
SetMode DN ?
SetAttribute DN ?
ClearScreen DN ?
SetCursorPosition DN ?
EnableCursor DN ?
Mode DN ?
ends
struct SIMPLE_INPUT_INTERFACE
Reset DN ?
ReadKeyStroke DN ?
WaitForKey DN ?
ends
struct EFI_BOOT_SERVICES
Hdr EFI_TABLE_HEADER
RaisePriority DN ?
RestorePriority DN ?
AllocatePages DN ?
FreePages DN ?
GetMemoryMap DN ?
AllocatePool DN ?
FreePool DN ?
CreateEvent DN ?
SetTimer DN ?
WaitForEvent DN ?
SignalEvent DN ?
CloseEvent DN ?
CheckEvent DN ?
InstallProtocolInterface DN ?
ReInstallProtocolInterface DN ?
UnInstallProtocolInterface DN ?
HandleProtocol DN ?
Reserved DN ?
RegisterProtocolNotify DN ?
LocateHandle DN ?
LocateDevicePath DN ?
InstallConfigurationTable DN ?
ImageLoad DN ?
ImageStart DN ?
Exit DN ?
ImageUnLoad DN ?
ExitBootServices DN ?
GetNextMonotonicCount DN ?
Stall DN ?
SetWatchdogTimer DN ?
ConnectController DN ?
DisConnectController DN ?
OpenProtocol DN ?
CloseProtocol DN ?
OpenProtocolInformation DN ?
ProtocolsPerHandle DN ?
LocateHandleBuffer DN ?
LocateProtocol DN ?
InstallMultipleProtocolInterfaces DN ?
UnInstallMultipleProtocolInterfaces DN ?
CalculateCrc32 DN ?
CopyMem DN ?
SetMem DN ?
ends
struct EFI_RUNTIME_SERVICES
Hdr EFI_TABLE_HEADER
GetTime DN ?
SetTime DN ?
GetWakeUpTime DN ?
SetWakeUpTime DN ?
SetVirtualAddressMap DN ?
ConvertPointer DN ?
GetVariable DN ?
GetNextVariableName DN ?
SetVariable DN ?
GetNextHighMonoCount DN ?
ResetSystem DN ?
ends
struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
Revision DQ ?
OpenVolume DN ?
ends
struct EFI_FILE_PROTOCOL
Revision DQ ?
Open DN ?
Close DN ?
Delete DN ?
Read DN ?
Write DN ?
GetPosition DN ?
SetPosition DN ?
GetInfo DN ?
SetInfo DN ?
Flush DN ?
OpenEx DN ?
ReadEx DN ?
WriteEx DN ?
FlushEx DN ?
ends
struct EFI_GRAPHICS_OUTPUT_PROTOCOL
QueryMode DN ?
SetMode DN ?
Blt DN ?
Mode DN ?
ends
struct EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
MaxMode dd ?
Mode dd ?
Info DN ?
SizeOfInfo DN ?
FrameBufferBase DQ ?
FrameBufferSize DN ?
ends
EFI_GRAPHICS_PIXEL_FORMAT:
.PixelRedGreenBlueReserved8BitPerColor = 0
.PixelBlueGreenRedReserved8BitPerColor = 1
.PixelBitMask = 2
.PixelBltOnly = 3
.PixelFormatMax = 4
struct EFI_PIXEL_BITMASK
RedMask dd ?
GreenMask dd ?
BlueMask dd ?
ReservedMask dd ?
ends
struct EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
Version dd ?
HorizontalResolution dd ?
VerticalResolution dd ?
PixelFormat dd ?
PixelInformation EFI_PIXEL_BITMASK
PixelsPerScanLine dd ?
ends
struct PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS
Read DN ?
Write DN ?
ends
struct EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
ParentHandle DN ? ; EFI_HANDLE
PollMem DN ?
PollIo DN ?
Mem PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS
Io PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS
Pci PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS
CopyMem DN ?
Map DN ?
Unmap DN ?
AllocateBuffer DN ?
FreeBuffer DN ?
Flush DN ?
GetAttributes DN ?
SetAttributes DN ?
Configuration DN ?
SegmentNumber dd ?
ends
struct EFI_QWORD_ADDRESS_SPACE_DESCRIPTOR ; described in acpi spec
Type db ?
Length dw ?
ResourceType db ?
GeneralFlags db ?
SpecificFlags db ?
Granularity dq ?
RangeMinimum dq ?
RangeMaximum dq ?
TranslationOffset dq ?
AddressLength dq ?
ends
EFI_RESOURCE_DESCRIPTOR_TYPE.QWORD_ADDRESS_SPACE = 0x8a
EFI_RESOURCE_DESCRIPTOR_TYPE.END_TAG = 0x79
EFI_RESOURCE_TYPE.MEMORY = 0
EFI_RESOURCE_TYPE.IO = 1
EFI_RESOURCE_TYPE.BUS = 2

58
kernel/boot/uefi64.inc Normal file
View File

@@ -0,0 +1,58 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2020-2021. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Version 2, or (at your option) any later version. ;;
;; ;;
;; Written by Ivan Baravy ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Based on UEFI library for fasm by bzt, Public Domain. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DN fix dq ; native
include "uefi.inc"
EFIERR = 0x8000000000000000
struct EFI_SYSTEM_TABLE
Hdr EFI_TABLE_HEADER
FirmwareVendor DN ?
FirmwareRevision dd ?
dd ?
ConsoleInHandle DN ?
ConIn DN ?
ConsoleOutHandle DN ?
ConOut DN ?
StandardErrorHandle DN ?
StdErr DN ?
RuntimeServices DN ?
BootServices DN ?
NumberOfTableEntries DN ?
ConfigurationTable DN ?
ends
struct EFI_CONFIGURATION_TABLE
VendorGUID rd 4
VendorTable DN ?
ends
struct EFI_LOADED_IMAGE_PROTOCOL
Revision dd ?
dd ?
ParentHandle DN ?
SystemTable DN ?
DeviceHandle DN ?
FilePath DN ?
Reserved DN ?
LoadOptionsSize dd ?
dd ?
ImageBase DN ?
ImageSize dq ?
ImageCodeType dd ?
ImageDataType dd ?
UnLoad DN ?
ends

10
kernel/const.inc Normal file
View File

@@ -0,0 +1,10 @@
struct DQ
union
lo dd ?
hi_be dd ? ; big endian
ends
union
hi dd ?
lo_be dd ?
ends
ends

618
kernel/proc64.inc Normal file
View File

@@ -0,0 +1,618 @@
; Macroinstructions for defining and calling procedures (x64 version)
macro invoke proc,[arg]
{ common fastcall [proc],arg }
macro fastcall proc,[arg]
{ common local stackspace,argscount,counter
if argscount < 4
stackspace = 4*8
else if argscount and 1
stackspace = (argscount+1)*8
else
stackspace = argscount*8
end if
counter = 0
if stackspace
if defined current@frame
if current@frame<stackspace
current@frame = stackspace
end if
else
if stackspace
sub rsp, stackspace
end if
end if
end if
forward
counter = counter + 1
define type@param
define definition@param arg
match =float value,definition@param
\{ define definition@param value
define type@param float \}
match =addr value,definition@param
\{ define definition@param value
define type@param addr \}
match any=,any,definition@param
\{ \local ..string,..continue
jmp ..continue
align sizeof.TCHAR
..string TCHAR definition@param,0
..continue:
define definition@param ..string
define type@param addr \}
match any,definition@param
\{ match \`any,any
\\{ \\local ..string,..continue
jmp ..continue
align sizeof.TCHAR
..string TCHAR definition@param,0
..continue:
define definition@param ..string
define type@param addr \\} \}
match param,definition@param
\{ local opcode,origin
size@param = 0
if param eqtype 0 | param eqtype 0f | type@param eq addr
size@param = 8
else if param eqtype byte 0 | param eqtype byte 0f
match prefix value,definition@param
\\{ if prefix eq qword
size@param = 8
else if prefix eq dword
size@param = 4
else if prefix eq word
size@param = 2
else if prefix eq byte
size@param = 1
end if \\}
else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
virtual
origin = $
inc param
load opcode byte from origin
if opcode = 67h | opcode = 41h
load opcode byte from origin+1
end if
if opcode and 0F8h = 48h
size@param = 8
else if opcode = 66h
size@param = 2
else if opcode = 0FFh
size@param = 4
else
size@param = 1
end if
end virtual
end if
if counter = 1
if type@param eq float
if ~ param eq xmm0
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax, param
movd xmm0, eax
else
movd xmm0, param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax, param
movq xmm0, rax
else
movq xmm0, param
end if
end if
end if
if vararg@fastcall & ~ param eq rcx
movq rcx, xmm0
end if
else if type@param eq addr
if ~ param eq rcx
lea rcx, [param]
end if
else if size@param = 8
if ~ param eq rcx
mov rcx, param
end if
else if size@param = 4
if ~ param eq ecx
mov ecx, param
end if
else if size@param = 2
if ~ param eq cx
mov cx, param
end if
else if size@param = 1
if ~ param eq cl
mov cl, param
end if
end if
else if counter = 2
if type@param eq float
if ~ param eq xmm1
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax, param
movd xmm1, eax
else
movd xmm1, param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax, param
movq xmm1, rax
else
movq xmm1, param
end if
end if
end if
if vararg@fastcall & ~ param eq rdx
movq rdx, xmm1
end if
else if type@param eq addr
if ~ param eq rdx
lea rdx, [param]
end if
else if size@param = 8
if ~ param eq rdx
mov rdx, param
end if
else if size@param = 4
if ~ param eq edx
mov edx, param
end if
else if size@param = 2
if ~ param eq dx
mov dx, param
end if
else if size@param = 1
if ~ param eq dl
mov dl, param
end if
end if
else if counter = 3
if type@param eq float
if ~ param eq xmm2
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax, param
movd xmm2, eax
else
movd xmm2, param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax, param
movq xmm2, rax
else
movq xmm2, param
end if
end if
end if
if vararg@fastcall & ~ param eq r8
movq r8, xmm2
end if
else if type@param eq addr
if ~ param eq r8
lea r8, [param]
end if
else if size@param = 8
if ~ param eq r8
mov r8, param
end if
else if size@param = 4
if ~ param eq r8d
mov r8d, param
end if
else if size@param = 2
if ~ param eq r8w
mov r8w, param
end if
else if size@param = 1
if ~ param eq r8b
mov r8b, param
end if
end if
else if counter = 4
if type@param eq float
if ~ param eq xmm3
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax, param
movd xmm3, eax
else
movd xmm3, param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax, param
movq xmm3, rax
else
movq xmm3, param
end if
end if
end if
if vararg@fastcall & ~ param eq r9
movq r9, xmm3
end if
else if type@param eq addr
if ~ param eq r9
lea r9, [param]
end if
else if size@param = 8
if ~ param eq r9
mov r9, param
end if
else if size@param = 4
if ~ param eq r9d
mov r9d, param
end if
else if size@param = 2
if ~ param eq r9w
mov r9w, param
end if
else if size@param = 1
if ~ param eq r9b
mov r9b, param
end if
end if
else
if type@param eq addr
lea rax, [param]
mov [rsp+(counter-1)*8], rax
else if param eqtype [0] | param eqtype byte [0]
if size@param = 8
mov rax, param
mov [rsp+(counter-1)*8], rax
else if size@param = 4
mov eax, param
mov [rsp+(counter-1)*8], eax
else if size@param = 2
mov ax, param
mov [rsp+(counter-1)*8], ax
else
mov al, param
mov [rsp+(counter-1)*8], al
end if
else if size@param = 8
virtual
origin = $
mov rax, param
load opcode byte from origin+1
end virtual
if opcode = 0B8h
mov rax, param
mov [rsp+(counter-1)*8], rax
else
mov qword [rsp+(counter-1)*8], param
end if
else if param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
movq [rsp+(counter-1)*8], param
else
mov [rsp+(counter-1)*8], param
end if
end if \}
common
argscount = counter
call proc
if stackspace & ~defined current@frame
add rsp, stackspace
end if }
macro proc [args]
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ local loc,fill,counter
loc = (localbytes+15) and (not 15)
parmbase@proc equ rbp+16
localbase@proc equ rbp-loc
push rbp
mov rbp, rsp
if loc+fill
sub rsp, loc+fill
end if
counter = 0
irps reg, reglist \{ push reg
counter = counter+1 \}
fill = 8*(counter and 1) }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
leave
retn }
close@proc equ
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 10000b \}
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
virtual at parmbase@proc
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $-(parmbase@proc)
end virtual
name # % = parmbytes/8
all@vars equ
current = 0
macro locals
\{ virtual at localbase@proc+current
macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
current = $-(localbase@proc)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc
\{ localbytes = current
match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if qqword eq type
dq ?,?,?,?
else if dqword eq type
dq ?,?
else if tbyte eq type
dq ?,?
else
dq ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dq ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val] { name def val }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =?, val \{ ..tmp equ \}
match any (=?), val \{ ..tmp equ \}
match =label, def \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
struc label type { label . type }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else if size@initlocal - position@initlocal < 8
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
else
load qword@initlocal qword from name+position@initlocal
if ( qword@initlocal > 0 & qword@initlocal < 80000000h ) | ( qword@initlocal < 0 & qword@initlocal >= -80000000h )
current@initlocal = 8
else
current@initlocal = 4
dword@initlocal = qword@initlocal and 0FFFFFFFFh
end if
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal], byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal], word@initlocal
else if current@initlocal = 4
mov dword [name+position@initlocal], dword@initlocal
else
mov qword [name+position@initlocal], qword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count*2
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
rq count*4
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
rq count*2
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
rq count*4
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
dq ?,?,?,?
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
dq ?,?
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
dq ?,?,?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
macro frame
{ local size,current
if size
sub rsp, size
end if
current = 0
current@frame equ current
size@frame equ size }
macro endf
{ size@frame = current@frame
if size@frame
add rsp, size@frame
end if
restore size@frame,current@frame }
macro static_rsp_prologue procname,flag,parmbytes,localbytes,reglist
{ local counter,loc,frame,current
counter = 0
irps reg, reglist \{ push reg
counter = counter+1 \}
loc = (localbytes+7) and (not 7)
if frame & (counter+loc shr 3+1) and 1
loc = loc + 8
end if
framebytes@proc equ frame+loc
if framebytes@proc
sub rsp, framebytes@proc
end if
localbase@proc equ rsp+frame
regsbase@proc equ rsp+frame+loc
parmbase@proc equ rsp+frame+loc+counter*8+8
current = 0
current@frame equ current
size@frame equ frame }
macro static_rsp_epilogue procname,flag,parmbytes,localbytes,reglist
{ if framebytes@proc
add rsp, framebytes@proc
end if
irps reg, reglist \{ reverse pop reg \}
retn }
macro static_rsp_close procname,flag,parmbytes,localbytes,reglist
{ size@frame = current@frame
restore size@frame,current@frame }
stdcall fix fastcall
macro cinvoke proc,[arg]
{ common ccall [proc],arg }
macro ccall proc,[arg]
{ common vararg@fastcall = 1
fastcall proc,arg
vararg@fastcall = 0 }
vararg@fastcall = 0

246
kernel/struct.inc Normal file
View File

@@ -0,0 +1,246 @@
; Macroinstructions for defining data structures
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
; @dont_give_a_doxygen
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
; @dont_give_a_doxygen
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
; @dont_give_a_doxygen
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
; @dont_give_a_doxygen
enable@substruct
; @dont_give_a_doxygen
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
; @dont_give_a_doxygen
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }