diff --git a/bootx64.asm b/bootx64.asm deleted file mode 100644 index c75ee42..0000000 --- a/bootx64.asm +++ /dev/null @@ -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 - diff --git a/build.sh b/build.sh index 71ae609..bc3c2be 100755 --- a/build.sh +++ b/build.sh @@ -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 diff --git a/kernel/boot/bootx64.asm b/kernel/boot/bootx64.asm new file mode 100644 index 0000000..1b157df --- /dev/null +++ b/kernel/boot/bootx64.asm @@ -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 diff --git a/kernel/boot/uefi.inc b/kernel/boot/uefi.inc new file mode 100644 index 0000000..a000d4d --- /dev/null +++ b/kernel/boot/uefi.inc @@ -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 diff --git a/kernel/boot/uefi64.inc b/kernel/boot/uefi64.inc new file mode 100644 index 0000000..235e093 --- /dev/null +++ b/kernel/boot/uefi64.inc @@ -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 diff --git a/kernel/const.inc b/kernel/const.inc new file mode 100644 index 0000000..de0259d --- /dev/null +++ b/kernel/const.inc @@ -0,0 +1,10 @@ +struct DQ + union + lo dd ? + hi_be dd ? ; big endian + ends + union + hi dd ? + lo_be dd ? + ends +ends \ No newline at end of file diff --git a/kernel/proc64.inc b/kernel/proc64.inc new file mode 100644 index 0000000..e10353e --- /dev/null +++ b/kernel/proc64.inc @@ -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 + 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 + 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, \{ 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, \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} + macro finish@proc + \{ localbytes = current + match close:reglist, close@proc: \\{ 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 diff --git a/kernel/struct.inc b/kernel/struct.inc new file mode 100644 index 0000000..97f705c --- /dev/null +++ b/kernel/struct.inc @@ -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, + fields@struct equ fields@struct,field@struct \} + struc dw [val] \{ \common define field@struct .,dw, + fields@struct equ fields@struct,field@struct \} + struc du [val] \{ \common define field@struct .,du, + fields@struct equ fields@struct,field@struct \} + struc dd [val] \{ \common define field@struct .,dd, + fields@struct equ fields@struct,field@struct \} + struc dp [val] \{ \common define field@struct .,dp, + fields@struct equ fields@struct,field@struct \} + struc dq [val] \{ \common define field@struct .,dq, + fields@struct equ fields@struct,field@struct \} + struc dt [val] \{ \common define field@struct .,dt, + 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, + fields@struct equ fields@struct,field@struct \} + macro dw [val] \{ \common \local anonymous + define field@struct anonymous,dw, + fields@struct equ fields@struct,field@struct \} + macro du [val] \{ \common \local anonymous + define field@struct anonymous,du, + fields@struct equ fields@struct,field@struct \} + macro dd [val] \{ \common \local anonymous + define field@struct anonymous,dd, + fields@struct equ fields@struct,field@struct \} + macro dp [val] \{ \common \local anonymous + define field@struct anonymous,dp, + fields@struct equ fields@struct,field@struct \} + macro dq [val] \{ \common \local anonymous + define field@struct anonymous,dq, + fields@struct equ fields@struct,field@struct \} + macro dt [val] \{ \common \local anonymous + define field@struct anonymous,dt, + 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, \} + 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 + common + sizeof.#name = $ + restruc name + match values, list \{ + struc name value \\{ \\local \\..base + match any, fields@struct \\\{ fields@struct equ fields@struct,.,name, \\\} + 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, \\\} + 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, \\} + \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 \} }