├── .dir-locals.el ├── .gitignore ├── Docker └── Dockerfile ├── Makedefs ├── Makefile ├── NOTES ├── README.md ├── TODO ├── Tests ├── ACPIReadWriteTests.swift ├── ACPITests.swift ├── AddressTests.swift ├── Info.plist ├── KlibTests.swift ├── MemoryRangeTests.swift ├── PCITests.swift ├── PageSizeTests.swift ├── PhysPageRangeTests.swift ├── StringTests.swift ├── TestUtils.swift ├── USBTests.swift ├── test.h └── test_files │ ├── DSDT.asl │ ├── macbook31 │ ├── macbook31-APIC.aml │ ├── macbook31-APIC.dsl │ ├── macbook31-ASF!.aml │ ├── macbook31-ASF!.dsl │ ├── macbook31-DSDT.aml │ ├── macbook31-DSDT.dsl │ ├── macbook31-ECDT.aml │ ├── macbook31-ECDT.dsl │ ├── macbook31-FACP.aml │ ├── macbook31-FACP.dsl │ ├── macbook31-FACS1.aml │ ├── macbook31-FACS1.dsl │ ├── macbook31-FACS2.aml │ ├── macbook31-FACS2.dsl │ ├── macbook31-HPET.aml │ ├── macbook31-HPET.dsl │ ├── macbook31-MCFG.aml │ ├── macbook31-MCFG.dsl │ ├── macbook31-SBST.aml │ ├── macbook31-SBST.dsl │ ├── macbook31-SSDT1.aml │ ├── macbook31-SSDT1.dsl │ ├── macbook31-SSDT2.aml │ ├── macbook31-SSDT2.dsl │ ├── macbook31-SSDT3.aml │ ├── macbook31-SSDT3.dsl │ ├── macbook31-SSDT4.aml │ ├── macbook31-SSDT4.dsl │ ├── macbook31-SSDT5.aml │ ├── macbook31-SSDT5.dsl │ ├── macbook31-SSDT6.aml │ ├── macbook31-SSDT6.dsl │ ├── macbook31-SSDT7.aml │ ├── macbook31-SSDT7.dsl │ ├── macbook31-SSDT8.aml │ └── macbook31-SSDT8.dsl │ ├── qemu │ ├── QEMU-DSDT.aml │ └── QEMU-DSDT.dsl │ ├── vmware │ ├── vmware-APIC.aml │ ├── vmware-APIC.dsl │ ├── vmware-BOOT.aml │ ├── vmware-BOOT.dsl │ ├── vmware-DSDT.aml │ ├── vmware-DSDT.dsl │ ├── vmware-FACP.aml │ ├── vmware-FACP.dsl │ ├── vmware-FACS1.aml │ ├── vmware-FACS1.dsl │ ├── vmware-FACS2.aml │ ├── vmware-FACS2.dsl │ ├── vmware-HPET.aml │ ├── vmware-HPET.dsl │ ├── vmware-MCFG.aml │ ├── vmware-MCFG.dsl │ ├── vmware-SRAT.aml │ ├── vmware-SRAT.dsl │ ├── vmware-WAET.aml │ └── vmware-WAET.dsl │ └── vmware11 │ ├── vmware11-apic.aml │ ├── vmware11-apic.dsl │ ├── vmware11-dmar.aml │ ├── vmware11-dmar.dsl │ ├── vmware11-dsdt.aml │ ├── vmware11-dsdt.dsl │ ├── vmware11-facp.aml │ ├── vmware11-facp.dsl │ ├── vmware11-facs.aml │ ├── vmware11-facs.dsl │ ├── vmware11-hpet.aml │ ├── vmware11-hpet.dsl │ ├── vmware11-mcfg.aml │ ├── vmware11-mcfg.dsl │ ├── vmware11-srat.aml │ ├── vmware11-srat.dsl │ ├── vmware11-waet.aml │ ├── vmware11-waet.dsl │ ├── vmware11-wsmt.aml │ └── vmware11-wsmt.dsl ├── bochsrc ├── boot ├── Makefile ├── a20.asm ├── boot16to64.asm ├── bootsector.asm ├── cpu_check.asm ├── efi │ ├── efi-test.c │ └── efi.mk ├── efi_elf.c ├── efi_entry.asm ├── efi_header.asm ├── efi_linker.script ├── efi_main.c ├── isohdr.asm ├── memory.asm ├── page_tables.asm ├── pmode_loader.asm └── utils.asm ├── debugtools ├── SwiftString.py └── dump_swift_string.py ├── doc ├── boot-readme.md ├── development.md ├── index.md ├── initialisation.md ├── kstdlib.md ├── other-notes.md ├── outline.md ├── screenshot-2.png ├── screenshot.png ├── swift-issues.md ├── swift-kernel-layers.001.png ├── swift-kernel-layers.key ├── symbols.txt ├── target-host.md ├── useful-links.md └── working-with-c.md ├── gdb-cmds ├── gdb-cmds-bochs ├── include ├── acpi.h ├── efi.h ├── efi │ ├── api.h │ ├── console.h │ ├── gop.h │ └── uga.h ├── fbcon.h ├── io.h ├── kernel.h ├── klibc.h ├── macros.asm ├── mm.h ├── swift.h ├── usb.h ├── vmx.h ├── x86defs.h └── x86funcs.h ├── kernel ├── Makefile ├── devices │ ├── ISABus.swift │ ├── PNPDevice.swift │ ├── Timer.swift │ ├── acpi │ │ ├── ACPIGenericAddressStructure.swift │ │ ├── TODO │ │ ├── acpi.swift │ │ ├── acpiglobalobjects.swift │ │ ├── amlmethod.swift │ │ ├── amlnamedobject.swift │ │ ├── amlnamespacemodifier.swift │ │ ├── amlparser.swift │ │ ├── amlresourcedata.swift │ │ ├── amltype1opcodes.swift │ │ ├── amltype2opcodes.swift │ │ ├── amltypes.swift │ │ ├── amlutils.swift │ │ ├── boot.swift │ │ ├── ecdt.swift │ │ ├── facp.swift │ │ ├── facs.swift │ │ ├── hpet.swift │ │ ├── madt.swift │ │ ├── mcfg.swift │ │ ├── sbst.swift │ │ ├── srat.swift │ │ └── waet.swift │ ├── apic.swift │ ├── bus.swift │ ├── cmos.swift │ ├── cpu.swift │ ├── device.swift │ ├── devicemanager.swift │ ├── driver.swift │ ├── ioapic.swift │ ├── kbd8042.swift │ ├── mtrr.swift │ ├── pci │ │ ├── PCICapability.swift │ │ ├── PCIDeviceFunction.swift │ │ ├── PCIInterruptLinkDevice.swift │ │ ├── PCIRoutingTable.swift │ │ ├── pcibus.swift │ │ ├── pciconfigspace.swift │ │ ├── pcidevice.swift │ │ └── pcideviceclass.swift │ ├── pic8259.swift │ ├── pit8254.swift │ ├── ps2keyboard.swift │ ├── qemufwcf.swift │ ├── timer.asm │ ├── tty.swift │ └── usb │ │ ├── hcd-ehci.swift │ │ ├── hcd-xhci.swift │ │ ├── uhci-buffers.swift │ │ ├── uhci-hcd.swift │ │ ├── uhci-pipe.swift │ │ ├── uhci-queuehead.swift │ │ ├── uhci-registers.swift │ │ ├── uhci-transferdescriptor.swift │ │ ├── usb-configdescriptor.swift │ │ ├── usb-controlrequest.swift │ │ ├── usb-device.swift │ │ ├── usb-devicedescriptor.swift │ │ ├── usb-devicequalifier.swift │ │ ├── usb-endpointdescriptor.swift │ │ ├── usb-hid.swift │ │ ├── usb-hiddescriptor.swift │ │ ├── usb-hub.swift │ │ ├── usb-interfacedescriptor.swift │ │ └── usb.swift ├── init │ ├── GDT.swift │ ├── biosboot.swift │ ├── bootparams.swift │ ├── bss.c │ ├── efiboot.swift │ ├── main.asm │ ├── smbios.swift │ └── startup.swift ├── klib │ ├── BitmapAllocator.swift │ ├── CircularBuffer.swift │ ├── Extensions.swift │ ├── MemoryBufferReader.swift │ ├── ReservationManager.swift │ ├── extensions │ │ ├── bitarray.swift │ │ ├── bytearray.swift │ │ ├── dwordarray.swift │ │ └── integer.swift │ └── printf.swift ├── mm │ ├── MMIORegion.swift │ ├── MemoryRegion.swift │ ├── PageDirectory.swift │ ├── PageDirectoryPointerTable.swift │ ├── PageMapLevel4Table.swift │ ├── PageSize.swift │ ├── PageTable.swift │ ├── PhysPageAlignedRegion.swift │ ├── PhysRegion.swift │ ├── address.swift │ ├── alloc.swift │ ├── init.swift │ ├── mapping.swift │ ├── page.swift │ └── symbols.swift ├── tasks │ ├── shell.swift │ ├── tasks.swift │ └── tests.swift ├── traps │ ├── IDT.swift │ ├── IRQSetting.swift │ ├── entry.asm │ ├── exceptions.swift │ └── interrupt.swift └── vm │ ├── vmcs.swift │ ├── vmentry.asm │ └── vmx.swift ├── klibc ├── Makefile ├── README.md ├── early_tty.c ├── io.c ├── koops.c ├── kprintf.c ├── libcpp.c ├── malloc.c ├── misc.c ├── printf.c ├── pthread.c ├── std_cxx11_string.c ├── string.c ├── x86_misc.asm └── x86_string.asm ├── lib └── font_8x16.c ├── linker.script ├── lldb-cmds ├── ovmf.bios ├── project1.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── kernel.xcscheme ├── run_qemu.sh └── utils ├── .gitignore ├── Makefile ├── Package.swift ├── Sources ├── PatchUtils │ └── PatchUtils.swift ├── efi_patch │ └── main.swift ├── foverride │ └── main.swift └── mkdiskimg │ └── main.swift └── linux.h /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((nil 5 | (eval let* 6 | ((x (dir-locals-find-file default-directory)) 7 | (this-directory (if (listp x) (car x) (file-name-directory x)))) 8 | (unless (featurep 'swift-project-settings) 9 | (add-to-list 'load-path 10 | (concat this-directory "utils") 11 | :append) 12 | (let ((swift-project-directory this-directory)) 13 | (require 'swift-project-settings))) 14 | (set (make-local-variable 'swift-project-directory) 15 | this-directory) 16 | ) 17 | (tab-width . 4) 18 | (fill-column . 80) 19 | (c-file-style . "swift")) 20 | (c++-mode 21 | (whitespace-style face lines indentation:space)) 22 | (c-mode 23 | (whitespace-style face lines indentation:space)) 24 | (objc-mode 25 | (whitespace-style face lines indentation:space)) 26 | (prog-mode 27 | (eval add-hook 'prog-mode-hook 28 | (lambda nil 29 | (whitespace-mode 1)) 30 | (not :APPEND) 31 | :BUFFER-LOCAL)) 32 | (swift-mode 33 | (swift-find-executable-fn . swift-project-executable-find) 34 | (swift-syntax-check-fn . swift-project-swift-syntax-check) 35 | (whitespace-style face lines indentation:space) 36 | (swift-basic-offset . 4) 37 | (tab-always-indent . t))) 38 | 39 | (add-hook 'c++-mode-hook '(lambda () (highlight-lines-matching-regexp ".\\{81\\}" 'hi-pink))) 40 | (add-hook 'c-mode-hook '(lambda () (highlight-lines-matching-regexp ".\\{81\\}" 'hi-pink))) 41 | (add-hook 'swift-mode-hook '(lambda () (highlight-lines-matching-regexp ".\\{81\\}" 'hi-pink))) 42 | 43 | 44 | ;; Local Variables: 45 | ;; eval: (whitespace-mode -1) 46 | ;; End: 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.map 2 | *.o 3 | *.bin 4 | *.dSYM 5 | *.swp 6 | *.orig 7 | *~ 8 | \#* 9 | 10 | modules 11 | output 12 | kernel/init/version.swift 13 | # Mac OS X filesystem metadata 14 | .DS_Store 15 | 16 | # Xcode user artifacts 17 | xcuserdata 18 | project.xcworkspace 19 | 20 | # python generated files 21 | *.pyc 22 | 23 | Build 24 | DerivedData 25 | .build 26 | .configuration 27 | .arcconfig 28 | .fuse* 29 | -------------------------------------------------------------------------------- /Docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Run using: docker build --tag=swift-kstdlib . 2 | FROM swift:5.0.2-bionic 3 | 4 | ARG KSTDLIB_VERSION=20190906 5 | ENV KSTDLIB_VERSION=$KSTDLIB_VERSION 6 | ENV KSTDLIB_URL=https://github.com/spevans/swift-kstdlib/releases/download/v${KSTDLIB_VERSION}/kstdlib-${KSTDLIB_VERSION}.tgz 7 | 8 | RUN echo Building with kstdlib version ${KSTDLIB_VERSION} 9 | RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true && apt-get -q update && \ 10 | apt-get -q install -y \ 11 | nasm \ 12 | xorriso \ 13 | mtools \ 14 | dosfstools \ 15 | make \ 16 | curl \ 17 | && rm -r /var/lib/apt/lists/* 18 | 19 | 20 | RUN echo Linking swift && ln -s / ~/swift 21 | 22 | 23 | # Copy any locals kstdlib tgzs to /tmp 24 | COPY * /tmp/ 25 | 26 | WORKDIR / 27 | 28 | RUN echo Downloading ${KSTDLIB_URL} \ 29 | && curl -fSL ${KSTDLIB_URL} -o /tmp/kstdlib-${KSTDLIB_VERSION}.tgz \ 30 | && apt-get purge -y curl \ 31 | && apt-get -y autoremove 32 | 33 | 34 | # Install any kstdlib.tgzs in /tmp 35 | 36 | RUN for tgz in `ls /tmp/*.tgz`; \ 37 | do echo tgz: $tgz ; \ 38 | if [ -f $tgz ]; \ 39 | then echo Installing $tgz ; \ 40 | tar zxf $tgz --directory ~ ; \ 41 | rm -f $tgz ; \ 42 | fi; \ 43 | done 44 | 45 | 46 | RUN ~/swift/usr/bin/swift --version \ 47 | && ~/swift/usr/bin/clang --version \ 48 | && ~/kstdlib-${KSTDLIB_VERSION}/usr/bin/swift --version \ 49 | && ~/kstdlib-${KSTDLIB_VERSION}/usr/bin/clang --version 50 | -------------------------------------------------------------------------------- /Makedefs: -------------------------------------------------------------------------------- 1 | UNAME_S := $(shell uname -s) 2 | NASM := nasm 3 | NASM_FLAGS := -Werror -p$(TOPDIR)/include/macros.asm 4 | MODULE_DIR := $(TOPDIR)/modules 5 | GITVER := $(shell git rev-parse HEAD) 6 | 7 | # The normal swift compiler 8 | SWIFT := swift 9 | 10 | # The path to the kernel-lib swift compiler 11 | KSWIFTDIR := $(shell echo ~/kstdlib-20190906) 12 | KSWIFT := $(KSWIFTDIR)/usr/bin/swift 13 | KSWIFTC := $(KSWIFTDIR)/usr/bin/swiftc 14 | KSWIFTLIBDIR := $(KSWIFTDIR)/usr/lib/swift_static/linux 15 | KSWIFTLIBS := $(KSWIFTLIBDIR)/libswiftCore.a $(KSWIFTLIBDIR)/x86_64/swiftrt.o 16 | KSWIFTC_FLAGS := -gnone -Xfrontend -disable-red-zone -Xcc -mno-red-zone -Xfrontend -mcode-model=kernel -Xcc -mcmodel=kernel -parse-as-library -import-objc-header $(TOPDIR)/include/kernel.h -warnings-as-errors -Xcc -Wall -Xcc -Wextra -Xcc -std=gnu11 -Xfrontend -warn-long-function-bodies=60000 -DKERNEL -Xcc -DKERNELLIB=1 17 | 18 | CC := $(KSWIFTDIR)/usr/bin/clang 19 | CFLAGS := -ggdb -Wall -std=gnu11 -Wextra -Werror -fno-builtin -fno-stack-protector -fno-omit-frame-pointer -fno-common -mno-red-zone -mcmodel=kernel -I$(TOPDIR)/include 20 | 21 | ifndef USE_FP 22 | CFLAGS := $(CFLAGS) -mno-mmx -mno-sse -mno-sse2 -ffreestanding 23 | KSWIFTC_FLAGS := $(KSWIFTC_FLAGS) -Xcc -mno-mmx -Xcc -mno-sse -Xcc -mno-sse2 -Xcc -ffreestanding -Xcc -mcmodel=kernel 24 | endif 25 | 26 | 27 | ifdef BUILD_ONONE 28 | KSWIFTC_FLAGS += -Onone 29 | KSWIFTLIBS += $(KSWIFTLIBDIR)/libswiftSwiftOnoneSupport.a 30 | else 31 | KSWIFTC_FLAGS +=-Osize -Xcc -O3 32 | CFLAGS += -O3 33 | endif 34 | 35 | NASM_OBJ_FLAGS := -felf64 36 | 37 | 38 | %.o: %.c 39 | $(CC) $(CFLAGS) -c -o $@ $< 40 | 41 | %.o: %.asm 42 | $(NASM) $(NASM_FLAGS) $(NASM_OBJ_FLAGS) -o $@ $< 43 | 44 | %.bin: %.asm 45 | $(NASM) $(NASM_FLAGS) -fbin -o $@ $< 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR := . 2 | include $(TOPDIR)/Makedefs 3 | 4 | ALL_SOURCES := $(shell find boot klibc kernel include -name '*.swift' -o -name '*.asm' -o -name '*.[ch]') 5 | KERNEL_OBJS := kernel/kernel.o klibc/klibc.o 6 | SUBDIRS := boot kernel klibc utils 7 | EXTRA_LIBS := $(KSWIFTDIR)/usr/lib/swift/clang/lib/linux/libclang_rt.builtins-x86_64.a 8 | 9 | .PHONY: all iso clean kernel 10 | 11 | all: iso 12 | 13 | iso: output/boot-cd.iso 14 | 15 | 16 | output/kernel.elf: $(ALL_SOURCES) 17 | ifneq ($(UNAME_S), Linux) 18 | @echo This only builds on linux && exit 1 19 | endif 20 | mkdir -p $(MODULE_DIR) output 21 | $(MAKE) -C boot 22 | $(MAKE) -C klibc 23 | $(MAKE) -C kernel 24 | $(MAKE) -C utils 25 | # initial link must be via ELF to produce a GOT 26 | ld --no-demangle -static -Tlinker.script -Map=output/kernel.map -z max-page-size=0x1000 -o output/kernel.elf $(KERNEL_OBJS) $(KSWIFTLIBS) $(EXTRA_LIBS) 27 | 28 | 29 | output/kernel.dmp: output/kernel.elf 30 | (objdump -d output/kernel.elf -Mintel | $(SWIFT)-demangle > output/kernel.dmp) 31 | 32 | 33 | output/kernel.efi: output/kernel.elf 34 | objcopy -I binary -O elf64-x86-64 -B i386:x86-64 output/kernel.elf output/kernel.elf.obj 35 | ld --no-demangle -static -Tboot/efi_linker.script -Map=output/efi_body.map -o output/efi_body.bin boot/efi_entry.o boot/efi_main.o boot/efi_elf.o boot/kprintf.o 36 | utils/.build/release/efi_patch boot/efi_header.bin output/efi_body.bin output/kernel.map output/kernel.efi 37 | 38 | 39 | output/kernel.bin: output/kernel.elf 40 | echo Converting output/kernel.elf to output/kernel.bin 41 | objcopy -O binary output/kernel.elf output/kernel.bin 42 | 43 | 44 | output/boot-hd.img: output/kernel.bin 45 | utils/.build/release/mkdiskimg boot/bootsector.bin boot/boot16to64.bin output/kernel.bin output/boot-hd.img 46 | 47 | 48 | output/boot-cd.iso: output/boot-hd.img output/kernel.efi 49 | rm -rf output/iso_tmp output/boot-cd.iso output/efi.img 50 | mkdir -p output/iso_tmp/efi/boot output/iso_tmp/boot 51 | cp output/boot-hd.img output/iso_tmp/boot.img 52 | cp output/kernel.efi output/iso_tmp/efi/boot/bootx64.efi 53 | /sbin/mkfs.msdos -C output/iso_tmp/boot/efi.img 30000 54 | mmd -i output/iso_tmp/boot/efi.img ::efi 55 | mmd -i output/iso_tmp/boot/efi.img ::efi/boot 56 | mcopy -i output/iso_tmp/boot/efi.img output/kernel.efi ::efi/boot 57 | # uncomment line below to make bootable EFI ISO 58 | mcopy -i output/iso_tmp/boot/efi.img output/kernel.efi ::efi/boot/bootx64.efi 59 | xorrisofs -J -joliet-long -isohybrid-mbr boot/isohdr.bin \ 60 | -b boot.img -c boot.cat -boot-load-size 4 -boot-info-table -no-emul-boot \ 61 | -eltorito-alt-boot -e boot/efi.img -no-emul-boot -isohybrid-gpt-basdat \ 62 | -isohybrid-apm-hfsplus -o output/boot-cd.iso output/iso_tmp 63 | rm -r output/iso_tmp 64 | 65 | 66 | clean: 67 | rm -rf output/* 68 | set -e; for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done 69 | -------------------------------------------------------------------------------- /NOTES: -------------------------------------------------------------------------------- 1 | 2 | Debugging: 3 | 4 | readelf --debug-dump=line 5 | 6 | use -ggdb for C/C++ sources 7 | dont not use and -g options for swift sources as 8 | 9 | 1. GDB doesnt understand swift anyway 10 | 2. Linking swift debug and c debug, even if both are the same DWARF type means that only the swift files 11 | show up in `info sources`. Even though an ELF file which is mixed will show both with the above readelf 12 | command 13 | 14 | 3. Currently build with --debug-swift-stdlib to get the debug (none optimized) runtime to link with all of the 15 | extra c++ string functions. 16 | should show what source files are known about. 17 | 18 | 19 | qemu can only be used with GDB 20 | vmware can be used with both GDB and LLDB - LLDB better as it understands Swift source code 21 | 22 | Wehn using with GDB, dont compile with -g on Swift soruces as GDB gets confused by the DWARF info. 23 | 24 | VMWare better emulator but the remote debugging can sometime cause it to hang on exit. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # project1 - Implementing a minimal bare metal kernel in Swift 2 | 3 | ## What is it? 4 | 5 | A project to write a kernel in Swift that can boot on a Mac or PC. 6 | The main aim is to get a simple kernel booting up with a CLI with full 7 | concurrency/thread support. 8 | 9 | There is a short writeup about it [here](http://si.org/projects/project1). 10 | 11 | ## Current status 12 | 13 | - Boots up under QEMU, Bochs and VMWare. Also boots on Macbook 3,1 (13inch Late 2007) 14 | - Installs interrupts and exception/fault handlers 15 | - Sets up paging 16 | - Scans ACPI/SMBIOS tables 17 | - Parses ACPI tables including AML bytecode in DSDT, SSDT tables 18 | - Initialises the APIC and IO/APIC (or PIC) 19 | - Traverses the ACPI device tree adding known devices according to topology. 20 | - Scans PCI bus (MMIO or PIO) to show vendor/device IDs 21 | - Initialises the PIT and PS/2 keyboard controller 22 | - Sets up an APIC and PIT timers and shows a test message with interrupt counts. 23 | - Runs a simple task reading keyboard scan codes from a circular buffer and 24 | translates them to ASCII codes to show on the screen. The Macbook doesn't 25 | have an i8042 PS/2 keyboard controller so the keyboard will not work. 26 | 27 | Currently working on enabling ACPI to process ACPI events and setting up more 28 | devices including the Realtime Clock and PCI interrupts. 29 | 30 | The next major tasks are: 31 | 32 | - USB controller and USB keyboard driver for the keyboard on Macbook 3,1 33 | 34 | 35 | ## How to build it 36 | 37 | Use Docker to build a container that includes the swift compiler with the modified stdlib using 38 | the Dockerfile in `Docker/Dockerfile`. 39 | 40 | ### Build the docker container 41 | 42 | ``` 43 | $ docker build --tag=swift-kstdlib Docker 44 | ``` 45 | 46 | To build the kernel and disk images from the command line: 47 | ``` 48 | $ docker run --rm -v `pwd`:`pwd` -w `pwd` -t swift-kstdlib make iso 49 | ``` 50 | or using Xcode, open `project1.xcodeproj`, select `kernel` in the target menu and then `Product → Build` 51 | or ⌘-B to build it. 52 | 53 | 54 | ## How to run it 55 | 56 | To run under qemu with a copy of the console output being sent to a virtual 57 | serial port use: 58 | 59 | `./run_qemu.sh` 60 | 61 | or to use with UEFI/OVMF BIOS 62 | `./run_qemu.sh --efi` 63 | 64 | There is a bochsrc to specify the HD image so it can be run with: 65 | 66 | `bochs -q` 67 | 68 | (then press `c` to run) 69 | 70 | ![Screenshot](doc/screenshot-2.png) 71 | 72 | 73 | Copyright (c) 2015 - 2020 Simon Evans 74 | 75 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 76 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 77 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 78 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 79 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 80 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 81 | SOFTWARE. 82 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | DEBUGGING: 2 | - Fix stack guard page 3 | - Add stub exception handlers in the IDT as early as possible to catch DIV0 etc 4 | - Fix makefile to build debug 5 | - Compress kernel to allow bigger kernel in ISO 6 | - Fix call to swift::fatalError() to work correctly 7 | 8 | Fix vasprintf() as used by assert() 9 | Improve backtrack/stacktrace 10 | ACPI: Setup acpi as a device 11 | Fix string sorting for ASCII / Decide on libicu stub 12 | Add MemoryManager and TaskManager classes. 13 | Add Resource manager for i/o ports and mmio 14 | IOAPIC: PCI interrupt routing 15 | Reduce the number of global values and functions 16 | Better setup of initial mapping to not waste physical page for guardpage 17 | Locks for hardware access eg PIC 18 | Enable multicore 19 | MOSTLY DONE fix keyboard scan codes and full scan code 20 | Shrink down boot16to64.bin 21 | use struct/class more consistenly and fixup what should be singletons etc 22 | DONE - convert device drivers to all be classes 23 | CPU & 24 | DONE Bootparams still needs fixing 25 | 26 | MAYBE Implement malloc() in swift 27 | 28 | DONE Load kernel as ELF and implement dladdr()/backtrace() (-z max-page-size=0x1000) 29 | -------------------------------------------------------------------------------- /Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tests/KlibTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KlibTests.swift 3 | // acpitest 4 | // 5 | // Created by Simon Evans on 06/12/2017. 6 | // Copyright © 2017 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class KlibTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testReservationManager() { 24 | var rs = ReservationSpace(name: "IO Ports", start: 0, end: 0xffff) 25 | XCTAssertTrue(rs.reserveSpace(name: "kbd8042", start: 0x60, end: 0x60)) 26 | XCTAssertTrue(rs.reserveSpace(name: "kbd8042", start: 0x64, end: 0x64)) 27 | XCTAssertFalse(rs.reserveSpace(name: "kbd8042", start: 0x60, end: 0x62)) 28 | 29 | rs.showReservedSpaces() 30 | } 31 | 32 | 33 | func testBitArray8() { 34 | var ba = BitArray64() 35 | XCTAssertEqual(ba.toUInt64(), 0) 36 | ba[7] = 1 37 | XCTAssertEqual(ba.toUInt64(), 128) 38 | XCTAssertEqual(ba.toUInt32(), 128) 39 | XCTAssertEqual(ba.toUInt16(), 128) 40 | XCTAssertEqual(ba.toUInt8(), 128) 41 | } 42 | 43 | func testBitArray64() { 44 | var ba = BitArray64() 45 | XCTAssertEqual(ba.toUInt64(), 0) 46 | XCTAssertEqual(ba[63], 0) 47 | ba[63] = 1 48 | XCTAssertEqual(ba[63], 1) 49 | XCTAssertEqual(ba.toUInt64(), 9223372036854775808) 50 | XCTAssertEqual(ba.toUInt32(), 0) 51 | XCTAssertEqual(ba.toUInt16(), 0) 52 | XCTAssertEqual(ba.toUInt8(), 0) 53 | } 54 | 55 | static var allTests = [ 56 | ("testReservatonManager", testReservationManager), 57 | ("testBitArray8", testBitArray8), 58 | ("testBitArray64", testBitArray64), 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /Tests/PageSizeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageSizeTests.swift 3 | // tests 4 | // 5 | // Created by Simon Evans on 16/01/2022. 6 | // Copyright © 2022 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class PageSizeTests: XCTestCase { 12 | 13 | func testPageSize() { 14 | let pageSize = PageSize() 15 | XCTAssertEqual(pageSize.size, 4096) 16 | XCTAssertEqual(pageSize.mask, 0xffff_ffff_ffff_F000) 17 | XCTAssertEqual(pageSize.encoding, 1) 18 | 19 | XCTAssertTrue(pageSize.isPageAligned(0xffff000)) 20 | XCTAssertTrue(pageSize.isPageAligned(0xfff1000)) 21 | XCTAssertTrue(pageSize.isPageAligned(0xf0ff000)) 22 | XCTAssertFalse(pageSize.isPageAligned(0xffff001)) 23 | 24 | XCTAssertEqual(pageSize.roundDown(0x234), 0x0) 25 | XCTAssertEqual(pageSize.roundToNextPage(0x234), 0x1000) 26 | XCTAssertEqual(pageSize.roundDown(0x1234), 0x1000) 27 | XCTAssertEqual(pageSize.roundToNextPage(0x1234), 0x2000) 28 | 29 | XCTAssertEqual(pageSize.lastAddressInPage(0x234), 0xfff) 30 | XCTAssertEqual(pageSize.lastAddressInPage(0x1234), 0x1fff) 31 | 32 | XCTAssertTrue(pageSize.onSamePage(0x1234, 0x1001)) 33 | XCTAssertTrue(pageSize.onSamePage(0x1000, 0x1fff)) 34 | XCTAssertFalse(pageSize.onSamePage(0x1234, 0x2001)) 35 | XCTAssertFalse(pageSize.onSamePage(0x1234, 0x2000)) 36 | 37 | XCTAssertEqual(pageSize.pageCountCovering(size:0x1234), 2) 38 | XCTAssertEqual(pageSize.pageCountCovering(size:0x1), 1) 39 | XCTAssertEqual(pageSize.pageCountCovering(size:0x3001), 4) 40 | XCTAssertEqual(pageSize.pageCountCovering(size:0x0), 0) 41 | 42 | XCTAssertEqual(pageSize.offsetInPage(0x1234), 0x234) 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Tests/PhysPageRangeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysPageAlignedRegionTests.swift 3 | // tests 4 | // 5 | // Created by Simon Evans on 15/01/2022. 6 | // Copyright © 2022 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class PhysPageAlignedRegionTests: XCTestCase { 12 | 13 | func testPageRangeChunks() { 14 | let physPageRange = PhysPageAlignedRegion(PhysAddress(0x1000), pageSize: PageSize(), pageCount: 130) 15 | var iterator = PhysPageAlignedRegionChunksInterator(physPageRange, pagesPerChunk: 128) 16 | while let chunk = iterator.next() { 17 | print(chunk) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Tests/StringTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringTests.swift 3 | // acpitest 4 | // 5 | // Created by Simon Evans on 02/08/2017. 6 | // Copyright © 2017 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class StringTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testSprintf() { 24 | let output1 = String.sprintf("Test: %lx", 0x0123456789abcdef) 25 | XCTAssertEqual("Test: 123456789abcdef", output1, "`lx' format specifier") 26 | 27 | let output2 = String.sprintf("Test: %p", 0x1234567890abcdef) 28 | XCTAssertEqual("Test: 0x1234567890abcdef", output2, "`p' format specifier") 29 | 30 | let output3 = String.sprintf("R8: %16lx", 0x0808080808080808) 31 | XCTAssertEqual("R8: 808080808080808", output3, "`16.16lx' 64bit number") 32 | 33 | let output4 = String.sprintf("R8: %016lx", 0x0808080808080808) 34 | print(output4) 35 | XCTAssertEqual("R8: 0808080808080808", output4, "`016.16lx' 64bit number") 36 | 37 | let output5 = String.sprintf("RAX: %#16.16lX", 0xaaaaaaaaaaaaaaaa as UInt64) 38 | XCTAssertEqual("RAX: 0XAAAAAAAAAAAAAAAA", output5, "`#16.16lx' 64bit number hight bit set") 39 | } 40 | 41 | func testByteArray2() { 42 | let x = ByteArray2([2, 1]) 43 | XCTAssertEqual(0x102, x.toInt(), "ByteArray2.toInt") 44 | XCTAssertEqual(2, x[0], "ByteArray2[0]") 45 | XCTAssertEqual(1, x[1], "ByteArray2[1]") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/USBTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // USBTests.swift 3 | // tests 4 | // 5 | // Created by Simon Evans on 27/10/2020. 6 | // Copyright © 2020 Simon Evans. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | enum USB {} 12 | 13 | class USBTests: XCTestCase { 14 | 15 | 16 | func testConfigDescriptor() throws { 17 | let getDescriptorConfigData = Data([ 18 | 0x09, 0x02, 0x3b, 0x00, 0x02, 0x01, 0x01, 0xc0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 19 | 0x00, 0x01, 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, 0x42, 0x00, 0x07, 0x05, 0x81, 0x03, 0x08, 20 | 0x00, 0x01, 0x09, 0x04, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x09, 0x21, 0x10, 0x01, 0x00, 21 | 0x01, 0x22, 0x41, 0x00, 0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x01, 22 | ]) 23 | 24 | XCTAssertEqual(getDescriptorConfigData.count, 59) 25 | 26 | let region = PhysRegion(data: getDescriptorConfigData) 27 | let mmioRegion = MMIOSubRegion(baseAddress: region.baseAddress, count: Int(region.size)) 28 | let configDescriptor = try USB.ConfigDescriptor(from: mmioRegion) 29 | 30 | print(configDescriptor) 31 | 32 | } 33 | 34 | 35 | func testConfigDescriptor2() throws { 36 | let getDescriptorConfigData = Data([ 37 | 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0xe0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x01, 0x09, 38 | 0x00, 0x00, 0x00, 0x07, 0x05, 0x81, 0x03, 0x02, 0x00, 0x0f 39 | ]) 40 | XCTAssertEqual(getDescriptorConfigData.count, 25) 41 | 42 | let region = PhysRegion(data: getDescriptorConfigData) 43 | let mmioRegion = MMIOSubRegion(baseAddress: region.baseAddress, count: Int(region.size)) 44 | let configDescriptor = try USB.ConfigDescriptor(from: mmioRegion) 45 | 46 | print(configDescriptor) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Tests/test.h: -------------------------------------------------------------------------------- 1 | // 2 | // test.h 3 | // project1 4 | // 5 | // Created by Simon Evans on 31/07/2017. 6 | // Copyright © 2017 Simon Evans. All rights reserved. 7 | // 8 | 9 | #ifndef test_h 10 | #define test_h 11 | 12 | #define TEST 1 13 | 14 | #include 15 | #include "../include/mm.h" 16 | #include "../include/acpi.h" 17 | #include "../include/usb.h" 18 | #include "../include/io.h" 19 | #include "../include/x86defs.h" 20 | #include "../include/x86funcs.h" 21 | #include "../include/klibc.h" 22 | 23 | static inline int kprintf1arg(const char * _Nonnull fmt, long l1) { 24 | return printf(fmt, l1); 25 | } 26 | 27 | static inline int kprintf2args(const char * _Nonnull fmt, long l1, long l2) { 28 | return printf(fmt, l1, l2); 29 | } 30 | 31 | static inline int kprintf3args(const char * _Nonnull fmt, long l1, long l2, long l3) { 32 | return printf(fmt, l1, l2, l3); 33 | } 34 | #endif /* test_h */ 35 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-APIC.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-APIC.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-ASF!.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-ASF!.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-DSDT.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-DSDT.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-ECDT.aml: -------------------------------------------------------------------------------- 1 | ECDTS9APPLE Apple00Loki_fb\_SB.PCI0.LPCB.EC -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-ECDT.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of ECDT.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [ECDT] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "ECDT" [Embedded Controller Boot Resources Table] 14 | [004h 0004 4] Table Length : 00000053 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 39 17 | [00Ah 0010 6] Oem ID : "APPLE " 18 | [010h 0016 8] Oem Table ID : "Apple00" 19 | [018h 0024 4] Oem Revision : 00000001 20 | [01Ch 0028 4] Asl Compiler ID : "Loki" 21 | [020h 0032 4] Asl Compiler Revision : 0000005F 22 | 23 | 24 | [024h 0036 12] Command/Status Register : [Generic Address Structure] 25 | [024h 0036 1] Space ID : 01 [SystemIO] 26 | [025h 0037 1] Bit Width : 08 27 | [026h 0038 1] Bit Offset : 00 28 | [027h 0039 1] Encoded Access Width : 00 [Undefined/Legacy] 29 | [028h 0040 8] Address : 0000000000000066 30 | 31 | [030h 0048 12] Data Register : [Generic Address Structure] 32 | [030h 0048 1] Space ID : 01 [SystemIO] 33 | [031h 0049 1] Bit Width : 08 34 | [032h 0050 1] Bit Offset : 00 35 | [033h 0051 1] Encoded Access Width : 00 [Undefined/Legacy] 36 | [034h 0052 8] Address : 0000000000000062 37 | 38 | [03Ch 0060 4] UID : 00000000 39 | [040h 0064 1] GPE Number : 17 40 | [041h 0065 18] Namepath : "\_SB.PCI0.LPCB.EC" 41 | 42 | Raw Table Data: Length 83 (0x53) 43 | 44 | 0000: 45 43 44 54 53 00 00 00 01 39 41 50 50 4C 45 20 // ECDTS....9APPLE 45 | 0010: 41 70 70 6C 65 30 30 00 01 00 00 00 4C 6F 6B 69 // Apple00.....Loki 46 | 0020: 5F 00 00 00 01 08 00 00 66 00 00 00 00 00 00 00 // _.......f....... 47 | 0030: 01 08 00 00 62 00 00 00 00 00 00 00 00 00 00 00 // ....b........... 48 | 0040: 17 5C 5F 53 42 2E 50 43 49 30 2E 4C 50 43 42 2E // .\_SB.PCI0.LPCB. 49 | 0050: 45 43 00 // EC. 50 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-FACP.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-FACP.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-FACS1.aml: -------------------------------------------------------------------------------- 1 | FACS@ -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-FACS1.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of FACS1.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [FACS] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "FACS" 14 | [004h 0004 4] Length : 00000040 15 | [008h 0008 4] Hardware Signature : 00001000 16 | [00Ch 0012 4] 32 Firmware Waking Vector : 00000000 17 | [010h 0016 4] Global Lock : 00000000 18 | [014h 0020 4] Flags (decoded below) : 00000000 19 | S4BIOS Support Present : 0 20 | 64-bit Wake Supported (V2) : 0 21 | [018h 0024 8] 64 Firmware Waking Vector : 0000000000000000 22 | [020h 0032 1] Version : 01 23 | [021h 0033 3] Reserved : 000000 24 | [024h 0036 4] OspmFlags (decoded below) : 00000000 25 | 64-bit Wake Env Required (V2) : 0 26 | 27 | Raw Table Data: Length 64 (0x40) 28 | 29 | 0000: 46 41 43 53 40 00 00 00 00 10 00 00 00 00 00 00 // FACS@........... 30 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 31 | 0020: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 32 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 33 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-FACS2.aml: -------------------------------------------------------------------------------- 1 | FACS@ -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-FACS2.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of FACS2.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [FACS] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "FACS" 14 | [004h 0004 4] Length : 00000040 15 | [008h 0008 4] Hardware Signature : 00001000 16 | [00Ch 0012 4] 32 Firmware Waking Vector : 00000000 17 | [010h 0016 4] Global Lock : 00000000 18 | [014h 0020 4] Flags (decoded below) : 00000000 19 | S4BIOS Support Present : 0 20 | 64-bit Wake Supported (V2) : 0 21 | [018h 0024 8] 64 Firmware Waking Vector : 0000000000000000 22 | [020h 0032 1] Version : 01 23 | [021h 0033 3] Reserved : 000000 24 | [024h 0036 4] OspmFlags (decoded below) : 00000000 25 | 64-bit Wake Env Required (V2) : 0 26 | 27 | Raw Table Data: Length 64 (0x40) 28 | 29 | 0000: 46 41 43 53 40 00 00 00 00 10 00 00 00 00 00 00 // FACS@........... 30 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 31 | 0020: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 32 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 33 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-HPET.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-HPET.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-HPET.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of HPET.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [HPET] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "HPET" [High Precision Event Timer table] 14 | [004h 0004 4] Table Length : 00000038 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : CC 17 | [00Ah 0010 6] Oem ID : "APPLE " 18 | [010h 0016 8] Oem Table ID : "Apple00" 19 | [018h 0024 4] Oem Revision : 00000001 20 | [01Ch 0028 4] Asl Compiler ID : "Loki" 21 | [020h 0032 4] Asl Compiler Revision : 0000005F 22 | 23 | [024h 0036 4] Hardware Block ID : 8086A201 24 | 25 | [028h 0040 12] Timer Block Register : [Generic Address Structure] 26 | [028h 0040 1] Space ID : 00 [SystemMemory] 27 | [029h 0041 1] Bit Width : 00 28 | [02Ah 0042 1] Bit Offset : 00 29 | [02Bh 0043 1] Encoded Access Width : 00 [Undefined/Legacy] 30 | [02Ch 0044 8] Address : 00000000FED00000 31 | 32 | [034h 0052 1] Sequence Number : 00 33 | [035h 0053 2] Minimum Clock Ticks : 0080 34 | [037h 0055 1] Flags (decoded below) : 00 35 | 4K Page Protect : 0 36 | 64K Page Protect : 0 37 | 38 | Raw Table Data: Length 56 (0x38) 39 | 40 | 0000: 48 50 45 54 38 00 00 00 01 CC 41 50 50 4C 45 20 // HPET8.....APPLE 41 | 0010: 41 70 70 6C 65 30 30 00 01 00 00 00 4C 6F 6B 69 // Apple00.....Loki 42 | 0020: 5F 00 00 00 01 A2 86 80 00 00 00 00 00 00 D0 FE // _............... 43 | 0030: 00 00 00 00 00 80 00 00 // ........ 44 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-MCFG.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-MCFG.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-MCFG.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of MCFG.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [MCFG] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "MCFG" [Memory Mapped Configuration table] 14 | [004h 0004 4] Table Length : 0000003C 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : E4 17 | [00Ah 0010 6] Oem ID : "APPLE " 18 | [010h 0016 8] Oem Table ID : "Apple00" 19 | [018h 0024 4] Oem Revision : 00000001 20 | [01Ch 0028 4] Asl Compiler ID : "Loki" 21 | [020h 0032 4] Asl Compiler Revision : 0000005F 22 | 23 | [024h 0036 8] Reserved : 0000000000000000 24 | 25 | [02Ch 0044 8] Base Address : 00000000F0000000 26 | [034h 0052 2] Segment Group Number : 0000 27 | [036h 0054 1] Start Bus Number : 00 28 | [037h 0055 1] End Bus Number : FF 29 | [038h 0056 4] Reserved : 00000000 30 | 31 | Raw Table Data: Length 60 (0x3C) 32 | 33 | 0000: 4D 43 46 47 3C 00 00 00 01 E4 41 50 50 4C 45 20 // MCFG<.....APPLE 34 | 0010: 41 70 70 6C 65 30 30 00 01 00 00 00 4C 6F 6B 69 // Apple00.....Loki 35 | 0020: 5F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 // _............... 36 | 0030: 00 00 00 00 00 00 00 FF 00 00 00 00 // ............ 37 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SBST.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SBST.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SBST.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of SBST.aml, Sun Apr 30 09:56:03 2017 7 | * 8 | * ACPI Data Table [SBST] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "SBST" [Smart Battery Specification Table] 14 | [004h 0004 4] Table Length : 00000030 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 84 17 | [00Ah 0010 6] Oem ID : "APPLE " 18 | [010h 0016 8] Oem Table ID : "Apple00" 19 | [018h 0024 4] Oem Revision : 00000001 20 | [01Ch 0028 4] Asl Compiler ID : "Loki" 21 | [020h 0032 4] Asl Compiler Revision : 0000005F 22 | 23 | [024h 0036 4] Warning Level : 0000001E 24 | [028h 0040 4] Low Level : 00000014 25 | [02Ch 0044 4] Critical Level : 0000000A 26 | 27 | Raw Table Data: Length 48 (0x30) 28 | 29 | 0000: 53 42 53 54 30 00 00 00 01 84 41 50 50 4C 45 20 // SBST0.....APPLE 30 | 0010: 41 70 70 6C 65 30 30 00 01 00 00 00 4C 6F 6B 69 // Apple00.....Loki 31 | 0020: 5F 00 00 00 1E 00 00 00 14 00 00 00 0A 00 00 00 // _............... 32 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT1.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT1.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT1.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembling to symbolic ASL+ operators 7 | * 8 | * Disassembly of SSDT1.aml, Sun Apr 30 09:56:03 2017 9 | * 10 | * Original Table Header: 11 | * Signature "SSDT" 12 | * Length 0x00000137 (311) 13 | * Revision 0x01 14 | * Checksum 0x89 15 | * OEM ID "APPLE " 16 | * OEM Table ID "SataAhci" 17 | * OEM Revision 0x00001000 (4096) 18 | * Compiler ID "INTL" 19 | * Compiler Version 0x20061109 (537268489) 20 | */ 21 | DefinitionBlock ("SSDT1.aml", "SSDT", 1, "APPLE ", "SataAhci", 0x00001000) 22 | { 23 | 24 | External (_SB_.PCI0.SATA, DeviceObj) 25 | External (GP27, UnknownObj) 26 | External (GTF0, IntObj) 27 | 28 | Scope (\_SB.PCI0.SATA) 29 | { 30 | Device (PRT0) 31 | { 32 | Name (_ADR, 0xFFFF) // _ADR: Address 33 | Method (_SDD, 1, NotSerialized) // _SDD: Set Device Data 34 | { 35 | Name (GBU0, Buffer (0x07) 36 | { 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00 /* ....... */ 38 | }) 39 | CreateByteField (GBU0, 0x00, GB00) 40 | CreateByteField (GBU0, 0x01, GB01) 41 | CreateByteField (GBU0, 0x02, GB02) 42 | CreateByteField (GBU0, 0x03, GB03) 43 | CreateByteField (GBU0, 0x04, GB04) 44 | CreateByteField (GBU0, 0x05, GB05) 45 | CreateByteField (GBU0, 0x06, GB06) 46 | If ((SizeOf (Arg0) == 0x0200)) 47 | { 48 | CreateWordField (Arg0, 0x9C, W780) 49 | If ((W780 & 0x08)) 50 | { 51 | GB00 = 0x10 52 | GB01 = 0x03 53 | GB06 = 0xEF 54 | } 55 | Else 56 | { 57 | GB00 = 0x90 58 | GB01 = 0x03 59 | GB06 = 0xEF 60 | } 61 | } 62 | 63 | GTF0 = GBU0 /* \_SB_.PCI0.SATA.PRT0._SDD.GBU0 */ 64 | } 65 | 66 | Method (_GTF, 0, NotSerialized) // _GTF: Get Task File 67 | { 68 | Return (GTF0) /* External reference */ 69 | } 70 | 71 | Method (_PS0, 0, Serialized) // _PS0: Power State 0 72 | { 73 | GP27 = 0x00 74 | } 75 | 76 | Method (_PS3, 0, Serialized) // _PS3: Power State 3 77 | { 78 | GP27 = 0x01 79 | } 80 | 81 | Method (_PSC, 0, Serialized) // _PSC: Power State Current 82 | { 83 | If (!GP27) 84 | { 85 | Return (0x00) 86 | } 87 | 88 | Return (0x03) 89 | } 90 | } 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT2.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT2.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT3.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT3.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT4.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT4.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT4.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembling to symbolic ASL+ operators 7 | * 8 | * Disassembly of SSDT4.aml, Sun Apr 30 09:56:03 2017 9 | * 10 | * Original Table Header: 11 | * Signature "SSDT" 12 | * Length 0x000000A6 (166) 13 | * Revision 0x01 14 | * Checksum 0xE4 15 | * OEM ID "APPLE" 16 | * OEM Table ID "Cpu1Tst" 17 | * OEM Revision 0x00003000 (12288) 18 | * Compiler ID "INTL" 19 | * Compiler Version 0x20061109 (537268489) 20 | */ 21 | DefinitionBlock ("SSDT4.aml", "SSDT", 1, "APPLE", "Cpu1Tst", 0x00003000) 22 | { 23 | 24 | External (_PR_.CPU0._PTC, IntObj) 25 | External (_PR_.CPU0._TSS, IntObj) 26 | External (_PR_.CPU1, DeviceObj) 27 | External (CFGD, UnknownObj) 28 | External (PDC1, UnknownObj) 29 | 30 | Scope (\_PR.CPU1) 31 | { 32 | Name (_TPC, 0x00) // _TPC: Throttling Present Capabilities 33 | Method (_PTC, 0, NotSerialized) // _PTC: Processor Throttling Control 34 | { 35 | Return (\_PR.CPU0._PTC) /* External reference */ 36 | } 37 | 38 | Method (_TSS, 0, NotSerialized) // _TSS: Throttling Supported States 39 | { 40 | Return (\_PR.CPU0._TSS) /* External reference */ 41 | } 42 | 43 | Method (_TSD, 0, NotSerialized) // _TSD: Throttling State Dependencies 44 | { 45 | If (((CFGD & 0x01000000) && !(PDC1 & 0x04))) 46 | { 47 | Return (Package (0x01) 48 | { 49 | Package (0x05) 50 | { 51 | 0x05, 52 | 0x00, 53 | 0x00, 54 | 0xFD, 55 | 0x02 56 | } 57 | }) 58 | } 59 | 60 | Return (Package (0x01) 61 | { 62 | Package (0x05) 63 | { 64 | 0x05, 65 | 0x00, 66 | 0x01, 67 | 0xFC, 68 | 0x01 69 | } 70 | }) 71 | } 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT5.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT5.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT6.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT6.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT7.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT7.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT7.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembling to symbolic ASL+ operators 7 | * 8 | * Disassembly of SSDT7.aml, Sun Apr 30 09:56:03 2017 9 | * 10 | * Original Table Header: 11 | * Signature "SSDT" 12 | * Length 0x000000C8 (200) 13 | * Revision 0x01 14 | * Checksum 0x07 15 | * OEM ID "APPLE" 16 | * OEM Table ID "Cpu1Ist" 17 | * OEM Revision 0x00003000 (12288) 18 | * Compiler ID "INTL" 19 | * Compiler Version 0x20061109 (537268489) 20 | */ 21 | DefinitionBlock ("SSDT7.aml", "SSDT", 1, "APPLE", "Cpu1Ist", 0x00003000) 22 | { 23 | 24 | External (_PR_.CPU0._PPC, IntObj) 25 | External (_PR_.CPU0._PSS, IntObj) 26 | External (_PR_.CPU1, DeviceObj) 27 | External (PDC1, UnknownObj) 28 | 29 | Scope (\_PR.CPU1) 30 | { 31 | Method (_PPC, 0, NotSerialized) // _PPC: Performance Present Capabilities 32 | { 33 | Return (\_PR.CPU0._PPC) /* External reference */ 34 | } 35 | 36 | Method (_PCT, 0, NotSerialized) // _PCT: Performance Control 37 | { 38 | Return (Package (0x02) 39 | { 40 | ResourceTemplate () 41 | { 42 | Register (FFixedHW, 43 | 0x00, // Bit Width 44 | 0x00, // Bit Offset 45 | 0x0000000000000000, // Address 46 | ,) 47 | }, 48 | 49 | ResourceTemplate () 50 | { 51 | Register (FFixedHW, 52 | 0x00, // Bit Width 53 | 0x00, // Bit Offset 54 | 0x0000000000000000, // Address 55 | ,) 56 | } 57 | }) 58 | } 59 | 60 | Method (_PSS, 0, NotSerialized) // _PSS: Performance Supported States 61 | { 62 | Return (\_PR.CPU0._PSS) /* External reference */ 63 | } 64 | 65 | Method (_PSD, 0, NotSerialized) // _PSD: Power State Dependencies 66 | { 67 | If ((PDC1 & 0x0800)) 68 | { 69 | Return (Package (0x01) 70 | { 71 | Package (0x05) 72 | { 73 | 0x05, 74 | 0x00, 75 | 0x00, 76 | 0xFE, 77 | 0x02 78 | } 79 | }) 80 | } 81 | 82 | Return (Package (0x01) 83 | { 84 | Package (0x05) 85 | { 86 | 0x05, 87 | 0x00, 88 | 0x00, 89 | 0xFC, 90 | 0x02 91 | } 92 | }) 93 | } 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT8.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/macbook31/macbook31-SSDT8.aml -------------------------------------------------------------------------------- /Tests/test_files/macbook31/macbook31-SSDT8.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembling to symbolic ASL+ operators 7 | * 8 | * Disassembly of SSDT8.aml, Sun Apr 30 09:56:03 2017 9 | * 10 | * Original Table Header: 11 | * Signature "SSDT" 12 | * Length 0x00000085 (133) 13 | * Revision 0x01 14 | * Checksum 0xF1 15 | * OEM ID "APPLE" 16 | * OEM Table ID "Cpu1Cst" 17 | * OEM Revision 0x00003000 (12288) 18 | * Compiler ID "INTL" 19 | * Compiler Version 0x20061109 (537268489) 20 | */ 21 | DefinitionBlock ("SSDT8.aml", "SSDT", 1, "APPLE", "Cpu1Cst", 0x00003000) 22 | { 23 | 24 | External (_PR_.CPU0._CST, IntObj) 25 | External (_PR_.CPU1, DeviceObj) 26 | External (CFGD, UnknownObj) 27 | External (PDC1, UnknownObj) 28 | 29 | Scope (\_PR.CPU1) 30 | { 31 | Method (_CST, 0, NotSerialized) // _CST: C-States 32 | { 33 | If (((CFGD & 0x01000000) && !(PDC1 & 0x10))) 34 | { 35 | Return (Package (0x02) 36 | { 37 | 0x01, 38 | Package (0x04) 39 | { 40 | ResourceTemplate () 41 | { 42 | Register (FFixedHW, 43 | 0x00, // Bit Width 44 | 0x00, // Bit Offset 45 | 0x0000000000000000, // Address 46 | ,) 47 | }, 48 | 49 | 0x01, 50 | 0x9D, 51 | 0x03E8 52 | } 53 | }) 54 | } 55 | 56 | Return (\_PR.CPU0._CST) /* External reference */ 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Tests/test_files/qemu/QEMU-DSDT.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/qemu/QEMU-DSDT.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-APIC.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-APIC.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-BOOT.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-BOOT.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-BOOT.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of BOOT.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [BOOT] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "BOOT" [Simple Boot Flag Table] 14 | [004h 0004 4] Table Length : 00000028 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : A5 17 | [00Ah 0010 6] Oem ID : "PTLTD " 18 | [010h 0016 8] Oem Table ID : "$SBFTBL$" 19 | [018h 0024 4] Oem Revision : 06040000 20 | [01Ch 0028 4] Asl Compiler ID : " LTP" 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 1] Boot Register Index : 36 24 | [025h 0037 3] Reserved : 000000 25 | 26 | Raw Table Data: Length 40 (0x28) 27 | 28 | 0000: 42 4F 4F 54 28 00 00 00 01 A5 50 54 4C 54 44 20 // BOOT(.....PTLTD 29 | 0010: 24 53 42 46 54 42 4C 24 00 00 04 06 20 4C 54 50 // $SBFTBL$.... LTP 30 | 0020: 01 00 00 00 36 00 00 00 // ....6... 31 | -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-DSDT.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-DSDT.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-FACP.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-FACP.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-FACS1.aml: -------------------------------------------------------------------------------- 1 | FACS@ -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-FACS1.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of FACS1.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [FACS] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "FACS" 14 | [004h 0004 4] Length : 00000040 15 | [008h 0008 4] Hardware Signature : 00000000 16 | [00Ch 0012 4] 32 Firmware Waking Vector : 00000000 17 | [010h 0016 4] Global Lock : 00000000 18 | [014h 0020 4] Flags (decoded below) : 00000000 19 | S4BIOS Support Present : 0 20 | 64-bit Wake Supported (V2) : 0 21 | [018h 0024 8] 64 Firmware Waking Vector : 0000000000000000 22 | [020h 0032 1] Version : 00 23 | [021h 0033 3] Reserved : 000000 24 | [024h 0036 4] OspmFlags (decoded below) : 00000000 25 | 64-bit Wake Env Required (V2) : 0 26 | 27 | Raw Table Data: Length 64 (0x40) 28 | 29 | 0000: 46 41 43 53 40 00 00 00 00 00 00 00 00 00 00 00 // FACS@........... 30 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 31 | 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 32 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 33 | -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-FACS2.aml: -------------------------------------------------------------------------------- 1 | FACS@ -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-FACS2.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of FACS2.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [FACS] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "FACS" 14 | [004h 0004 4] Length : 00000040 15 | [008h 0008 4] Hardware Signature : 00000000 16 | [00Ch 0012 4] 32 Firmware Waking Vector : 00000000 17 | [010h 0016 4] Global Lock : 00000000 18 | [014h 0020 4] Flags (decoded below) : 00000000 19 | S4BIOS Support Present : 0 20 | 64-bit Wake Supported (V2) : 0 21 | [018h 0024 8] 64 Firmware Waking Vector : 0000000000000000 22 | [020h 0032 1] Version : 00 23 | [021h 0033 3] Reserved : 000000 24 | [024h 0036 4] OspmFlags (decoded below) : 00000000 25 | 64-bit Wake Env Required (V2) : 0 26 | 27 | Raw Table Data: Length 64 (0x40) 28 | 29 | 0000: 46 41 43 53 40 00 00 00 00 00 00 00 00 00 00 00 // FACS@........... 30 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 31 | 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 32 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 33 | -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-HPET.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-HPET.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-HPET.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of HPET.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [HPET] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "HPET" [High Precision Event Timer table] 14 | [004h 0004 4] Table Length : 00000038 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : AA 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW HPET" 19 | [018h 0024 4] Oem Revision : 06040000 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 4] Hardware Block ID : 8086AF01 24 | 25 | [028h 0040 12] Timer Block Register : [Generic Address Structure] 26 | [028h 0040 1] Space ID : 00 [SystemMemory] 27 | [029h 0041 1] Bit Width : 00 28 | [02Ah 0042 1] Bit Offset : 00 29 | [02Bh 0043 1] Encoded Access Width : 00 [Undefined/Legacy] 30 | [02Ch 0044 8] Address : 00000000FED00000 31 | 32 | [034h 0052 1] Sequence Number : 00 33 | [035h 0053 2] Minimum Clock Ticks : 37EE 34 | [037h 0055 1] Flags (decoded below) : 01 35 | 4K Page Protect : 1 36 | 64K Page Protect : 0 37 | 38 | Raw Table Data: Length 56 (0x38) 39 | 40 | 0000: 48 50 45 54 38 00 00 00 01 AA 56 4D 57 41 52 45 // HPET8.....VMWARE 41 | 0010: 56 4D 57 20 48 50 45 54 00 00 04 06 56 4D 57 20 // VMW HPET....VMW 42 | 0020: 01 00 00 00 01 AF 86 80 00 00 00 00 00 00 D0 FE // ................ 43 | 0030: 00 00 00 00 00 EE 37 01 // ......7. 44 | -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-MCFG.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-MCFG.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-MCFG.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of MCFG.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [MCFG] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "MCFG" [Memory Mapped Configuration table] 14 | [004h 0004 4] Table Length : 0000003C 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 6E 17 | [00Ah 0010 6] Oem ID : "PTLTD " 18 | [010h 0016 8] Oem Table ID : "$PCITBL$" 19 | [018h 0024 4] Oem Revision : 06040000 20 | [01Ch 0028 4] Asl Compiler ID : " LTP" 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 8] Reserved : 0000000000000000 24 | 25 | [02Ch 0044 8] Base Address : 00000000F0000000 26 | [034h 0052 2] Segment Group Number : 0000 27 | [036h 0054 1] Start Bus Number : 00 28 | [037h 0055 1] End Bus Number : 7F 29 | [038h 0056 4] Reserved : 00000000 30 | 31 | Raw Table Data: Length 60 (0x3C) 32 | 33 | 0000: 4D 43 46 47 3C 00 00 00 01 6E 50 54 4C 54 44 20 // MCFG<....nPTLTD 34 | 0010: 24 50 43 49 54 42 4C 24 00 00 04 06 20 4C 54 50 // $PCITBL$.... LTP 35 | 0020: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 // ................ 36 | 0030: 00 00 00 00 00 00 00 7F 00 00 00 00 // ............ 37 | -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-SRAT.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware/vmware-SRAT.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-WAET.aml: -------------------------------------------------------------------------------- 1 | WAET(bVMWAREVMW WAETVMW  -------------------------------------------------------------------------------- /Tests/test_files/vmware/vmware-WAET.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20160108-64 4 | * Copyright (c) 2000 - 2016 Intel Corporation 5 | * 6 | * Disassembly of WAET.aml, Sat Apr 29 16:39:43 2017 7 | * 8 | * ACPI Data Table [WAET] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "WAET" [Windows ACPI Emulated Devices Table] 14 | [004h 0004 4] Table Length : 00000028 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 62 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW WAET" 19 | [018h 0024 4] Oem Revision : 06040000 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 4] Flags (decoded below) : 00000002 24 | RTC needs no INT ack : 0 25 | PM timer, one read only : 1 26 | 27 | Raw Table Data: Length 40 (0x28) 28 | 29 | 0000: 57 41 45 54 28 00 00 00 01 62 56 4D 57 41 52 45 // WAET(....bVMWARE 30 | 0010: 56 4D 57 20 57 41 45 54 00 00 04 06 56 4D 57 20 // VMW WAET....VMW 31 | 0020: 01 00 00 00 02 00 00 00 // ........ 32 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-apic.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-apic.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-dmar.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-dmar.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-dmar.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of dmar.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [DMAR] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "DMAR" [DMA Remapping table] 14 | [004h 0004 4] Table Length : 00000050 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : B5 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW DMAR" 19 | [018h 0024 4] Oem Revision : 06040001 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 1] Host Address Width : 2A 24 | [025h 0037 1] Flags : 01 25 | [026h 0038 10] Reserved : 00 00 00 00 00 00 00 00 00 00 26 | 27 | [030h 0048 2] Subtable Type : 0000 [Hardware Unit Definition] 28 | [032h 0050 2] Length : 0018 29 | 30 | [034h 0052 1] Flags : 01 31 | [035h 0053 1] Reserved : 00 32 | [036h 0054 2] PCI Segment Number : 0000 33 | [038h 0056 8] Register Base Address : 00000000FEC10000 34 | 35 | [040h 0064 1] Device Scope Type : 03 [IOAPIC Device] 36 | [041h 0065 1] Entry Length : 08 37 | [042h 0066 2] Reserved : 0000 38 | [044h 0068 1] Enumeration ID : 80 39 | [045h 0069 1] PCI Bus Number : 00 40 | 41 | [046h 0070 2] PCI Path : 00,07 42 | 43 | 44 | [048h 0072 2] Subtable Type : 0002 [Root Port ATS Capability] 45 | [04Ah 0074 2] Length : 0008 46 | 47 | [04Ch 0076 1] Flags : 01 48 | [04Dh 0077 1] Reserved : 00 49 | [04Eh 0078 2] PCI Segment Number : 0000 50 | 51 | Raw Table Data: Length 80 (0x50) 52 | 53 | 0000: 44 4D 41 52 50 00 00 00 01 B5 56 4D 57 41 52 45 // DMARP.....VMWARE 54 | 0010: 56 4D 57 20 44 4D 41 52 01 00 04 06 56 4D 57 20 // VMW DMAR....VMW 55 | 0020: 01 00 00 00 2A 01 00 00 00 00 00 00 00 00 00 00 // ....*........... 56 | 0030: 00 00 18 00 01 00 00 00 00 00 C1 FE 00 00 00 00 // ................ 57 | 0040: 03 08 00 00 80 00 00 07 02 00 08 00 01 00 00 00 // ................ 58 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-dsdt.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-dsdt.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-facp.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-facp.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-facs.aml: -------------------------------------------------------------------------------- 1 | FACS@ -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-facs.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of facs.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [FACS] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "FACS" 14 | [004h 0004 4] Length : 00000040 15 | [008h 0008 4] Hardware Signature : 00000000 16 | [00Ch 0012 4] 32 Firmware Waking Vector : 00000000 17 | [010h 0016 4] Global Lock : 00000000 18 | [014h 0020 4] Flags (decoded below) : 00000000 19 | S4BIOS Support Present : 0 20 | 64-bit Wake Supported (V2) : 0 21 | [018h 0024 8] 64 Firmware Waking Vector : 0000000000000000 22 | [020h 0032 1] Version : 00 23 | [021h 0033 3] Reserved : 000000 24 | [024h 0036 4] OspmFlags (decoded below) : 00000000 25 | 64-bit Wake Env Required (V2) : 0 26 | 27 | Raw Table Data: Length 64 (0x40) 28 | 29 | 0000: 46 41 43 53 40 00 00 00 00 00 00 00 00 00 00 00 // FACS@........... 30 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 31 | 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 32 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ 33 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-hpet.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-hpet.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-hpet.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of hpet.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [HPET] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "HPET" [High Precision Event Timer table] 14 | [004h 0004 4] Table Length : 00000038 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : B5 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW HPET" 19 | [018h 0024 4] Oem Revision : 00000000 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000000 22 | 23 | [024h 0036 4] Hardware Block ID : 8086AF01 24 | 25 | [028h 0040 12] Timer Block Register : [Generic Address Structure] 26 | [028h 0040 1] Space ID : 00 [SystemMemory] 27 | [029h 0041 1] Bit Width : 00 28 | [02Ah 0042 1] Bit Offset : 00 29 | [02Bh 0043 1] Encoded Access Width : 00 [Undefined/Legacy] 30 | [02Ch 0044 8] Address : 00000000FED00000 31 | 32 | [034h 0052 1] Sequence Number : 00 33 | [035h 0053 2] Minimum Clock Ticks : 37EE 34 | [037h 0055 1] Flags (decoded below) : 01 35 | 4K Page Protect : 1 36 | 64K Page Protect : 0 37 | 38 | Raw Table Data: Length 56 (0x38) 39 | 40 | 0000: 48 50 45 54 38 00 00 00 01 B5 56 4D 57 41 52 45 // HPET8.....VMWARE 41 | 0010: 56 4D 57 20 48 50 45 54 00 00 00 00 56 4D 57 20 // VMW HPET....VMW 42 | 0020: 00 00 00 00 01 AF 86 80 00 00 00 00 00 00 D0 FE // ................ 43 | 0030: 00 00 00 00 00 EE 37 01 // ......7. 44 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-mcfg.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-mcfg.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-mcfg.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of mcfg.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [MCFG] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "MCFG" [Memory Mapped Configuration table] 14 | [004h 0004 4] Table Length : 0000003C 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 6A 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "EFIMCFG " 19 | [018h 0024 4] Oem Revision : 06040001 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 000007CE 22 | 23 | [024h 0036 8] Reserved : 0000000000000000 24 | 25 | [02Ch 0044 8] Base Address : 00000000E0000000 26 | [034h 0052 2] Segment Group Number : 0000 27 | [036h 0054 1] Start Bus Number : 00 28 | [037h 0055 1] End Bus Number : 7F 29 | [038h 0056 4] Reserved : 00000000 30 | 31 | Raw Table Data: Length 60 (0x3C) 32 | 33 | 0000: 4D 43 46 47 3C 00 00 00 01 6A 56 4D 57 41 52 45 // MCFG<....jVMWARE 34 | 0010: 45 46 49 4D 43 46 47 20 01 00 04 06 56 4D 57 20 // EFIMCFG ....VMW 35 | 0020: CE 07 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 // ................ 36 | 0030: 00 00 00 00 00 00 00 7F 00 00 00 00 // ............ 37 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-srat.aml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/Tests/test_files/vmware11/vmware11-srat.aml -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-waet.aml: -------------------------------------------------------------------------------- 1 | WAET(aVMWAREVMW WAETVMW  -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-waet.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of waet.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [WAET] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "WAET" [Windows ACPI Emulated Devices Table] 14 | [004h 0004 4] Table Length : 00000028 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 61 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW WAET" 19 | [018h 0024 4] Oem Revision : 06040001 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 4] Flags (decoded below) : 00000002 24 | RTC needs no INT ack : 0 25 | PM timer, one read only : 1 26 | 27 | Raw Table Data: Length 40 (0x28) 28 | 29 | 0000: 57 41 45 54 28 00 00 00 01 61 56 4D 57 41 52 45 // WAET(....aVMWARE 30 | 0010: 56 4D 57 20 57 41 45 54 01 00 04 06 56 4D 57 20 // VMW WAET....VMW 31 | 0020: 01 00 00 00 02 00 00 00 // ........ 32 | -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-wsmt.aml: -------------------------------------------------------------------------------- 1 | WSMT((VMWAREVMW WSMTVMW  -------------------------------------------------------------------------------- /Tests/test_files/vmware11/vmware11-wsmt.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180105 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | * 6 | * Disassembly of wsmt.dat, Fri Jul 17 14:13:23 2020 7 | * 8 | * ACPI Data Table [WSMT] 9 | * 10 | * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue 11 | */ 12 | 13 | [000h 0000 4] Signature : "WSMT" [Windows SMM Security Migrations Table] 14 | [004h 0004 4] Table Length : 00000028 15 | [008h 0008 1] Revision : 01 16 | [009h 0009 1] Checksum : 28 17 | [00Ah 0010 6] Oem ID : "VMWARE" 18 | [010h 0016 8] Oem Table ID : "VMW WSMT" 19 | [018h 0024 4] Oem Revision : 06040001 20 | [01Ch 0028 4] Asl Compiler ID : "VMW " 21 | [020h 0032 4] Asl Compiler Revision : 00000001 22 | 23 | [024h 0036 4] Protection Flags : 00000007 24 | FIXED_COMM_BUFFERS : 1 25 | COMM_BUFFER_NESTED_PTR_PROTECTION : 1 26 | SYSTEM_RESOURCE_PROTECTION : 1 27 | 28 | Raw Table Data: Length 40 (0x28) 29 | 30 | 0000: 57 53 4D 54 28 00 00 00 01 28 56 4D 57 41 52 45 // WSMT(....(VMWARE 31 | 0010: 56 4D 57 20 57 53 4D 54 01 00 04 06 56 4D 57 20 // VMW WSMT....VMW 32 | 0020: 01 00 00 00 07 00 00 00 // ........ 33 | -------------------------------------------------------------------------------- /bochsrc: -------------------------------------------------------------------------------- 1 | ata0-master: type=disk, path="output/boot-hd.img", mode=flat, cylinders=20, heads=16, spt=63 2 | ata0-slave: type=cdrom, path="output/boot-cd.iso", status=inserted, biosdetect=auto 3 | #usb_uhci: enabled:1 port1=disk:output/boot-cd.iso 4 | boot: disk, cdrom 5 | vga: extension=cirrus 6 | vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus 7 | pci: enabled=1, chipset=i440fx, slot1=cirrus 8 | cpu: reset_on_triple_fault=0 9 | port_e9_hack: enabled=1 10 | magic_break: enabled=1 11 | cpuid: 1g_pages=1 12 | #log: bochs.out 13 | #debug: action=report 14 | #info: action=report 15 | -------------------------------------------------------------------------------- /boot/Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR := .. 2 | include $(TOPDIR)/Makedefs 3 | 4 | EFI_CFLAGS := $(CFLAGS) -fno-stack-protector -mno-red-zone -fpic -fshort-wchar -fno-unwind-tables -DEFI 5 | 6 | all: bootsector.bin isohdr.bin boot16to64.bin efi_header.bin efi_entry.o efi_main.o efi_elf.o kprintf.o 7 | 8 | 9 | boot16to64.bin: boot16to64.asm utils.asm a20.asm cpu_check.asm page_tables.asm pmode_loader.asm memory.asm 10 | $(NASM) $(NASM_FLAGS) -fbin -o $@ $< 11 | 12 | 13 | efi_main.o: efi_main.c 14 | $(CC) $(EFI_CFLAGS) -c -o $@ $< 15 | 16 | efi_elf.o: efi_elf.c 17 | $(CC) $(EFI_CFLAGS) -c -o $@ $< 18 | 19 | kprintf.o: ../klibc/kprintf.c 20 | $(CC) $(EFI_CFLAGS) -c -o $@ $< 21 | 22 | clean: 23 | rm -f *.bin *.o *.s *.so *.efi *.elf *.map 24 | -------------------------------------------------------------------------------- /boot/a20.asm: -------------------------------------------------------------------------------- 1 | ;;; boot/a20.asm 2 | ;;; 3 | ;;; Copyright © 2015 Simon Evans. All rights reserved. 4 | ;;; 5 | ;;; Enable the A20 gate using various methods. 6 | ;;; Starts with a check to see if its even needed 7 | 8 | FAST_A20_GATE EQU 0x92 9 | A20_TEST_COUNT EQU 5 10 | 11 | 12 | ;;; Enable the A20 using differnt methods, returns carry set if not enabled 13 | enable_a20: 14 | call check_a20 15 | jnc enabled_ok 16 | call enable_a20_bios 17 | call check_a20 18 | jnc enabled_ok 19 | call enable_a20_fast 20 | jnc enabled_ok 21 | call enable_a20_8042 22 | call check_a20 23 | enabled_ok: 24 | ret 25 | 26 | 27 | ;;; Enable the A20 using the BIOS if supported 28 | enable_a20_bios: 29 | mov ax, 0x2401 30 | int 0x15 31 | ret 32 | 33 | 34 | ;;; Enable the A20 using the 'Fast A20 Gate' if supported 35 | enable_a20_fast: 36 | in al, FAST_A20_GATE 37 | test al, 2 ; check if enabled 38 | jnz a20_fast_return ; already is, return 39 | or al, 2 ; set a20 enable 40 | and al, 0xFE ; Clear the reset bit 41 | out FAST_A20_GATE, al 42 | a20_fast_return: 43 | ret 44 | 45 | 46 | ;;; Enable the A20 using the keyboard controller 47 | enable_a20_8042: 48 | call empty_8042 49 | mov al, 0xD1 50 | out 0x64, al ; command write 51 | call empty_8042 52 | mov al, 0xDF 53 | out 0x60, al ; A20 on 54 | call empty_8042 55 | mov al, 0xff 56 | out 0x64, al ; extra for UHCI 57 | call empty_8042 58 | ret 59 | 60 | empty_8042: 61 | call io_delay 62 | in al, 0x64 ; read status 63 | test al, 1 ; output buffer? 64 | jne no_output ; no, check if input empty 65 | call io_delay ; yes, read and ignore 66 | in al, 0x60 67 | jmp empty_8042 68 | no_output: 69 | test al, 2 ; Buffer empty, all done 70 | jne empty_8042 71 | ret 72 | 73 | 74 | ;;; Test if A20 is opened, returns carry set on error 75 | check_a20: 76 | push ds 77 | push es 78 | xor ax, ax 79 | mov ds, ax 80 | mov ax, 0xffff 81 | mov es, ax 82 | mov ax, [0x1000] 83 | mov cx, A20_TEST_COUNT 84 | 85 | check_loop: 86 | ;; Test if DS:1000h (0x1000) == ES:1010h (0x101000 if enabled) 87 | call io_delay 88 | mov bx, [0x1000] ; read DS:1000 89 | cmp bx, [es:0x1010] ; read ES:1010 90 | jne a20_enabled ; not equal so A20 is enabled 91 | inc bx ; are equal so alter one 92 | mov [0x1000], bx 93 | cmp bx, [es:0x1010] 94 | jne a20_enabled ; not equal anymore so A20 is enabled 95 | dec cx 96 | jnz check_loop 97 | stc ; After multiple checks A20 still disabled 98 | jmp a20_return 99 | 100 | a20_enabled: 101 | clc 102 | 103 | a20_return: 104 | mov [0x1000], ax 105 | pop es 106 | pop ds 107 | ret 108 | -------------------------------------------------------------------------------- /boot/cpu_check.asm: -------------------------------------------------------------------------------- 1 | ;;; boot/cpu_check.asm 2 | ;;; 3 | ;;; Copyright © 2015 Simon Evans. All rights reserved. 4 | ;;; 5 | ;;; Check the CPU is sufficient for 64bit long mode 6 | 7 | FEATURE_BIT_LONG_MODE EQU 1 << 29 8 | 9 | ;;; Returns carry set if cpu not good enough 10 | cpu_check: 11 | ;; check CPUID supported by seeing if ID bit in EFLAGS can be toggled 12 | pushfd 13 | 14 | pushfd 15 | pop eax ; EAX = EFLAGS 16 | mov ecx, eax 17 | xor ecx, 0x00200000 ; toggle ID bit 18 | push ecx 19 | popfd ; load into flags 20 | pushfd ; store to see if change is preserved 21 | pop ecx ; ECX opposite bit to EAX if CPUID present 22 | popfd ; restore EFLAGS 23 | cmp ecx, eax 24 | jne has_cpuid 25 | mov si, msg_no_cpuid 26 | call print 27 | stc ; no CPUID 28 | ret 29 | 30 | has_cpuid: 31 | mov eax, 0x80000000 ; Get Highest Extended Function Supported 32 | cpuid 33 | cmp eax, 0x80000001 ; has Extended Processor Info and Feature Bits? 34 | jl bad_cpu 35 | mov eax, 0x80000001 36 | cpuid 37 | test edx, FEATURE_BIT_LONG_MODE 38 | jz bad_cpu 39 | clc ; All OK 40 | ret 41 | 42 | bad_cpu: 43 | mov si, msg_no_long_mode 44 | call print 45 | stc 46 | ret 47 | 48 | msg_no_cpuid: db "CPUID not present", 0x0A, 0x0D, 0 49 | msg_no_long_mode: db "Long mode not supported", 0x0A, 0x0D, 0 50 | -------------------------------------------------------------------------------- /boot/efi/efi.mk: -------------------------------------------------------------------------------- 1 | ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) 2 | 3 | OBJS = efi-test.o 4 | TARGET = efi-test.efi 5 | 6 | EFIINC = /usr/include/efi 7 | EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol 8 | LIB = /usr/lib 9 | EFILIB = /usr/lib 10 | EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o 11 | EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds 12 | 13 | CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \ 14 | -fshort-wchar -mno-red-zone -Wall -O2 -std=gnu11 15 | ifeq ($(ARCH),x86_64) 16 | CFLAGS += -DEFI_FUNCTION_WRAPPER 17 | endif 18 | 19 | LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \ 20 | -Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS) 21 | 22 | all: $(TARGET) 23 | 24 | efi-test.so: $(OBJS) 25 | ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi 26 | 27 | %.efi: %.so 28 | objcopy -j .text -j .sdata -j .data -j .dynamic \ 29 | -j .dynsym -j .rel -j .rela -j .reloc \ 30 | --target=efi-app-$(ARCH) $^ $@ 31 | 32 | clean: 33 | rm -f $(OBJS) $(TARGET) efi-test.so 34 | -------------------------------------------------------------------------------- /boot/efi_linker.script: -------------------------------------------------------------------------------- 1 | ENTRY(efi_entry) 2 | OUTPUT_FORMAT(binary) 3 | 4 | SECTIONS 5 | { 6 | .text.start (0x0000) : { 7 | *(.text .text.*) 8 | *(.rodata .rodata.*) 9 | *(.data .data.*) 10 | *(.bss .bss.*) 11 | . = ALIGN(16); 12 | output/kernel.elf.obj(.data) 13 | . = ALIGN(16); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /boot/isohdr.asm: -------------------------------------------------------------------------------- 1 | ;;; boot/isohdr.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 22/02/2016. 4 | ;;; Copyright © 2016 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; ISO header containing Apple Partition Map header to provide 7 | ;;; a file suitable for the xorrisofs `-isohybrid-mbr' option 8 | ;;; Currently doesnt work for booting if used on a USB image 9 | 10 | [MAP ALL isohdr.map] 11 | LOAD_SEG EQU 0x7c0 ; isohdr.bin loaded here 12 | 13 | ORG 0x0 14 | apm_mbr: db 0x33, 0xed ; Apple Partition Map header 15 | times 30 db 0x90 16 | 17 | jmp 0x07c0:start ; initialise CS 18 | 19 | start: 20 | cli 21 | cld 22 | xor ax, ax 23 | mov ss, ax 24 | mov sp, 0x2000 25 | sti 26 | mov ds, ax 27 | mov ax, 0x7a0 28 | mov es, ax 29 | 30 | ;; Relocate to 0x7A00:0000 so bootsector can be loaded to 31 | ;; normal position @ 0x7C00:0000 32 | mov si, 0x7c00 33 | xor di, di 34 | mov cx, 0x100 35 | rep movsw 36 | jmp 0x7a0:here 37 | here: 38 | mov ax, es 39 | mov ds, ax 40 | 41 | mov [boot_dev], dl 42 | mov ax, [lba_offset] 43 | mov [dap_lba], ax 44 | mov ax, [lba_offset + 2] 45 | mov [dap_lba + 2], ax 46 | 47 | ;; Read in bootsector.bin and boot16to64.bin 48 | mov ah, 0x42 ; Extended read sectors 49 | mov dl, [boot_dev] 50 | mov si, dap 51 | int 0x13 52 | jc boot_failure 53 | mov si, msg_ok 54 | call print 55 | jmp LOAD_SEG:0 ; Execute boot16to64 56 | 57 | boot_failure: 58 | ;; Boot failure, print message then reboot 59 | mov si, msg_fail 60 | call print 61 | ;; wait for keypress 62 | xor ax, ax 63 | int 0x16 64 | int 0x19 65 | jmp 0xf000:0xfff0 ; if int 19 fails 66 | 67 | 68 | %include "utils.asm" ; for print_string 69 | 70 | msg_ok: db "Loaded OK", 0x0A, 0x0D, 0 71 | msg_fail: db "Load failed. Press any key to reboot", 0x0A, 0x0D, 0 72 | 73 | ;;; Bootsector padding, disk image info and signature 74 | ;;; The offset 480 is used by an external program to 75 | ;;; patch in the secondary loader and kernel image LBA/sector 76 | ;;; counts so must always reside at this locatio 77 | OFFSET 400 78 | 79 | ;;; DAP (Disk Address Packet) used for LBA BIOS interface 80 | dap: db 16 ; DAP size 81 | db 0 ; always 0 82 | dap_count: dw 4 83 | dap_offset: dw 0 ; Code is loaded to LOAD_SEG:0000 84 | dap_segment: dw LOAD_SEG 85 | dap_lba: dq 0 ; 64bit LBA address 86 | 87 | sector_lba: dq 0 88 | boot_dev: db 0 ; BIOS disk number 89 | 90 | OFFSET 432 91 | lba_offset: dd 0 ; Patched in by xorrisofs 92 | -------------------------------------------------------------------------------- /boot/memory.asm: -------------------------------------------------------------------------------- 1 | ;;; boot/memory.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 24/12/2015. 4 | ;;; Copyright © 2015 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; Obtain the memory map from the BIOS 7 | ;;; Store a struct bios_boot_params @ 3000:0000 followed by the E820 map 8 | 9 | MAX_SMAP_ENTRIES EQU 200 10 | E820_SIGNATURE EQU "PAMS" ; "SMAP" in LE format 11 | 12 | get_memory: 13 | push es 14 | mov di, 0x3000 15 | mov es, di 16 | ;; clear a page @ 3000:0000 17 | cld 18 | xor edi, edi 19 | xor eax, eax 20 | mov ecx, 0x400 21 | rep stosd 22 | ;; struct bios_boot_params setup 23 | 24 | mov dword [es:00], 'BIOS' ; .signature 25 | mov dword [es:08], 0 ; .size (of table) 26 | mov dword [es:16], KERNEL_LOAD_ADDR ; physical address of kernel 27 | mov dword [es:24], 0x30028 ; .e820_map lo dword 28 | mov dword [es:28], 0x0 ; .e820_map hi dword @ 0x030020 PhysAddr 29 | mov edi, 40 ; offset to e832 data 30 | xor ebx, ebx 31 | 32 | .next_entry: 33 | mov eax, 0xe820 34 | mov ecx, 20 35 | mov edx, E820_SIGNATURE 36 | int 0x15 37 | jc .finished 38 | cmp eax, E820_SIGNATURE 39 | jne .finished 40 | inc dword [es:32] ; .e820_entries++ 41 | add edi, 20 42 | cmp ebx, 0 43 | je .finished 44 | cmp dword [es:32], MAX_SMAP_ENTRIES 45 | jl .next_entry 46 | 47 | .finished: 48 | mov [es:08], edi ; .size (of table) 49 | pop es 50 | ret 51 | -------------------------------------------------------------------------------- /boot/utils.asm: -------------------------------------------------------------------------------- 1 | ;;; boot/utils.asm 2 | ;;; 3 | ;;; Copyright © 2015 Simon Evans. All rights reserved. 4 | 5 | ;;; print_string - print ASCIIZ string in DS:SI via BIOS 6 | print: 7 | lodsb 8 | test al, al 9 | je print_return 10 | mov ah, 0x0E 11 | int 0x10 12 | jmp print 13 | 14 | print_return: 15 | ret 16 | 17 | 18 | ;;; Simple IO delay by writing to an unused I/O port 19 | io_delay: 20 | out 0x80, al 21 | ret 22 | -------------------------------------------------------------------------------- /debugtools/SwiftString.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | 4 | class SwiftString: 5 | def __init__(self, hi_word, lo_word): 6 | self.hi_word = hi_word 7 | self.lo_word = lo_word 8 | 9 | 10 | def is_small(self): 11 | return (self.hi_word & (1 << 61) != 0) 12 | 13 | 14 | def is_large(self): 15 | return not self.is_small() 16 | 17 | 18 | def is_immortal(self): 19 | return (self.hi_word & (1 << 63) == 0) 20 | 21 | 22 | def is_mortal(self): 23 | return not self.is_immortal() 24 | 25 | 26 | def is_ascii(self): 27 | if self.is_small(): 28 | return (self.hi_word & (1 << 62) != 0) 29 | else: 30 | return (self.lo_word & (1 << 63) != 0) 31 | 32 | 33 | def count(self): 34 | if self.is_small(): 35 | return (self.hi_word >> 56) & 0xf 36 | else: 37 | return (self.lo_word & 0x0000ffffffffffff) 38 | 39 | 40 | def is_nfc(self): 41 | if self.is_small(): 42 | return None 43 | else: 44 | return (self.lo_word & (1 << 62) != 0) 45 | 46 | 47 | def is_natively_stored(self): 48 | if self.is_small(): 49 | return None 50 | else: 51 | return (self.lo_word & (1 << 61) != 0) 52 | 53 | 54 | def is_tail_allocated(self): 55 | if self.is_small(): 56 | return None 57 | else: 58 | return (self.lo_word & (1 << 60) != 0) 59 | 60 | 61 | def is_foreign(self): 62 | return (self.hi_word & (1 << 60) != 0) 63 | 64 | 65 | def is_bridged(self): 66 | return self.is_large() and ((self.hi_word & 1 << 62) != 0) 67 | 68 | 69 | def objectaddress(self): 70 | if self.is_large(): 71 | return self.hi_word & 0x00ffffffffffffffff 72 | else: 73 | return None 74 | 75 | 76 | def byte_buffer(self): 77 | if self.is_small(): 78 | buffer = [] 79 | for i in range(0, 8): 80 | byte = (self.lo_word >> (i * 8)) & 0xff 81 | buffer.append(byte) 82 | 83 | for i in range(0, 7): 84 | byte = (self.hi_word >> (i * 8)) & 0xff 85 | buffer.append(byte) 86 | 87 | return buffer 88 | else: 89 | return None 90 | 91 | 92 | def dump(self): 93 | print("HI: 0x%016x LO: 0x%016x" % (self.hi_word, self.lo_word)) 94 | if self.is_small(): 95 | print("Small String") 96 | else: 97 | print("Large String") 98 | 99 | print("Immortal: %s" % self.is_immortal()) 100 | print("ASCII: %s" % self.is_ascii()) 101 | print("Count: %d" % self.count()) 102 | 103 | if self.is_small(): 104 | buffer = self.byte_buffer() 105 | print("Bytes: [%s]" % ', '.join(map(str, buffer))) 106 | print("String: '%s'" % ''.join(map(chr, buffer))) 107 | else: 108 | print("NFC: %s" % self.is_nfc()) 109 | print("Foreign: %s" % self.is_foreign()) 110 | print("Address: %016x" % self.objectaddress()) 111 | -------------------------------------------------------------------------------- /doc/boot-readme.md: -------------------------------------------------------------------------------- 1 | qemu-system-x86_64 -m 16G -cdrom output/boot-cd.iso 2 | qemu-system-x86_64 -M q35 -hda output/boot-hd.img 3 | qemu-system-x86_64 -bios bios.bin -m 16G -cdrom output/boot-cd.iso 4 | qemu-system-x86_64 -m 16G -usbdevice disk:output/boot-cd.iso 5 | -------------------------------------------------------------------------------- /doc/index.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | swift-project1 - writing a simple bare metal kernel in Swift 4 | 5 | A project to write a kernel in Swift with that can boot on a Mac or PC. 6 | The eventual aim is to get a simple kernel booting up with a CLI and some 7 | device drivers, to investigate using Swift for systems programming. 8 | 9 | 10 | [project1 on github](https://github.com/spevans/swift-project1) 11 | 12 | 13 | The main aspects being investigated are: 14 | 15 | 16 | ## [Target Host](target-host.md) 17 | - 64bit x86_64, Qemu, Bochs, VMware and Macbooks 18 | 19 | 20 | ## [Development environment and compiler](development.md) 21 | - Additions to the swift compiler: Red zone and kernel address space 22 | - Using the compiler 23 | - Libraries 24 | - Swift modules 25 | 26 | 27 | ## [Standard library and runtime](kstdlib.md) 28 | - Floating point and Maths functions 29 | - Stdio and print() 30 | - klibc 31 | - Unicode and libICU (TODO) 32 | 33 | 34 | ## [Initialisation](initialisation.md) 35 | - From boot to swift startup() 36 | - globalinit*() (TODO) 37 | - malloc() and free() (TODO) 38 | - Thread Local Storage (TLS) 39 | - Streaming SIMD Extensions (SSE) 40 | - Reading data tables in swift 41 | 42 | 43 | ## [Working with C](working-with-c.md) 44 | - Swift calling convention 45 | - Pointers 46 | - Swift function names 47 | - Defines and constants 48 | - Structs 49 | - Arrays 50 | - StaticString 51 | 52 | 53 | ## [Other Notes](other-notes.md) 54 | - Will it build on OSX? 55 | - Future directions 56 | 57 | 58 | [TODO] 59 | ## Unsafe Swift 60 | - When to use C or Assembly (interrupts, GDT, IDT) 61 | - unsafeBitCast 62 | 63 | 64 | ## [Useful links](useful-links.md) 65 | -------------------------------------------------------------------------------- /doc/other-notes.md: -------------------------------------------------------------------------------- 1 | # Other Notes 2 | 3 | 4 | ## Will it build on OSX? 5 | 6 | Currently it will not build on OSX. Originally development was started on OSX 7 | against the `libswiftCore.dylib` shipped with the latest Xcode including writing 8 | a static linker to link the .dylib with the stub C functions to produce a 9 | binary. This was working however stubs for the Objective-C functions were 10 | required. Then Swift went open source and since the linux library is not 11 | compiled with Objective-C support it removed a whole slew of functions and 12 | symbols that would need to be supported. 13 | 14 | The linux version also has the advantage that it builds a more efficient binary 15 | since it is using proper ELF files and the standard ld linker. The static linker 16 | just dumped the .dylib and relocates it in place but it suffered from the 17 | fact that ZEROFILL sections have to be stored as blocks of zeros in the binary 18 | and there is no optimisation of cstring sections etc. Also, changes in the 19 | latest .dylib built from the Swift repo seem to add some new Mach-Oheader flags 20 | which would require more support. It may be possible to build against the 21 | static stdlib on OSX but at the moment its not that interesting to do. As of now 22 | support for building on OSX has been removed. 23 | 24 | 25 | ## Future directions 26 | 27 | The next few things to investigate if time permits are: 28 | 29 | 30 | ### 1. Linking directly with stdlib 31 | 32 | To reduce the number of unused stub functions needed by stdlib it might be worth 33 | trying to compile directly with the stdlib .swift files rather than linking to 34 | the `libSwiftcore.a` library. This should also give better chances for 35 | optimisation using `-whole-module-optimization` although compile times would be 36 | increased. However this would require more understanding of the Swift build 37 | system. 38 | 39 | 40 | ### 2. Implementing on 64Bit ARM 41 | 42 | ARM is another major architecture supported by Swift which was initially avoided 43 | as I have more experience with x86. Getting the kernel working on a simple ARM 44 | system such as a Raspberry Pi Zero (or a 64bit ARM board) would help avoid 45 | hardcoding too many 64bit x86_64 assumptions into the current code. However 46 | this would require a version of the compiler that can cross compile and QEMU 47 | or equivalent that can emulate the specifc ARM board for initial testing. 48 | 49 | Another advantage of porting to ARM is that the hardware should be simpler as 50 | unlike the PC there should not be any legacy hardware to support. Another is not 51 | requiring ACPI (although it has been partially implemented now so is not such a 52 | problem). 53 | -------------------------------------------------------------------------------- /doc/outline.md: -------------------------------------------------------------------------------- 1 | * Abstract 2 | 3 | 4 | *** Target Host (x86_64) qemu/bochs macbook, EFI/bios, ELF/Macho 5 | 6 | 7 | * Writing for PC, EFI v BIOS 8 | 9 | * bochs, qemu etc 10 | 11 | * why only linux, ELF v Mach-o 12 | 13 | *** Compiler changes + Runtime 14 | 15 | 16 | * Redzone, compiler patch, kernel negative space, change for pointer high bit 17 | * Using the compiler 18 | 19 | * Stuff Removed from the runtime, Float, Random numbers, Ascii/unicode (hacks for Hashable to run with collation), builtin maths, sin/cos etc, disable backtrace, libdl, compiling the runtime with the compiler changes , swift-compiler-rt (libclang_rt.builtins-x86_64.a) for libatomic 20 | 21 | * swift-kstdlib (Stdlib) 22 | * Remove libswiftOnoneSupport (no -Onone) , Outputstream (less use of stdio an no need to redirect) 23 | 24 | * klibc to support the runtime, list of symbols.txt. main areas of support: 25 | - heap (malloc/free, no realloc) new/delete 26 | - mem/str functions 27 | - fprintf/fwrite (note about optimization of fprintf->fwrite) write() 28 | - __cxa* 29 | - pthread* 30 | - std::__throw (just panic) 31 | - std::__cx11:basic_string 32 | 33 | - Implement own printf and early tty for text/frame buffer (incl serial port) 34 | 35 | - C/asm required for start up 36 | 37 | 38 | **** Initialisation 39 | 40 | - From boot to swift startup() 41 | - globalinit*() 42 | - malloc() and free() 43 | - Thread Local Storage (TLS) 44 | - Streaming SIMD Extensions (SSE), floating point 45 | 46 | *** Working With C 47 | - Swift calling convention 48 | - Pointers 49 | - Swift function names 50 | - Defines and constants 51 | - Structs 52 | - Arrays 53 | - StaticString 54 | 55 | - When C is required for Swift (structs/unions/constants) 56 | 57 | 58 | *** Unsafe Swift 59 | - When to use C or Assembly (interrupts, GDT, IDT) (lack of struct layout in swift) 60 | - unsafeBitCast 61 | 62 | 63 | 64 | 65 | 66 | 67 | * Using modules v One big module 68 | 69 | * Functions that need to exist (malloc) before required for swift var/let init 70 | 71 | * C Usage: 72 | - inline for asm 73 | - structs in C, alignment/packing 74 | - UInt for addresses, exporting symboes from C to swift via _addr() fuctions 75 | - Use struct in C to convert to struct in swift 76 | - -Xcc -I 77 | - ULL, UL, L -> UInt64, UInt etc 78 | - ptrToint 79 | - @_silgen_name 80 | 81 | 82 | * Other 83 | - @noreturn breaks compiler 84 | - lack of bitfields 85 | - strideof() v sizeof() 86 | - varargs and malloc/realloc/malloc_usable_size 87 | - print(x,y,z) v print("\(x) \(y) \(z)" 88 | - lack of struct packing / C structs with alignment and bit fields 89 | - Foundation quite broken on linux 90 | - lack of offset() 91 | - StaticString 92 | - non-use of realloc() 93 | - fixed arrays V tuples 94 | - lots of alloc() eg in throw 95 | - Removing parts from the standard library 96 | - throw v nil 97 | 98 | * performance issues 99 | - assignFrom() doesnt do memcpy() 100 | - rdtsc() uint64_t held in 2 registers 101 | 102 | -------------------------------------------------------------------------------- /doc/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/doc/screenshot-2.png -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/doc/screenshot.png -------------------------------------------------------------------------------- /doc/swift-kernel-layers.001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/doc/swift-kernel-layers.001.png -------------------------------------------------------------------------------- /doc/swift-kernel-layers.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/doc/swift-kernel-layers.key -------------------------------------------------------------------------------- /doc/target-host.md: -------------------------------------------------------------------------------- 1 | # Target host and test environment 2 | 3 | I decided to target x86_64 64bit Longmode as when I started I wasnt sure if the 4 | swift compiler correctly targeted 32bit. Recently I read that 32bit is fine for 5 | non Apple hosts, the restriction is that the 32bit Objective-C runtime on Darwin 6 | is the problem. I had thought about targeting Arm64 on something like a 7 | Raspberry Pi but am more familiar with x86 so that made for a faster start. 8 | 9 | 10 | QEMU, Bochs and VMware Fusion are used for testing inside VMs. A MacBook 3,1 11 | is used for testing on actual hardware. 12 | 13 | [QEMU](http://wiki.qemu.org/Main_Page) has a wide range of startup options and 14 | makes it easy to test booting from both a hard drive image and a CDROM ISO. It 15 | also provides a lot of CPU state in the logs when a fault occurs. 16 | It was also useful for developing the EFI booting using the 17 | [OVMF](https://wiki.ubuntu.com/UEFI/OVMF) firmware. 18 | 19 | Although QEMU supports GDB for debugging I never really got it to work easily as 20 | I found the breakpoints often seemed to breakpoint into QEMU rather than the 21 | code running inside it. However the simple startup and ability to boot it either 22 | from a hard disk image file to test BIOS booting or an ISO image file containing 23 | an EFI image made it a good choice for EFI testing. It also allows output over 24 | a virtual serial port to go straight to stdio which allows for having a large 25 | console log which helps when the text mode is only 25 lines and has no 26 | scrollback. 27 | 28 | [Bochs](http://bochs.sourceforge.net) was the primary VM used for testing and 29 | debugging the BIOS chain loader, switching to Long mode and Swift kernel 30 | startup. Its builtin debugger is pretty good and made examination of the CPU 31 | state very easy. Its ability to walk the page tables made it useful for testing 32 | page table setup. The only downside of Bochs is that it is quite slow if left to 33 | run the code (slower than QEMU), however this is not a major issue when testing. 34 | The ability to step through and debug the CPU state and the code made Bochs the 35 | best VM to use for debugging booting and startup. 36 | 37 | The only downside of Bochs was that it cannot run the OVMF firmware so couldn't 38 | be used for EFI debugging. This wasn't a major downside since the kernel startup 39 | was already working and the EFI statrtup just required from printf() debugging. 40 | 41 | VMWare provides the best level of emulation but crashes are restricted to a log 42 | file entry with one line describing what happened to the CPU. In the case of a 43 | triple fault which causes a CPU reset the information on the screen is lost. 44 | However once the code was more complete and exception handlers had been added it 45 | is a good way to check the device drivers, PCI and ACPI parsing was stable as the 46 | hardware emulation is the most advanced of the 3 VMs. 47 | 48 | MacBook 3,1 and MacBookPro 11,1. These were the only two test machines available 49 | and were the reason to get EFI booting working as they do not have a PC BIOS. 50 | The MacBook was running Linux and GRUB so just required adding the `kernel.efi` 51 | file to GRUB and booted from there. The MacBookPro was booted off of a USB 52 | drive which had `boot-cd.iso` written to it. These both booted without issues 53 | except for the lack of keyboard - Macs dont support the i8042 PS/2 controller, 54 | the builtin keyboards are USB devices and no emulation is provided by the 55 | firmaware. 56 | 57 | -------------------------------------------------------------------------------- /doc/useful-links.md: -------------------------------------------------------------------------------- 1 | 2 | # Useful links 3 | 4 | ## x86_64 topics 5 | 6 | [Intel® 64 and IA-32 Architectures Developer's Manual](http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf) 7 | 8 | [Porting Linux to x86-64](https://www.kernel.org/doc/ols/2001/x86-64.pdf) 9 | 10 | [ELF Handling For Thread-Local Storage](https://uclibc.org/docs/tls.pdf) 11 | 12 | [System V Application Binary Interface, AMD64 Architecture Processor Supplement](http://www.x86-64.org/documentation/abi.pdf) 13 | 14 | 15 | ## File object formats 16 | 17 | [Executable and Linkable Format (ELF)](http://www.skyfree.org/linux/references/ELF_Format.pdf) 18 | 19 | [Mach-O Programming Topics](http://www.cs.miami.edu/~burt/learning/Csc521.091/docs/MachOTopics.pdf) 20 | 21 | [Microsoft Portable Executable and Common Object File Format Specification](http://www.singlix.com/trdos/runix/OSDev_Wiki/pecoff_v83.pdf) 22 | 23 | 24 | ## PC booting and firmware 25 | 26 | [UEFI Specification 2.6](http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf) 27 | 28 | [Extensible Firmware Interface Specification v1.10](http://www.intel.com/content/dam/doc/product-specification/efi-v1-10-specification.pdf) 29 | 30 | [El Torito" Bootable CD-ROM Format Specification](http://download.intel.com/support/motherboards/desktop/sb/specscdrom.pdf) 31 | 32 | [The Linux EFI Boot Stub](http://firmware.intel.com/blog/linux-efi-boot-stub) 33 | 34 | [Programming for EFI: Creating a "Hello, World" Program](http://www.rodsbooks.com/efi-programming/hello.html) 35 | 36 | [UEFI Programming - First Steps](http://x86asm.net/articles/uefi-programming-first-steps/index.html) 37 | 38 | [ISOLinux](http://www.syslinux.org/wiki/index.php?title=ISOLINUX) 39 | 40 | 41 | ## ACPI and other PC firmware tables 42 | 43 | [Advanced Configuration and Power Interface Specification](http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf) 44 | 45 | [System Management BIOS (SMBIOS) Reference 6 Specification](http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.8.0.pdf) 46 | 47 | [ACPI Specification v0.91](http://www.intel.com/content/dam/doc/technology-brief/acpi-specification-v091.pdf) 48 | 49 | [ACPI Table Storage Specification v0.91](http://www.intel.com/content/dam/doc/technology-brief/acpi-table-storage-specification-v091.pdf) 50 | 51 | [ACPI - Advanced Configuration and Power Interface​](http://www.acpi.info) 52 | 53 | [Unified Extensible Firmware Interface Forum](http://www.uefi.org) 54 | 55 | 56 | ## PC Hardware 57 | 58 | [PCI Express Base Specification Revision 3](http://www.composter.com.ua/documents/PCI_Express_Base_Specification_Revision_3.0.pdf) 59 | 60 | [Enhanced Host Controller Interface for USB 2.0: Specification](http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/ehci-specification-for-usb.pdf) 61 | 62 | [OSDev.org](http://wiki.osdev.org/Main_Page) 63 | -------------------------------------------------------------------------------- /gdb-cmds: -------------------------------------------------------------------------------- 1 | set step-mode on 2 | set disassemble-next-line on 3 | display/i $pc 4 | set architecture i386:x86-64 5 | set disassembly-flavor intel 6 | 7 | define trem 8 | target remote localhost:1234 9 | end 10 | 11 | set substitute-path /home/spse/swift-kernel-lib /Users/spse/Files/src/swift-kernel-lib 12 | set substitute-path /home/spse/src/project1 /Users/spse/Files/src/project1 13 | file output/kernel.elf 14 | break abort 15 | break debugger_hook 16 | -------------------------------------------------------------------------------- /gdb-cmds-bochs: -------------------------------------------------------------------------------- 1 | set kaslr-memory-search 0 2 | handle SIGUSR1 noprint 3 | target remote tcp::1234 4 | br *0x10000 5 | continue 6 | set architecture i386:x86-64 7 | -------------------------------------------------------------------------------- /include/efi/uga.h: -------------------------------------------------------------------------------- 1 | #ifndef __EFI_UGA_H__ 2 | #define __EFI_UGA_H__ 3 | 4 | #define EFI_UGA_PROTOCOL_GUID \ 5 | { 0x982c298b, 0xf4fa, 0x41cb, { 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 }} 6 | 7 | #define EFI_UGA_IO_PROTOCOL_GUID \ 8 | { 0x61a4d49e, 0x6f68, 0x4f1b, { 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 }} 9 | 10 | 11 | struct _efi_uga_draw_protocol; 12 | 13 | typedef efi_status_t 14 | (*efi_uga_draw_protocol_get_mode_t)(struct _efi_uga_draw_protocol *this, 15 | uint32_t *horizontal_resolution, 16 | uint32_t *vertical_resolution, 17 | uint32_t *color_depth, 18 | uint32_t *refresh_rate); 19 | 20 | typedef efi_status_t 21 | (*efi_uga_draw_protocol_set_mode_t)(struct _efi_uga_draw_protocol *this, 22 | uint32_t horizontal_resolution, 23 | uint32_t vertical_resolution, 24 | uint32_t color_depth, 25 | uint32_t refresh_rate); 26 | 27 | typedef struct { 28 | uint8_t blue; 29 | uint8_t green; 30 | uint8_t red; 31 | uint8_t reserved; 32 | } efi_uga_pixel_t; 33 | 34 | 35 | typedef enum { 36 | efi_uga_video_fill, 37 | efi_uga_video_to_blt_buffer, 38 | efi_uga_blt_buffer_to_video, 39 | efi_uga_video_to_video, 40 | efi_uga_blt_max 41 | } efi_uga_blt_operation_t; 42 | 43 | typedef efi_status_t 44 | (*efi_uga_draw_protocol_blt_t) (struct _efi_uga_draw_protocol *this, 45 | efi_uga_pixel_t *blt_buffer, 46 | efi_uga_blt_operation_t blt_operation, 47 | efi_uintn source_x, 48 | efi_uintn source_y, 49 | efi_uintn destination_X, 50 | efi_uintn destination_y, 51 | efi_uintn width, 52 | efi_uintn height, 53 | efi_uintn delta); 54 | 55 | 56 | typedef struct _efi_uga_draw_protocol { 57 | efi_uga_draw_protocol_get_mode_t get_mode; 58 | efi_uga_draw_protocol_set_mode_t SetMode; 59 | efi_uga_draw_protocol_blt_t Blt; 60 | } efi_uga_draw_protocol_t; 61 | 62 | #endif // __EFI_UGA_H__ 63 | -------------------------------------------------------------------------------- /include/fbcon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * include/fbcon.h 3 | * 4 | * Created by Simon Evans on 06/02/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Definition for graphical frambuffer and font 8 | * 9 | */ 10 | 11 | #ifndef __FBCON_H__ 12 | #define __FBCON_H__ 13 | 14 | #include 15 | 16 | 17 | struct frame_buffer { 18 | void *address; 19 | uint64_t size; 20 | uint32_t width; 21 | uint32_t height; 22 | uint32_t px_per_scanline; 23 | uint32_t depth; 24 | uint8_t red_shift; 25 | uint8_t red_mask; 26 | uint8_t green_shift; 27 | uint8_t green_mask; 28 | uint8_t blue_shift; 29 | uint8_t blue_mask; 30 | } __attribute__((packed)); 31 | 32 | struct font { 33 | uint8_t width; 34 | uint8_t height; 35 | const unsigned char *data; 36 | }; 37 | 38 | #endif // __FBCON_H__ 39 | -------------------------------------------------------------------------------- /include/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * include/io.h 3 | * 4 | * Created by Simon Evans on 18/04/2021. 5 | * Copyright © 2021 Simon Evans. All rights reserved. 6 | * 7 | * Functions to deal with MMIO where memory operations should 8 | * not be reordered by the compiler. 9 | */ 10 | 11 | 12 | #ifndef __IO_H__ 13 | #define __IO_H__ 14 | 15 | #include 16 | 17 | // Stop the compiler from reording memory access. 18 | #define barrier() __asm__ __volatile__("": : :"memory") 19 | 20 | 21 | static inline uint8_t 22 | mmio_read_uint8(const volatile void *address) { 23 | barrier(); 24 | uint8_t value = *(const volatile uint8_t *)address; 25 | barrier(); 26 | return value; 27 | } 28 | 29 | static inline void 30 | mmio_write_uint8(volatile void *address, uint8_t value) { 31 | barrier(); 32 | *(volatile uint8_t *)address = value; 33 | barrier(); 34 | } 35 | 36 | static inline uint16_t 37 | mmio_read_uint16(const volatile void *address) { 38 | barrier(); 39 | uint16_t value = *(const volatile uint16_t *)address; 40 | barrier(); 41 | return value; 42 | } 43 | 44 | static inline void 45 | mmio_write_uint16(volatile void *address, uint16_t value) { 46 | barrier(); 47 | *(volatile uint16_t *)address = value; 48 | barrier(); 49 | } 50 | 51 | static inline uint32_t 52 | mmio_read_uint32(const volatile void *address) { 53 | barrier(); 54 | uint32_t value = *(const volatile uint32_t *)address; 55 | barrier(); 56 | return value; 57 | } 58 | 59 | static inline void 60 | mmio_write_uint32(volatile void *address, uint32_t value) { 61 | barrier(); 62 | *(volatile uint32_t *)address = value; 63 | barrier(); 64 | } 65 | 66 | static inline uint64_t 67 | mmio_read_uint64(const volatile void *address) { 68 | barrier(); 69 | uint64_t value = *(const volatile uint64_t *)address; 70 | barrier(); 71 | return value; 72 | } 73 | 74 | static inline void 75 | mmio_write_uint64(volatile void *address, uint64_t value) { 76 | barrier(); 77 | *(volatile uint64_t *)address = value; 78 | barrier(); 79 | } 80 | 81 | 82 | static inline void 83 | memoryBarrier() { 84 | asm volatile("mfence" : : : "memory"); 85 | } 86 | 87 | static inline void 88 | readMemoryBarrier() { 89 | asm volatile("lfence" : : : "memory"); 90 | } 91 | 92 | static inline void 93 | writeMemoryBarrier() { 94 | asm volatile("sfence" : : : "memory"); 95 | } 96 | 97 | 98 | #endif // __IO_H__ 99 | -------------------------------------------------------------------------------- /include/klibc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/klibc.h 3 | * 4 | * Created by Simon Evans on 12/12/2015. 5 | * Copyright © 2015 - 2018 Simon Evans. All rights reserved. 6 | * 7 | * Miscellaneous functions mostly string/memory 8 | * 9 | */ 10 | 11 | #ifndef __KLIBC_H__ 12 | #define __KLIBC_H__ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "x86funcs.h" 20 | #include "mm.h" 21 | 22 | #ifndef TEST 23 | #include "efi.h" 24 | typedef int64_t ssize_t; 25 | #endif 26 | 27 | #define UNIMPLEMENTED(x) void x() { koops("UNIMPLEMENTED: %s", __func__); } 28 | #define likely(x) __builtin_expect(!!(x), 1) 29 | #define unlikely(x) __builtin_expect(!!(x), 0) 30 | 31 | #if DEBUG 32 | #define debugf(...) do { \ 33 | serial_printf("debug: %p: ", __builtin_return_address(0)); \ 34 | serial_printf(__VA_ARGS__); \ 35 | } while(0) 36 | 37 | #else 38 | #define debugf(...) do {} while(0) 39 | #endif 40 | 41 | #ifndef TEST 42 | // kprintf 43 | int kvsnprintf(char * _Nonnull buf, size_t size, const char * _Nonnull fmt, va_list args) __attribute__ ((format (printf, 3, 0))); 44 | int kvlprintf(const char * _Nonnull fmt, size_t len, va_list args); 45 | int kvprintf(const char * _Nonnull fmt, va_list args) __attribute__ ((format (printf, 1, 0))); 46 | int kprintf(const char * _Nonnull fmt, ...) __attribute__ ((format (printf, 1, 2))); 47 | int kprintf1arg(const char * _Nonnull fmt, long l1); 48 | int kprintf2args(const char * _Nonnull fmt, long l1, long l2); 49 | int kprintf3args(const char * _Nonnull fmt, long l1, long l2, long l3); 50 | #endif 51 | 52 | // klibc 53 | void abort(void); 54 | void debugger_hook(void); 55 | #ifndef TEST 56 | void koops(const char * _Nonnull fmt, ...) __attribute__ ((format (printf, 1, 2))) __attribute__((noreturn)); 57 | #endif 58 | void stack_trace(uintptr_t rsp, uintptr_t rbp); 59 | unsigned int read_int_nest_count(void); 60 | int memcmp(const void * _Nonnull s1, const void * _Nonnull s2, size_t count); 61 | void * _Nonnull memcpy(void * _Nonnull dest, const void * _Nonnull src, size_t count); 62 | void * _Nonnull memset(void * _Nonnull dest, int c, size_t count); 63 | void * _Nonnull memsetw(void * _Nonnull dest, uint16_t w, size_t count); 64 | int strcmp(const char * _Nonnull s1, const char * _Nonnull s2); 65 | char * _Nonnull strcpy(char * _Nonnull dest, const char * _Nonnull src); 66 | size_t strlen(const char * _Nonnull s); 67 | 68 | // early_tty.c 69 | typedef uint16_t text_coord; 70 | 71 | void kprint(const char * _Nonnull string); 72 | void serial_print_char(const char ch); 73 | void early_print_char(const char c); 74 | void early_print_string(const char * _Nonnull text); 75 | void early_print_string_len(const char * _Nonnull text, size_t len); 76 | int serial_printf(const char * _Nonnull fmt, ...) __attribute__ ((format (printf, 1, 2))); 77 | 78 | #endif // __KLIBC_H__ 79 | -------------------------------------------------------------------------------- /include/macros.asm: -------------------------------------------------------------------------------- 1 | %macro OFFSET 1 2 | times %1 - ($ - $$) db 0 3 | %endmacro 4 | 5 | 6 | KERNEL_VIRTUAL_BASE EQU 0xffffffff81000000 ; 2^64 - 2GB + 16MB 7 | PHYSICAL_MEM_BASE EQU 0xffff800000000000 ; 128TB 8 | 9 | CODE_SEG EQU 0x8 10 | DATA_SEG EQU 0x10 11 | KERNEL_ENTRY EQU KERNEL_VIRTUAL_BASE + 0x1000 12 | TLS_SEG EQU 0x18 13 | TLS_END_ADDR EQU 0x1FF8 14 | 15 | ;;; This layout matches include/x86defs.h 16 | %macro SAVE_REGS 0 17 | 18 | push gs 19 | push fs 20 | push rbp 21 | push r15 22 | push r14 23 | push r13 24 | push r12 25 | push r11 26 | push r10 27 | push r9 28 | push r8 29 | push rdi 30 | push rsi 31 | push rdx 32 | push rcx 33 | push rbx 34 | push rax 35 | xor rax, rax 36 | mov ax,ds 37 | push rax 38 | mov ax, es 39 | push rax 40 | 41 | %endmacro 42 | 43 | 44 | %macro RESTORE_REGS 0 45 | 46 | pop rax 47 | mov es, ax 48 | pop rax 49 | mov ds, ax 50 | pop rax 51 | pop rbx 52 | pop rcx 53 | pop rdx 54 | pop rsi 55 | pop rdi 56 | pop r8 57 | pop r9 58 | pop r10 59 | pop r11 60 | pop r12 61 | pop r13 62 | pop r14 63 | pop r15 64 | pop rbp 65 | pop fs 66 | pop gs 67 | 68 | %endmacro 69 | 70 | 71 | %macro ALIGN_STACK 0 72 | 73 | ;; Align the stack to 16bytes required for ABI, stores original 74 | ;; RSP in RDI 75 | mov rdi, rsp 76 | push rsp 77 | push qword [rsp] 78 | and rsp, -16 79 | 80 | %endmacro 81 | 82 | 83 | %macro UNALIGN_STACK 0 84 | 85 | mov rsp, [rsp+8] 86 | 87 | %endmacro 88 | -------------------------------------------------------------------------------- /include/mm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * include/mm.h 3 | * 4 | * Created by Simon Evans on 18/01/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Miscellaneous definitions for memory management 8 | * 9 | */ 10 | 11 | #ifndef __MM_H__ 12 | #define __MM_H__ 13 | 14 | #include 15 | 16 | 17 | #define KERNEL_VIRTUAL_BASE 0xffffffff81000000UL // 2^64 - 2G + 16MB 18 | #ifndef TEST 19 | #define PHYSICAL_MEM_BASE 0xffff800000000000UL // 128TB 20 | #else 21 | #define PHYSICAL_MEM_BASE 0x0000000000001000UL // 4K - For testing in userspace 22 | #endif 23 | #define MAX_PHYSICAL_MEMORY 0x1000000000UL // 64GB Physical RAM 24 | 25 | #define PAGE_SHIFT 12 26 | #define PAGE_SIZE (1UL << PAGE_SHIFT) 27 | #define PAGE_MASK (~(PAGE_SIZE - 1)) 28 | 29 | #define CODE_SELECTOR 0x08 30 | #define DATA_SELECTOR 0x10 31 | #define TSS_SELECTOR 0x20 32 | 33 | 34 | struct e820_entry { 35 | uint64_t base_address; 36 | uint64_t length; 37 | uint32_t type; 38 | } __attribute__((packed)); 39 | 40 | 41 | // Structure for boot information passed from BIOS loader to kernel 42 | // Changes must also update boot/memory.asm 43 | struct bios_boot_params { 44 | char signature[8]; // ASCIIZ string 'BIOS' 45 | size_t table_size; // Size of entire table including embedded data and signature 46 | void * _Nonnull kernel_phys_addr; 47 | void * _Nonnull e820_map; 48 | size_t e820_entries; // Number of e820 memory map entries 49 | } __attribute__((packed)); 50 | 51 | 52 | void * _Nullable alloc_pages(size_t count); 53 | void free_pages(void * _Nonnull pages, size_t count); 54 | void * _Nullable malloc(size_t size); 55 | void free(void * _Nullable ptr); 56 | size_t malloc_usable_size (void * _Nullable ptr); 57 | 58 | #endif // __MM_H__ 59 | -------------------------------------------------------------------------------- /include/swift.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/swift.h 3 | * 4 | * Created by Simon Evans on 16/12/2015. 5 | * Copyright © 2015, 2016 Simon Evans. All rights reserved. 6 | * 7 | * Declarations of Swift functions callable from C 8 | * 9 | */ 10 | 11 | #ifndef __SWIFT_H__ 12 | #define __SWIFT_H__ 13 | 14 | #include 15 | 16 | 17 | // Swift versions of the print functions 18 | 19 | // static SwiftKernel.TTY.printChar (Swift.Int8) -> () 20 | extern void tty_print_char(const char ch); 21 | 22 | // static SwiftKernel.TTY.printCString (Swift.UnsafePointer) -> () 23 | extern void tty_print_cstring(const char * _Nonnull str); 24 | 25 | // static SwiftKernel.TTY.printCStringLen (Swift.UnsafePointer, length : Swift.Int) -> () 26 | extern void tty_print_cstring_len(const char * _Nonnull str, size_t len); 27 | 28 | // Used by dladdr() implemented in kernel/mm/symbols.swift 29 | typedef struct { 30 | const char * _Nullable dli_fname; /* File name of defining object. */ 31 | void * _Nullable dli_fbase; /* Load address of that object. */ 32 | const char * _Nullable dli_sname; /* Name of nearest symbol. */ 33 | void * _Nullable dli_saddr; /* Exact value of nearest symbol. */ 34 | } Dl_info; 35 | extern int dladdr(const void * _Nullable addr, Dl_info * _Nonnull info); 36 | 37 | #endif // __SWIFT_H__ 38 | -------------------------------------------------------------------------------- /include/usb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * include/usb.h 3 | * 4 | * Created by Simon Evans on 20/10/2020. 5 | * Copyright © 2020 Simon Evans. All rights reserved. 6 | * 7 | * USB data structures requiring specific field ordering. 8 | * 9 | */ 10 | 11 | #include 12 | 13 | struct usb_standard_device_descriptor { 14 | uint8_t bLength; 15 | uint8_t bDescriptorType; 16 | uint16_t bcdUSB; 17 | uint8_t bDeviceClass; 18 | uint8_t bDeviceSubClass; 19 | uint8_t bDeviceProtocol; 20 | uint8_t bMaxPacketSize0; 21 | uint16_t idVendor; 22 | uint16_t idProduct; 23 | uint16_t bcdDevice; 24 | uint8_t iManufacturer; 25 | uint8_t iProduct; 26 | uint8_t iSerialNumber; 27 | uint8_t bNumConfigurations; 28 | } __attribute__((packed)); 29 | 30 | 31 | struct usb_device_qualifier { 32 | uint8_t bLength; 33 | uint8_t bDescriptorType; 34 | uint16_t bcdUSB; 35 | uint8_t bDeviceClass; 36 | uint8_t bDeviceSubClass; 37 | uint8_t bDeviceProtocol; 38 | uint8_t bMaxPacketSize0; 39 | uint8_t bNumConfigurations; 40 | uint8_t bReserved; 41 | } __attribute__((packed)); 42 | 43 | 44 | struct usb_standard_config_descriptor { 45 | uint8_t bLength; 46 | uint8_t bDescriptorType; 47 | uint16_t wTotalLength; 48 | uint8_t bNumInterfaces; 49 | uint8_t bConfigurationValue; 50 | uint8_t iConfiguration; 51 | uint8_t bmAttributes; 52 | uint8_t bMaxPower; 53 | } __attribute__((packed)); 54 | 55 | 56 | struct usb_standard_interface_descriptor { 57 | uint8_t bLength; 58 | uint8_t bDescriptorType; 59 | uint8_t bInterfaceNumber; 60 | uint8_t bAlternateSetting; 61 | uint8_t bNumEndpoints; 62 | uint8_t bInterfaceClass; 63 | uint8_t bInterfaceSubClass; 64 | uint8_t bInterfaceProtocol; 65 | uint8_t iInterface; 66 | } __attribute__((packed)); 67 | 68 | 69 | struct usb_standard_endpoint_descriptor { 70 | uint8_t bLength; 71 | uint8_t bDescriptorType; 72 | uint8_t bEndpointAddress; 73 | uint8_t bmAttributes; 74 | uint16_t wMaxPacketSize; 75 | uint8_t bInterval; 76 | } __attribute__((packed)); 77 | 78 | 79 | struct usb_hid_descriptor { 80 | uint8_t bLength; 81 | uint8_t bDescriptorType; 82 | uint16_t bcdHID; 83 | uint8_t bCountryCode; 84 | uint8_t bNumDescriptors; 85 | uint8_t bReportDescriptorType; 86 | uint16_t wDescriptorLength; 87 | } __attribute__((packed)); 88 | 89 | 90 | struct usb_control_request { 91 | uint8_t bmRequestType; 92 | uint8_t bRequest; 93 | uint16_t wValue; 94 | uint16_t wIndex; 95 | uint16_t wLength; 96 | } __attribute__((packed)); 97 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | # -*- mode: BSDmakefile; tab-width: 8; -*- 2 | TOPDIR := .. 3 | include $(TOPDIR)/Makedefs 4 | GITVER := $(shell git rev-parse HEAD) 5 | 6 | SWIFT_MODULE := SwiftKernel 7 | SWIFT_OBJS := SwiftKernel.o 8 | SWIFT_SRCS := $(shell find `pwd` -name '*.swift' | grep -v version.swift) init/version.swift 9 | 10 | all: kernel.o 11 | 12 | 13 | init/main.o: init/main.asm 14 | init/bss.o: init/bss.c 15 | traps/entry.o: traps/entry.asm 16 | vm/vmentry.o: vm/vmentry.asm 17 | devices/timer.o: devices/timer.asm 18 | 19 | init/init.o: init/main.o init/bss.o 20 | ld -r -no_eh_labels -o $@ $^ 21 | 22 | KERNEL_OBJS := init/init.o traps/entry.o vm/vmentry.o devices/timer.o SwiftKernel.o 23 | HEADERS = $(TOPDIR)/include/*.h 24 | 25 | init/version.swift: ../.git/index 26 | echo making version.swift for $(GITVER) 27 | echo 'let gitBuildVersion="$(GITVER)"' > init/version.swift 28 | 29 | kernel.o: $(KERNEL_OBJS) 30 | ld -r -no_eh_labels -o $@ $(KERNEL_OBJS) 31 | 32 | SwiftKernel.o: $(SWIFT_SRCS) $(HEADERS) 33 | # swiftc doesnt always seem to update the timestamp after building the delete the output file to be 34 | # sure that a new file is created 35 | rm -f $@ 36 | $(KSWIFTC) $(KSWIFTC_FLAGS) -whole-module-optimization -module-name $(SWIFT_MODULE) -emit-object -o $@ $(SWIFT_SRCS) 37 | 38 | clean: 39 | find . -name '*.bin' -o -name '*.o' |xargs rm 40 | rm -f init/version.swift 41 | -------------------------------------------------------------------------------- /kernel/devices/PNPDevice.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/PNPDevice.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 07/06/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | // Device representing hardware identified by a _HID or _CID ACPI name, 9 | // non-PCI, usually ISA or ACPI devices. 10 | 11 | final class PNPDevice: Device { 12 | private unowned let _acpiDevice: AMLDefDevice 13 | private(set) var pnpDeviceDriver: PNPDeviceDriver? 14 | private(set) var resources = ISABus.Resources([]) 15 | unowned let parentBus: Bus 16 | let pnpName: String 17 | var enabled = false 18 | 19 | var acpiDevice: AMLDefDevice? { _acpiDevice } 20 | var fullName: String { _acpiDevice.fullname() } 21 | var deviceDriver: DeviceDriver? { pnpDeviceDriver } 22 | var description: String { "ISA: \(pnpName) \(fullName) \(resources)" } 23 | 24 | 25 | init(parentBus: Bus, acpiDevice: AMLDefDevice, pnpName: String) { 26 | self._acpiDevice = acpiDevice 27 | self.parentBus = parentBus 28 | self.pnpName = pnpName 29 | } 30 | 31 | func setDriver(_ driver: DeviceDriver) { 32 | if let deviceDriver = deviceDriver { 33 | fatalError("\(self) already has a device driver: \(deviceDriver)") 34 | } 35 | 36 | guard let pnpDriver = driver as? PNPDeviceDriver else { 37 | fatalError("\(self): \(driver) is not for a PNP Device") 38 | } 39 | pnpDeviceDriver = pnpDriver 40 | } 41 | 42 | func initialise() -> Bool { 43 | guard _acpiDevice.initialiseIfPresent() else { 44 | print("\(fullName): initialiseIfPresent() failed") 45 | return false 46 | } 47 | if let crs = _acpiDevice.currentResourceSettings() { 48 | resources = ISABus.Resources(crs) 49 | } 50 | self.enabled = true 51 | return true 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /kernel/devices/Timer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/Timer.swift 3 | // 4 | // Created by Simon Evans on 18/04/2021. 5 | // Copyright © 2021 Simon Evans. All rights reserved. 6 | // 7 | // Timer setup and related routines. 8 | // 9 | 10 | 11 | // Generic Timer device 12 | protocol Timer { 13 | var irq: IRQSetting { get } 14 | func enablePeriodicInterrupt(hz: Int) 15 | } 16 | 17 | 18 | // Setup a periodic timer using either a PIT or HPET. This is set to 1Khz and 19 | // used to increment a counter that can be used for sleep etc. 20 | func setupPeriodicTimer() -> Bool { 21 | // Find a timer 22 | let irq: IRQSetting 23 | // Set the timer interrupt for 1kHz 24 | if let timer = system.deviceManager.timer { 25 | timer.enablePeriodicInterrupt(hz: 1000) 26 | irq = timer.irq 27 | print(timer) 28 | } else { 29 | // Try and use the HPET to emultate the PIT 30 | if var hpet = system.deviceManager.acpiTables.entry(of: HPET.self) { 31 | guard hpet.emulateLegacyPIT(ticksPerSecond: 1000) else { 32 | print("timer: HPET doesnt support PIT mode") 33 | return false 34 | } 35 | } else { 36 | print("timer: Cant find an HPET") 37 | return false 38 | } 39 | // HPET is put in legacy mode so IRQ should be 0 although. 40 | irq = IRQSetting(isaIrq: 0) 41 | } 42 | system.deviceManager.interruptManager.setIrqHandler(irq, handler: timerInterrupt) 43 | print("timer: Setup for 1000Hz on irq:", irq) 44 | return true 45 | } 46 | 47 | 48 | private func timerInterrupt() -> Bool { 49 | timer_callback() 50 | return true 51 | } 52 | 53 | 54 | func sleep(milliseconds: Int) { 55 | let current = current_ticks() 56 | let required = current + UInt64(milliseconds) 57 | while required > current_ticks() { 58 | hlt() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /kernel/devices/acpi/ACPIGenericAddressStructure.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/ACPIGenericAddressStructure.swift 3 | // 4 | // Created by Simon Evans on 17/04/2021. 5 | // Copyright © 2021 Simon Evans. All rights reserved. 6 | // 7 | // ACPI Generic Address Structure. 8 | // 9 | 10 | 11 | struct ACPIGenericAddressStrucure { 12 | enum AddressSpaceID: UInt8 { 13 | case systemMemory = 0 14 | case systemIO = 1 15 | } 16 | 17 | private let gas: acpi_gas 18 | 19 | init(_ gas: acpi_gas) { 20 | self.gas = gas 21 | } 22 | 23 | var addressSpaceID: AddressSpaceID { 24 | return AddressSpaceID(rawValue: gas.address_space_id)! 25 | } 26 | 27 | var registerBitWidth: Int { Int(gas.register_bit_width) } 28 | var registerBitOffset: Int { Int(gas.register_bit_offset) } 29 | var access_size: Int { Int(gas.access_size) } 30 | var baseAddress: UInt64 { gas.address } 31 | var physicalAddress: PhysAddress { PhysAddress(RawAddress(baseAddress)) } 32 | var rawPointer: UnsafeMutableRawPointer { physicalAddress.rawPointer } 33 | } 34 | -------------------------------------------------------------------------------- /kernel/devices/acpi/TODO: -------------------------------------------------------------------------------- 1 | Use IOPort and MMapped regions for the RegionSpace, only use arrays for testing 2 | Make error messaging better 3 | Max subparser recursion depth 4 | Simplify parseArgs etc and merge with Var args 5 | Scope modifiers dont need to store the objectList 6 | Store local names in the context not the globalObjects 7 | 8 | - Fix RegionSpace read/write at bitOffset 9 | - merge If/ElseIf/ElseIf/Else blocks 10 | - AMLDefOpRegion Should probably be a class and try to allocate its own region at init() 11 | - Fix enums to have lowercase first letter 12 | - Implement Data conversion 13 | - Should AMLTermArg.evaluate() throw? 14 | 15 | DONE - Fix dual invokeMethods, should only be one 16 | -------------------------------------------------------------------------------- /kernel/devices/acpi/amlutils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/amlutils.swift 3 | // 4 | // Created by Simon Evans on 30/04/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // ACPI misc utilities 8 | 9 | 10 | // Convert a compressed 32bit EISA type ID to a string 11 | private func decodeEISAId(_ id: UInt32) -> AMLString { 12 | let eisaid = BitArray32(UInt32(bigEndian: id)) 13 | 14 | func hexDigit(_ x: Int) -> UnicodeScalar { 15 | precondition(x >= 0 && x < 16) 16 | let digits: StaticString = "0123456789ABCDEF" 17 | 18 | let digitsBuffer = UnsafeBufferPointer(start: digits.utf8Start, 19 | count: digits.utf8CodeUnitCount) 20 | 21 | return UnicodeScalar(digitsBuffer[x]) 22 | } 23 | 24 | var hid = "" 25 | UnicodeScalar(eisaid[26...30] + 0x40)!.write(to: &hid) 26 | UnicodeScalar(eisaid[21...25] + 0x40)!.write(to: &hid) 27 | UnicodeScalar(eisaid[16...20] + 0x40)!.write(to: &hid) 28 | hexDigit(Int(eisaid[12...15])).write(to: &hid) 29 | hexDigit(Int(eisaid[8...11])).write(to: &hid) 30 | hexDigit(Int(eisaid[4...7])).write(to: &hid) 31 | hexDigit(Int(eisaid[0...3])).write(to: &hid) 32 | 33 | return AMLString(hid) 34 | } 35 | 36 | 37 | func decodeHID(obj: AMLTermArg) -> AMLString { 38 | if let string = obj.stringValue { 39 | return string 40 | } 41 | else if let value = obj.integerValue { 42 | return decodeEISAId(UInt32(value)) 43 | } else { 44 | fatalError("decodeHID: \(obj) is invalid argument for decoding an EISAid") 45 | } 46 | } 47 | 48 | 49 | func resolveNameTo(scope: AMLNameString, path: AMLNameString) -> AMLNameString { 50 | if let x = path.value.first { 51 | if path.isFullPath { 52 | return path 53 | } 54 | var newScope = scope.value 55 | var newPath = path.value 56 | if x == AMLNameString.parentPrefixChar { 57 | newPath = "" 58 | var parts = scope.value.components(separatedBy: AMLNameString.pathSeparatorChar) 59 | for ch in path.value { 60 | if ch == AMLNameString.parentPrefixChar { 61 | _ = parts.popLast() 62 | } else { 63 | newPath.append(ch) 64 | } 65 | } 66 | newScope = parts.joined(separator: String(AMLNameString.pathSeparatorChar)) 67 | } 68 | if !newScope.isEmpty, newScope != String(AMLNameString.rootChar) { 69 | newScope.append(AMLNameString.pathSeparatorChar) 70 | } 71 | newScope.append(newPath) 72 | return AMLNameString(newScope) 73 | } else { 74 | return scope // path is empty 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /kernel/devices/acpi/boot.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/boot.swift 3 | // 4 | // Created by Simon Evans on 07/05/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // Parsing of Simple Boot Flag (BOOT) Table. 8 | 9 | struct BOOT: ACPITable, CustomStringConvertible { 10 | 11 | // Offset in CMOS memory where the BOOT register is located. 12 | let cmosOffset: Int 13 | var description: String { return "BOOT: CMOS memory index: \(cmosOffset)" } 14 | 15 | 16 | init(_ ptr: UnsafeRawPointer) { 17 | let table = ptr.load(as: acpi_boot_table.self) 18 | guard Int(table.header.length) == MemoryLayout.size else { 19 | fatalError("ACPI: BOOT: Table length is incorrect") 20 | } 21 | cmosOffset = Int(table.cmos_index) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /kernel/devices/acpi/ecdt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/ecdt.swift 3 | // 4 | // Created by Simon Evans on 06/05/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // Parsing of Embedded Controller Boot Resources (ECDT) table. 8 | 9 | struct ECDT: ACPITable, CustomStringConvertible { 10 | 11 | let ecId: String 12 | var description: String { return "ECDT: \(ecId)" } 13 | 14 | 15 | init(_ ptr: UnsafeRawPointer) { 16 | let table = ptr.load(as: acpi_ecdt_table.self) 17 | 18 | // The EC_ID string is variable length and at the end 19 | // of the table. It is not included in the struct 20 | // as it is variable length so cant be expressed 21 | let ecIdLen = Int(table.header.length) - MemoryLayout.size 22 | guard ecIdLen > 0 else { 23 | fatalError("ACPI: ECDT table lentgth is too short") 24 | } 25 | let ecIdPtr = ptr.advanced(by: MemoryLayout.size) 26 | ecId = String(ecIdPtr, maxLength: ecIdLen) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kernel/devices/acpi/facp.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/acpi/facp.swift 3 | * 4 | * Created by Simon Evans on 02/03/2016. 5 | * Copyright © 2016 - 2021 Simon Evans. All rights reserved. 6 | * 7 | * Parsing of ACPI FACP (Fixed ACPI Description Table). Bare minimum 8 | * of fields are looked at, just to see if IAPC flags held any information. 9 | */ 10 | 11 | struct FACP: ACPITable, CustomStringConvertible { 12 | 13 | private let table: acpi_facp_table 14 | 15 | // IA-PC Boot Architecture Flags (bit) 16 | private let IAPC_LEGACY_DEVICES = 0 17 | private let IAPC_8042 = 1 18 | private let IAPC_VGA_NOT_PRESENT = 2 19 | private let IAPC_MSI_NOT_SUPPORTED = 3 20 | private let IAPC_PCIE_ASPM = 4 21 | private let IAPC_RTC_NOT_PRESENT = 5 22 | 23 | 24 | var hasLegacyDevices: Bool { table.iapc_boot_arch.bit(IAPC_LEGACY_DEVICES) } 25 | var has8042Controller: Bool { table.iapc_boot_arch.bit(IAPC_8042) } 26 | var isVgaPresent: Bool { table.iapc_boot_arch.bit(IAPC_VGA_NOT_PRESENT) == false } 27 | var isMsiSupported: Bool { table.iapc_boot_arch.bit(IAPC_MSI_NOT_SUPPORTED) == false } 28 | var canEnablePcieAspmControls: Bool { table.iapc_boot_arch.bit(IAPC_PCIE_ASPM) == false } 29 | var hasCmosRtc: Bool { table.iapc_boot_arch.bit(IAPC_RTC_NOT_PRESENT) == false } 30 | var rtcCenturyIndex: UInt8 { return table.century } 31 | 32 | var facsAddress: PhysAddress? { 33 | if table.header.length >= 140 { 34 | return physicalAddress(xAddr: table.x_firmware_ctrl, 35 | addr: table.firmware_ctrl) 36 | } 37 | if table.header.length >= 40 { 38 | return physicalAddress(xAddr: 0, addr: table.firmware_ctrl) 39 | } 40 | return nil 41 | } 42 | 43 | var dsdtAddress: PhysAddress? { 44 | if table.header.length >= 148 { 45 | return physicalAddress(xAddr: table.x_dsdt, addr: table.dsdt) 46 | } 47 | if table.header.length >= 44 { 48 | return physicalAddress(xAddr: 0, addr: table.dsdt) 49 | } 50 | return nil 51 | } 52 | 53 | 54 | var description: String { 55 | "FACP: hasLegacyDev: \(hasLegacyDevices) has8042: \(has8042Controller) hasVga: \(isVgaPresent) " + 56 | "hasMSI: \(isMsiSupported) hasRTC: \(hasCmosRtc)" 57 | } 58 | 59 | init(_ ptr: UnsafeRawPointer) { 60 | table = ptr.load(as: acpi_facp_table.self) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /kernel/devices/acpi/facs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/facs.swift 3 | // 4 | // Created by Simon Evans on 07/05/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // Parsing of Firmware ACPI Control Structure (FACS). 8 | 9 | struct FACS: ACPITable, CustomStringConvertible { 10 | 11 | private let table: acpi_facs_table 12 | var description: String { "FACS: 0x\(String(table.hardware_signature, radix: 16))" } 13 | 14 | 15 | init(_ ptr: UnsafeRawPointer) { 16 | table = ptr.load(as: acpi_facs_table.self) 17 | guard table.length >= MemoryLayout.size else { 18 | fatalError("ACPI: FACS table is too short \(table.length) bytes") 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kernel/devices/acpi/mcfg.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/acpi/mcfg.swift 3 | * 4 | * Created by Simon Evans on 02/03/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Parsing of ACPI MCFG (PCI Express MM configuration space address description 8 | * table). 9 | */ 10 | 11 | 12 | // FIXME: This table may need to be fixedup using PNP0C01/PNP0C02 info from 13 | // motherboard resources as the bus range may be too big 14 | struct MCFG: ACPITable { 15 | 16 | struct ConfigEntry: CustomStringConvertible { 17 | let baseAddress: PhysAddress 18 | let segmentGroup: UInt16 19 | let startBus: UInt8 20 | let endBus: UInt8 21 | let reserved: UInt32 22 | 23 | var description: String { 24 | return "base: \(asHex(baseAddress.value)) segment: \(segmentGroup)" 25 | + " startBus: \(asHex(startBus)) endBus: \(asHex(endBus))" 26 | } 27 | 28 | init(entry: acpi_mcfg_config_entry) { 29 | baseAddress = PhysAddress(RawAddress(entry.base_address)) 30 | segmentGroup = entry.segment_group 31 | startBus = entry.start_bus 32 | endBus = entry.end_bus 33 | reserved = 0 34 | } 35 | 36 | init(baseAddress: PhysAddress, segmentGroup: UInt16, startBus: UInt8, 37 | endBus: UInt8) { 38 | self.baseAddress = baseAddress 39 | self.segmentGroup = segmentGroup 40 | self.startBus = startBus 41 | self.endBus = endBus 42 | reserved = 0 43 | } 44 | } 45 | 46 | let allocations: [ConfigEntry] 47 | 48 | 49 | init(_ ptr: UnsafeRawPointer, vendor: String, product: String) { 50 | let table = ptr.load(as: acpi_mcfg_table.self) 51 | // Multiple acpi_mcfg_config_entrys follow the table 52 | let itemLen = Int(table.header.length) - MemoryLayout.stride 53 | let configEntrySize = MemoryLayout.size 54 | 55 | assert(itemLen > 0) 56 | assert(itemLen % configEntrySize == 0) 57 | // validate the structure is packed 58 | assert(configEntrySize == MemoryLayout.stride) 59 | 60 | let itemCnt = itemLen / configEntrySize 61 | var items: [ConfigEntry] = [] 62 | items.reserveCapacity(itemCnt) 63 | 64 | let configPtr = ptr.advanced(by: MemoryLayout.stride) 65 | for idx in 0...stride, 67 | as: acpi_mcfg_config_entry.self) 68 | items.append(ConfigEntry(entry: entry)) 69 | } 70 | 71 | if (vendor == "Apple Inc.") && (product == "MacBook3,1") && (items[0].endBus == 0xff) { 72 | items[0] = ConfigEntry( 73 | baseAddress: items[0].baseAddress, 74 | segmentGroup: items[0].segmentGroup, 75 | startBus: items[0].startBus, 76 | endBus: 0x3f) 77 | 78 | print("ACPI: MCFG: Overrode endBus from 0xff to 0x3f for", 79 | vendor, product) 80 | } 81 | 82 | allocations = items 83 | } 84 | 85 | 86 | func baseAddressFor(bus: UInt8) -> PhysAddress? { 87 | for entry in allocations { 88 | if bus >= entry.startBus && bus <= entry.endBus { 89 | let offset = UInt(bus - entry.startBus) << 20 90 | return entry.baseAddress + offset 91 | } 92 | } 93 | 94 | return nil 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /kernel/devices/acpi/sbst.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/sbst.swift 3 | // 4 | // Created by Simon Evans on 06/05/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // Smart Battery (SBST) Table. 8 | 9 | 10 | struct SBST: ACPITable, CustomStringConvertible { 11 | 12 | let warningLevelInmWh: Int 13 | let lowLevelInmWh: Int 14 | let criticalLevelInmWh: Int 15 | 16 | var description: String { 17 | return "SBST: battery warning: \(warningLevelInmWh)mWh" 18 | + " low: \(lowLevelInmWh)mWh critical: \(criticalLevelInmWh)mWh" 19 | } 20 | 21 | 22 | init(_ ptr: UnsafeRawPointer) { 23 | let table = ptr.load(as: acpi_sbst_table.self) 24 | let length = table.header.length 25 | guard length >= MemoryLayout.size else { 26 | fatalError("ACPI: SBST table too short: \(length)") 27 | } 28 | warningLevelInmWh = Int(table.warning_energy_level) 29 | lowLevelInmWh = Int(table.low_energy_level) 30 | criticalLevelInmWh = Int(table.critical_energy_level) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /kernel/devices/acpi/waet.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/acpi/waet.swift 3 | // 4 | // Created by Simon Evans on 07/05/2017. 5 | // Copyright © 2017 Simon Evans. All rights reserved. 6 | // 7 | // Parsing of Windows ACPI Enlightenment Table (WAET) Table. 8 | 9 | struct WAET: ACPITable, CustomStringConvertible { 10 | 11 | private let deviceFlags: BitArray32 12 | 13 | var isRTCGood: Bool { deviceFlags[0] == 1 } 14 | var isPMTimerGood: Bool { deviceFlags[1] == 1 } 15 | var description: String { return "WAET: isRTCGood: \(isRTCGood) isPMTimerGood: \(isPMTimerGood)" } 16 | 17 | 18 | init(_ ptr: UnsafeRawPointer) { 19 | let table = ptr.load(as: acpi_waet_table.self) 20 | guard Int(table.header.length) == MemoryLayout.size else { 21 | fatalError("ACPI: WAET: Table length is incorrect") 22 | } 23 | deviceFlags = BitArray32(table.device_flags) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kernel/devices/device.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/device.swift 3 | // 4 | // Created by Simon Evans on 30/09/2020. 5 | // Copyright © 2020 Simon Evans. All rights reserved. 6 | // 7 | 8 | protocol Device: AnyObject, CustomStringConvertible { 9 | var parentBus: Bus { get } 10 | var acpiDevice: AMLDefDevice? { get } 11 | var fullName: String { get } 12 | var enabled: Bool { get set } 13 | var deviceDriver: DeviceDriver? { get } 14 | 15 | func initialise() -> Bool 16 | func setDriver(_ driver: DeviceDriver) 17 | } 18 | 19 | // Generic Keyboard device 20 | protocol Keyboard { 21 | func readKeyboard() -> UnicodeScalar? 22 | // TODO: Add some key modifier state 23 | } 24 | -------------------------------------------------------------------------------- /kernel/devices/driver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // driver.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 26/09/2020. 6 | // Copyright © 2020 Simon Evans. All rights reserved. 7 | // 8 | 9 | 10 | protocol DeviceDriver: AnyObject { 11 | func initialise() -> Bool 12 | } 13 | 14 | 15 | protocol PNPDeviceDriver: DeviceDriver { 16 | // var pnpDevice: PNPDevice { get } 17 | // var supportedPnpIds: Set { get } 18 | init?(pnpDevice: PNPDevice) 19 | } 20 | 21 | 22 | protocol PCIDeviceDriver: DeviceDriver { 23 | // var pciDevice: PCIDevice { get } 24 | // var supportedVendorIds: Set<(UInt16, UInt16)> { get } 25 | init?(pciDevice: PCIDevice) 26 | } 27 | 28 | 29 | struct PCISupportedVendorDevice: Hashable, Equatable { 30 | let vendor: UInt16 31 | let device: UInt16 32 | } 33 | 34 | private var pciDriversForIds: [PCISupportedVendorDevice: PCIDeviceDriver.Type] = [: 35 | ] 36 | 37 | #if KERNEL 38 | private var pnpDriversForIds: [String: PNPDeviceDriver.Type] = [ 39 | "PNP0100": PIT8254.self, 40 | "PNP0303": KBD8042.self, 41 | "PNP030B": KBD8042.self, 42 | "PNP0B00": CMOSRTC.self, 43 | "PNP0C0F": PCIInterruptLinkDevice.self, 44 | "QEMU0002": QEMUFWCFG.self, 45 | ] 46 | #else 47 | private var pnpDriversForIds: [String: PNPDeviceDriver.Type] = [:] 48 | #endif 49 | 50 | 51 | func pciDriverById(vendor: UInt16, device: UInt16) -> PCIDeviceDriver.Type? { 52 | let vendorDevice = PCISupportedVendorDevice(vendor: vendor, device: device) 53 | return pciDriversForIds[vendorDevice] 54 | } 55 | 56 | func pnpDriverById(pnpName: String) -> PNPDeviceDriver.Type? { 57 | return pnpDriversForIds[pnpName] 58 | } 59 | 60 | 61 | func registerPCIDriver(driver: PCIDeviceDriver.Type, supportedIds: [PCISupportedVendorDevice]) { 62 | for supportedId in supportedIds { 63 | pciDriversForIds[supportedId] = driver 64 | } 65 | } 66 | 67 | func registerPNPDeviceDriver(driver: PNPDeviceDriver.Type) { 68 | 69 | } 70 | -------------------------------------------------------------------------------- /kernel/devices/pci/PCIInterruptLinkDevice.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/devices/PCIInterruptLinkDevice.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 03/05/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | // PCI Link Devices (LNKA..LNKD) used for PCI interrupts (INT #A .. INT #D) 9 | // 10 | 11 | final class PCIInterruptLinkDevice: PNPDeviceDriver, CustomStringConvertible { 12 | let irq: IRQSetting // The IRQ signaled by this device 13 | var description: String { "PCI Link Device: [IRQ: \(irq)]" } 14 | 15 | 16 | init?(pnpDevice: PNPDevice) { 17 | guard let acpiDevice = pnpDevice.acpiDevice else { 18 | print("PCIInterruptLinkDevice: \(pnpDevice) has no ACPI information") 19 | return nil 20 | } 21 | 22 | 23 | guard let uid = acpiDevice.uniqueId() else { 24 | print("PCIInterruptLinkDevice: cant get _UID") 25 | return nil 26 | } 27 | 28 | guard let uidValue = uid.integerValue, uidValue <= UInt8.max else { 29 | print("PCI LNK: uid is not an integer: \(uid)") 30 | return nil 31 | } 32 | 33 | guard let crs = acpiDevice.currentResourceSettings() else { 34 | print("PCIInterruptLinkDevice: Cant get resources") 35 | return nil 36 | } 37 | 38 | let resources = ISABus.Resources(crs) 39 | let f = acpiDevice.fullname() 40 | print("PCIInterruptLinkDevice: \(f) \(resources)") 41 | 42 | if let prs = pnpDevice.acpiDevice?.possibleResourceSettings() { 43 | print("PCI LNK \(f): _PRS:", prs) 44 | } 45 | 46 | if let cirq = resources.interrupts.first { 47 | irq = cirq 48 | print("Using IRQ \(cirq)") 49 | } else { 50 | print(f, "has no configured irq") 51 | return nil 52 | } 53 | 54 | print("PCI INT Link \(f) [_UID=\(uidValue)]: resources:", resources) 55 | } 56 | 57 | // FIXME: Maybe select a better IRQ to use to balance them out better or make 58 | // .irq into a funtion to do lazy irq allocation 59 | func initialise() -> Bool { 60 | true 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /kernel/devices/pci/pcideviceclass.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/pci/pcideviceclass.swift 3 | * 4 | * Created by Simon Evans on 24/09/2020. 5 | * Copyright © 2015 - 2020 Simon Evans. All rights reserved. 6 | * 7 | * PCI Class and subclass codes. 8 | * 9 | */ 10 | 11 | 12 | struct PCIDeviceClass: Equatable { 13 | let classCode: PCIClassCode 14 | let subClassCode: UInt8 15 | let progInterface: UInt8 16 | 17 | init?(classCode: UInt8, subClassCode: UInt8, progInterface: UInt8) { 18 | guard let _classCode = PCIClassCode(rawValue: classCode) else { 19 | return nil 20 | } 21 | self.classCode = _classCode 22 | self.subClassCode = subClassCode 23 | self.progInterface = progInterface 24 | } 25 | 26 | init(classCode: PCIClassCode, subClassCode: UInt8, progInterface: UInt8) { 27 | self.classCode = classCode 28 | self.subClassCode = subClassCode 29 | self.progInterface = progInterface 30 | } 31 | 32 | var bridgeSubClass: PCIBridgeControllerSubClass? { 33 | guard classCode == .bridgeDevice else { 34 | return nil 35 | } 36 | return PCIBridgeControllerSubClass(rawValue: subClassCode) 37 | } 38 | 39 | var seriaBusSubClass: PCISerialBusControllerSubClass? { 40 | classCode == .serialBusController ? PCISerialBusControllerSubClass(rawValue: subClassCode) : nil 41 | } 42 | } 43 | 44 | enum PCIClassCode: UInt8 { 45 | 46 | case unclassified = 0 47 | case massStorageController = 1 48 | case networkController = 2 49 | case displayController = 3 50 | case multimediaController = 4 51 | case memoryController = 5 52 | case bridgeDevice = 6 53 | case simpleCommunicationController = 7 54 | case baseSystemPeripheral = 8 55 | case inputDeviceController = 9 56 | case dockingStation = 0xA 57 | case processor = 0xB 58 | case serialBusController = 0xC 59 | case wirelessController = 0xD 60 | case intelligentController = 0xE 61 | case satelliteCommunicationController = 0xF 62 | case encryptionController = 0x10 63 | case signalProcessingController = 0x11 64 | case processingAccelerator = 0x12 65 | case nonEssentialInstrumentation = 0x13 66 | case coProcessor = 0x40 67 | case unassigned = 0xff 68 | } 69 | 70 | 71 | // .bridgeDevice 72 | enum PCIBridgeControllerSubClass: UInt8 { 73 | case host = 0 74 | case isa = 1 75 | case eisa = 2 76 | case mca = 3 77 | case pci = 4 78 | case pcmcia = 5 79 | case nuBus = 6 80 | case cardBus = 7 81 | case raceway = 8 82 | case pciSemiTransparent = 9 83 | case infiniband = 0x0a 84 | case other = 0x80 85 | } 86 | 87 | // serialBusController 88 | enum PCISerialBusControllerSubClass: UInt8 { 89 | case fireWire = 0 90 | case accessBus = 1 91 | case ssa = 2 92 | case usb = 3 93 | case fibreChannel = 4 94 | case smbus = 5 95 | case infiniband = 6 96 | case ipmiInterface = 7 97 | case sercos = 8 98 | case canbus = 9 99 | case other = 0x80 100 | } 101 | 102 | 103 | // USB Programming Interface 104 | enum PCIUSBProgrammingInterace: UInt8 { 105 | case uhci = 0x00 106 | case ohci = 0x10 107 | case ehci = 0x20 108 | case xhci = 0x30 109 | case other = 0x80 110 | case device = 0xfe 111 | } 112 | -------------------------------------------------------------------------------- /kernel/devices/qemufwcf.swift: -------------------------------------------------------------------------------- 1 | // 2 | // qemufwcf.swift 3 | // tests 4 | // 5 | // Created by Simon Evans on 10/08/2019. 6 | // Copyright © 2019 Simon Evans. All rights reserved. 7 | // 8 | // QEMU Firmware Configuration (fw_cfg) Device 9 | // https://github.com/qemu/qemu/blob/master/docs/specs/fw_cfg.txt 10 | 11 | final class QEMUFWCFG: PNPDeviceDriver { 12 | let pnpName: String 13 | let baseIOPort: UInt16 14 | private(set) var hasDMAInterface = false 15 | 16 | init?(pnpDevice: PNPDevice) { 17 | self.pnpName = pnpDevice.pnpName 18 | let resources = pnpDevice.resources 19 | print(pnpDevice.fullName, "Resources:", resources) 20 | guard let ioPorts = resources.ioPorts.first, ioPorts.count > 6, 21 | let basePort = ioPorts.first else { 22 | print("QEMU: port range is to small:", resources.ioPorts.count) 23 | return nil 24 | } 25 | baseIOPort = basePort 26 | } 27 | 28 | 29 | func initialise() -> Bool { 30 | let signature = readSignature() 31 | guard signature == "QEMU" else { 32 | print("QEMU: Invalid signature", signature) 33 | return false 34 | } 35 | 36 | let features = featureBitmap() 37 | print("Signature:", signature, "features", asHex(features)) 38 | guard features & 1 == 1 else { 39 | print("QEMU device feature bit doesnt have IO access") 40 | return false 41 | } 42 | hasDMAInterface = (features & 2) != 0 43 | print("QEMU: DMA interface available") 44 | return true 45 | } 46 | 47 | 48 | func setIndex(_ index: UInt16) { 49 | let ioport = baseIOPort 50 | outw(ioport, index) 51 | } 52 | 53 | func readData() -> UInt8 { 54 | return inb(baseIOPort + 1) 55 | } 56 | 57 | private func readSignature() -> String { 58 | setIndex(0) 59 | var signature = "" 60 | for _ in 1...4 { 61 | signature += String(UnicodeScalar(readData())) 62 | } 63 | return signature 64 | } 65 | 66 | private func featureBitmap() -> UInt32 { 67 | setIndex(1) 68 | var shift = UInt32(0) 69 | var result = UInt32(0) 70 | for _ in 1...4 { 71 | result |= (UInt32(readData()) << shift) 72 | shift += 8 73 | } 74 | return result 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /kernel/devices/timer.asm: -------------------------------------------------------------------------------- 1 | ;;; kernel/traps/timer.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 11/10/2020. 4 | ;;; Copyright © 2020 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; Timer interrupt and current tick count 7 | 8 | GLOBAL timer_callback 9 | GLOBAL current_ticks 10 | 11 | 12 | timer_callback: 13 | inc qword [ticks] 14 | ret 15 | 16 | current_ticks: 17 | mov rax, [ticks] 18 | ret 19 | 20 | sleep_in_milliseconds: 21 | add rdi, [ticks] 22 | 23 | .loop: 24 | hlt 25 | cmp rdi, [ticks] 26 | jg .loop 27 | ret 28 | 29 | 30 | SECTION .data 31 | 32 | ticks DQ 0 33 | -------------------------------------------------------------------------------- /kernel/devices/usb/hcd-ehci.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/usb/hcd-ehci.swift 3 | * 4 | * Created by Simon Evans on 05/10/2020. 5 | * Copyright © 2015 - 2020 Simon Evans. All rights reserved. 6 | * 7 | * EHCI HCD driver. 8 | * 9 | */ 10 | 11 | 12 | final class HCD_EHCI: PCIDeviceDriver, USBHCD, CustomStringConvertible { 13 | private let pciDevice: PCIDevice // The device (upstream) side of the bridge 14 | private let baseAddress: UInt32 15 | private let allows64BitMapping: Bool 16 | 17 | var description: String { "EHCI driver @ 0x\(String(baseAddress, radix: 16))" } 18 | 19 | 20 | init?(pciDevice: PCIDevice) { 21 | print("EHCI init:", pciDevice) 22 | guard pciDevice.deviceFunction.deviceClass == PCIDeviceClass(classCode: .serialBusController, 23 | subClassCode: PCISerialBusControllerSubClass.usb.rawValue, 24 | progInterface: PCIUSBProgrammingInterace.ehci.rawValue) else { 25 | print("EHCI: \(pciDevice) is not a EHCI Device") 26 | return nil 27 | } 28 | 29 | guard let generalDevice = pciDevice.deviceFunction.generalDevice else { 30 | print("EHCI: Not a PCI generalDevice") 31 | return nil 32 | } 33 | 34 | let base = generalDevice.bar0 35 | guard base & 1 == 0 else { 36 | print("EHCI: BAR0 address 0x\(String(base, radix: 16)) is not a memory resource") 37 | return nil 38 | } 39 | 40 | self.pciDevice = pciDevice 41 | allows64BitMapping = base & 0b110 == 0b100 42 | baseAddress = base & 0xffff_ff00 43 | print("EHCI: 0x\(String(baseAddress, radix: 16)) allows64BitMapping: \(allows64BitMapping)") 44 | } 45 | 46 | 47 | func initialise() -> Bool { 48 | print("EHCI driver") 49 | let sbrn = pciDevice.deviceFunction.readConfigByte(atByteOffset: 0x60) 50 | print("EHCI: bus release number 0x\(String(sbrn, radix: 16))") 51 | return false 52 | } 53 | 54 | func allocatePipe(device: USBDevice, endpointDescriptor: USB.EndpointDescriptor) -> USBPipe { 55 | fatalError("xhci: allocatePipe not implemented") 56 | } 57 | 58 | func pollInterrupt() -> Bool { 59 | return false 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /kernel/devices/usb/hcd-xhci.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/usb/hcd-uhci.swift 3 | * 4 | * Created by Simon Evans on 05/10/2020. 5 | * Copyright © 2015 - 2020 Simon Evans. All rights reserved. 6 | * 7 | * XHCI HCD driver. 8 | * 9 | */ 10 | 11 | 12 | final class HCD_XHCI: PCIDeviceDriver, USBHCD, CustomStringConvertible { 13 | private let pciDevice: PCIDevice // The device (upstream) side of the bridge 14 | private let baseAddress: UInt32 15 | 16 | var description: String { "XHCI driver @ 0x\(String(baseAddress, radix: 16))" } 17 | 18 | 19 | init?(pciDevice: PCIDevice) { 20 | print("XHCI init") 21 | guard pciDevice.deviceFunction.deviceClass == PCIDeviceClass(classCode: .serialBusController, 22 | subClassCode: PCISerialBusControllerSubClass.usb.rawValue, 23 | progInterface: PCIUSBProgrammingInterace.xhci.rawValue) else { 24 | print("XHCI: \(pciDevice) is not an XHCI Device") 25 | return nil 26 | } 27 | 28 | guard let generalDevice = pciDevice.deviceFunction.generalDevice else { 29 | print("XHCI: Not a PCI generalDevice") 30 | return nil 31 | } 32 | 33 | let base = generalDevice.bar0 34 | guard base & 1 == 0 else { 35 | print("XHCI: BAR0 address 0x\(String(base, radix: 16)) is not a memory resource") 36 | return nil 37 | } 38 | 39 | self.pciDevice = pciDevice 40 | baseAddress = base & 0xffff_ff00 41 | print("XHCI: 0x\(String(baseAddress, radix: 16))") 42 | } 43 | 44 | 45 | func initialise() -> Bool { 46 | print("XHCI driver") 47 | let sbrn = pciDevice.deviceFunction.readConfigByte(atByteOffset: 0x60) 48 | print("XHCI: bus release number 0x\(String(sbrn, radix: 16))") 49 | return false 50 | } 51 | 52 | 53 | func allocatePipe(device: USBDevice, endpointDescriptor: USB.EndpointDescriptor) -> USBPipe { 54 | fatalError("xhci: allocatePipe not implemented") 55 | } 56 | 57 | func pollInterrupt() -> Bool { 58 | return false 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /kernel/devices/usb/usb-devicedescriptor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/usb/usb-devicedescriptor.swift 3 | * 4 | * Created by Simon Evans on 22/10/2020. 5 | * Copyright © 2020 Simon Evans. All rights reserved. 6 | * 7 | * USB Device Descriptor. 8 | * 9 | */ 10 | 11 | 12 | extension USB { 13 | 14 | enum DeviceClass: UInt8 { 15 | case interfaceSpecific = 0x00 16 | case communications = 0x02 17 | case hub = 0x09 18 | case billboard = 0x11 19 | case diagnosticDevice = 0xDC 20 | case miscellaneous = 0xEF 21 | case vendorSpecific = 0xFF 22 | } 23 | 24 | struct DeviceDescriptor: CustomStringConvertible { 25 | private let descriptor: usb_standard_device_descriptor 26 | 27 | var description: String { 28 | let dc = (deviceClass != nil) ? String(describing: deviceClass!) : "unknown" 29 | return "bcdUSB: 0x\(String(bcdUSB, radix: 16)) bDeviceClass: \(String(bDeviceClass, radix: 16)) bDeviceSubClass: \(String(bDeviceSubClass, radix: 16))" 30 | + " bDeviceProtocol: \(String(bDeviceProtocol, radix: 16)) bMaxPacketSize0: \(String(bMaxPacketSize0)) class: \(dc)" 31 | } 32 | 33 | var bLength: UInt8 { descriptor.bLength } 34 | var bDescriptorType: DescriptorType { DescriptorType(rawValue: descriptor.bDescriptorType)! } 35 | var bcdUSB: UInt16 { descriptor.bcdUSB } 36 | var bDeviceClass: UInt8 { descriptor.bDeviceClass } 37 | var bDeviceSubClass: UInt8 { descriptor.bDeviceSubClass } 38 | var bDeviceProtocol: UInt8 { descriptor.bDeviceProtocol } 39 | var bMaxPacketSize0: UInt8 { descriptor.bMaxPacketSize0 } 40 | var idVendor: UInt16 { descriptor.idVendor } 41 | var idProduct: UInt16 { descriptor.idProduct } 42 | var bcdDevice: UInt16 { descriptor.bcdDevice } 43 | var iManufacturer: UInt8 { descriptor.iManufacturer } 44 | var iProduct: UInt8 { descriptor.iProduct } 45 | var iSerialNumber: UInt8 { descriptor.iSerialNumber } 46 | var bNumConfigurations: UInt8 { descriptor.bNumConfigurations } 47 | 48 | var deviceClass: DeviceClass? { DeviceClass(rawValue: bDeviceClass) } 49 | 50 | 51 | // Pass in a buffer that maybe shorter than a full packet 52 | init(from buffer: MMIOSubRegion) { 53 | precondition(buffer.count >= 8) 54 | precondition(buffer.count <= MemoryLayout.size) 55 | 56 | var _descriptor = usb_standard_device_descriptor() 57 | withUnsafeMutableBytes(of: &_descriptor) { 58 | for idx in 0...size else { 38 | throw ParsingError.packetTooShort 39 | } 40 | 41 | // Validate the initial bytes 42 | guard Int(buffer[0]) == MemoryLayout.size else { throw ParsingError.invalidLengthByte } 43 | guard buffer[1] == USB.DescriptorType.CONFIGURATION.rawValue else { throw ParsingError.invalidDescriptor(buffer[1]) } 44 | 45 | var _descriptor = usb_device_qualifier() 46 | withUnsafeMutableBytes(of: &_descriptor) { 47 | assert(MemoryLayout.size == $0.count) 48 | 49 | for idx in 0..<$0.count { 50 | $0[idx] = buffer[0] 51 | } 52 | } 53 | descriptor = _descriptor 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /kernel/devices/usb/usb-hiddescriptor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/usb/usb-hiddescriptor.swift 3 | * 4 | * Created by Simon Evans on 27/10/2020. 5 | * Copyright © 2020 Simon Evans. All rights reserved. 6 | * 7 | * USB HID Descriptor. 8 | * 9 | */ 10 | 11 | 12 | extension USB { 13 | 14 | struct HIDDescriptor: CustomStringConvertible { 15 | private let descriptor: usb_hid_descriptor 16 | 17 | var bLength: UInt8 { descriptor.bLength } 18 | var bDescriptorType: UInt8 { descriptor.bDescriptorType } 19 | var bcdHID: UInt16 { descriptor.bcdHID } 20 | var bCountryCode: UInt8 { descriptor.bCountryCode } 21 | var bNumDescriptors: UInt8 { descriptor.bNumDescriptors } 22 | var bReportDescriptorType: UInt8 { descriptor.bReportDescriptorType } 23 | var wDescriptorLength: UInt16 { descriptor.wDescriptorLength } 24 | 25 | var description: String { 26 | let version = "\(String(bcdHID >> 8, radix: 16)).\(String(bcdHID & 0xff, radix: 16))" 27 | return "HID: v\(version) country: \(bCountryCode)" 28 | } 29 | 30 | 31 | init(from iterator: inout MMIOSubRegion.Iterator) throws { 32 | // Validate the initial bytes 33 | guard let lengthByte = iterator.next(), let descriptorByte = iterator.next() else { throw ParsingError.packetTooShort } 34 | guard Int(lengthByte) == MemoryLayout.size else { throw ParsingError.invalidLengthByte } 35 | guard descriptorByte == USB.DescriptorType.HID.rawValue else { throw ParsingError.invalidDescriptor(descriptorByte) } 36 | 37 | var _descriptor = usb_hid_descriptor() 38 | try withUnsafeMutableBytes(of: &_descriptor) { 39 | assert(MemoryLayout.size == $0.count) 40 | $0[0] = lengthByte 41 | $0[1] = descriptorByte 42 | 43 | for idx in 2..<$0.count { 44 | guard let byte = iterator.next() else { throw ParsingError.packetTooShort } 45 | $0[idx] = byte 46 | } 47 | } 48 | 49 | descriptor = _descriptor 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /kernel/devices/usb/usb-hub.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/devices/usb/usb-hub.swift 3 | * 4 | * Created by Simon Evans on 22/10/2020. 5 | * Copyright © 2020 Simon Evans. All rights reserved. 6 | * 7 | * USB Hub 8 | * 9 | */ 10 | 11 | 12 | final class USBHubDevice { 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /kernel/init/bss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/init/bss.c 3 | * 4 | * Created by Simon Evans on 01/01/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * BSS declarations for data structures that cant be declared directly 8 | * in Swift as they require alignment, packing etc. Also C fixed size 9 | * arrays cant currently be declared either in Swift at the moment 10 | * 11 | */ 12 | 13 | #include "klibc.h" 14 | #include "mm.h" 15 | 16 | #define bss_page __attribute__((__section__(".bss..allocated_pages"))) __attribute__((aligned(PAGE_SIZE))) 17 | 18 | // Interrupt Descriptor Table - Swift doesnt support fixed length arrays yet 19 | struct idt_entry idt[NR_INTERRUPTS] bss_page; 20 | // The dispatch table from the IDT stubs to the actual handlers 21 | void (*trap_dispatch_table[NR_TRAPS])(struct exception_regs *); 22 | void (*irq_dispatch_table[NR_IRQS])(); 23 | 24 | #define PAGE_TABLE_SIZE 4096 25 | 26 | uint8_t initial_pml4[PAGE_TABLE_SIZE] bss_page; 27 | uint8_t physmap_pml3[PAGE_TABLE_SIZE] bss_page; 28 | uint8_t kernmap_pml3[PAGE_TABLE_SIZE] bss_page; 29 | uint8_t physmap_pml2[PAGE_TABLE_SIZE] bss_page; 30 | uint8_t kernmap_pml2[PAGE_TABLE_SIZE] bss_page; 31 | uint8_t physmap_pml1[PAGE_TABLE_SIZE][8] bss_page; 32 | uint8_t kernmap_pml1[PAGE_TABLE_SIZE][8] bss_page; 33 | 34 | 35 | #define EXPORT_SYMBOL_TO_SWIFT(x) const void *x##_addr = &x; 36 | 37 | EXPORT_SYMBOL_TO_SWIFT(irq_dispatch_table) 38 | -------------------------------------------------------------------------------- /kernel/init/startup.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/init/startup.swift 3 | * 4 | * Created by Simon Evans on 12/12/2015. 5 | * Copyright © 2015 Simon Evans. All rights reserved. 6 | * 7 | * Simple test hello world 8 | * 9 | */ 10 | 11 | 12 | fileprivate(set) var system: System! 13 | 14 | @_silgen_name("startup") 15 | public func startup(bootParamsAddr: UInt) { 16 | system = System(bootParamsAddr: bootParamsAddr) 17 | system.initSystem() 18 | system.runSystem() 19 | koops("kernel: Shouldnt get here") 20 | } 21 | 22 | 23 | final class System { 24 | let systemTables: SystemTables 25 | let deviceManager: DeviceManager 26 | let bootParams: BootParams 27 | 28 | init(bootParamsAddr: RawAddress) { 29 | // Setup GDT/IDT as early as possible to help catch CPU exceptions 30 | setupGDT() 31 | setupIDT() 32 | CPU.getInfo() 33 | // BootParams must come first to find memory regions for MM 34 | bootParams = parse(bootParamsAddr: VirtualAddress(bootParamsAddr)) 35 | // Setup the new page tables and add the free RAM to the free list so that 36 | // ACPI parsing etc has more memory available. 37 | setupMM(bootParams: bootParams) 38 | 39 | // SystemTables() needs the MM setup so that the memory can be mapped. This will also parse 40 | // all of the ACPI tables including the DSDT. 41 | systemTables = SystemTables(bootParams: bootParams) 42 | // symbolLookupInit uses a sort() so may require more free memory, do it after all the free 43 | // RAM has been added to the free list. 44 | symbolLookupInit(bootParams: bootParams) 45 | deviceManager = DeviceManager(acpiTables: systemTables.acpiTables) 46 | } 47 | 48 | fileprivate func initSystem() { 49 | CPU.getInfo() 50 | deviceManager.initialiseEarlyDevices() 51 | 52 | // gitBuildVersion defined in kernel/init/version.swift, created 53 | // by kernel/Makefile 54 | print("Version: \(gitBuildVersion)\n") 55 | } 56 | 57 | 58 | fileprivate func runSystem() { 59 | addTask(name: "IRQ Queue runner", task: mainLoop) 60 | addTask(name: "KeyboardInput", task: keyboardInput) 61 | run_first_task() // This jumps straight into mainLoop 62 | } 63 | } 64 | 65 | 66 | func benchmark(_ function: () -> ()) -> UInt64 { 67 | let t0 = rdtsc() 68 | function() 69 | return rdtsc() - t0 70 | } 71 | 72 | 73 | fileprivate func mainLoop() { 74 | let interruptManager = system.deviceManager.interruptManager 75 | // Idle, woken up by interrupts 76 | interruptManager.enableIRQs() 77 | system.deviceManager.initialiseDevices() 78 | 79 | while true { 80 | hlt() 81 | yield() 82 | } 83 | } 84 | 85 | 86 | fileprivate func keyboardInput() { 87 | // Try reading from the keyboard otherwise just pause forever 88 | // (used for testing on macbook where there is no PS/2 keyboard) 89 | 90 | commandShell() 91 | print("commandShell exited") 92 | if system.deviceManager.keyboard == nil { 93 | print("Devices:") 94 | system.deviceManager.dumpDevices() 95 | } 96 | 97 | print("HLTing") 98 | while true { 99 | hlt() 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /kernel/klib/CircularBuffer.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/klib/CircularBuffer.swift 3 | * 4 | * Created by Simon Evans on 05/03/2017. 5 | * Copyright © 2017 Simon Evans. All rights reserved. 6 | * 7 | * Simple circular buffer implementation. 8 | * 9 | */ 10 | 11 | // TODO: Add sleep/wask of consumer. 12 | 13 | final class CircularBuffer { 14 | private var buffer: Array 15 | private let capacity: Int 16 | private var idxIn = 0, idxOut = 0, count = 0 17 | 18 | init(item: T, capacity: Int) { 19 | self.capacity = capacity 20 | buffer = Array(repeating: item, count: capacity) 21 | } 22 | 23 | func clear() { 24 | idxIn = 0 25 | idxOut = 0 26 | count = 0 27 | } 28 | 29 | func add(_ item: T) -> Bool { 30 | return noInterrupt { 31 | guard count < capacity else { 32 | return false 33 | } 34 | buffer[idxIn] = item 35 | count += 1 36 | idxIn += 1 37 | if idxIn == capacity { 38 | idxIn = 0 39 | } 40 | return true 41 | } 42 | } 43 | 44 | func remove() -> T? { 45 | return noInterrupt { 46 | guard count > 0 else { 47 | return nil 48 | } 49 | let result = buffer[idxOut] 50 | count -= 1 51 | idxOut += 1 52 | if idxOut == capacity { 53 | idxOut = 0 54 | } 55 | return result 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /kernel/klib/ReservationManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReservationManager.swift 3 | // acpi 4 | // 5 | // Created by Simon Evans on 06/12/2017. 6 | // Copyright © 2017 Simon Evans. All rights reserved. 7 | // 8 | 9 | 10 | struct ReservedSpace: CustomStringConvertible { 11 | let name: String 12 | let start: UInt 13 | let end: UInt 14 | 15 | var description: String { 16 | if start == end { 17 | return "\(name): 0x\(String(start, radix: 16))" 18 | } else { 19 | return "\(name): 0x\(String(start, radix: 16)) - 0x\(String(end, radix: 16))" 20 | } 21 | } 22 | } 23 | 24 | struct ReservationSpace { 25 | let name: String 26 | let start: UInt 27 | let end: UInt 28 | var reservedSpaces: [ReservedSpace] 29 | 30 | init(name: String, start: UInt, end: UInt) { 31 | self.name = name 32 | self.start = start 33 | self.end = end 34 | reservedSpaces = [] 35 | } 36 | 37 | mutating func reserveSpace(name: String, start: UInt, end: UInt) -> Bool { 38 | precondition(end >= start) 39 | if start < self.start || end > self.end { 40 | return false 41 | } 42 | 43 | // Look through the ranges already reserved and check there is no overlap 44 | // FIXME: use a better lookup 45 | for idx in reservedSpaces.startIndex..= reservedSpaces[idx].start && start <= reservedSpaces[idx].end) || 47 | (end >= reservedSpaces[idx].start && end <= reservedSpaces[idx].end) { 48 | return false 49 | } 50 | } 51 | let newSpace = ReservedSpace(name: name, start: start, end: end) 52 | reservedSpaces.append(newSpace) 53 | return true 54 | } 55 | 56 | func showReservedSpaces() { 57 | for space in reservedSpaces.sorted(by: { $0.start < $1.start }) { 58 | print(space) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /kernel/mm/PageMapLevel4Table.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/mm/PageMapLevel4Table.swift 3 | * 4 | * Created by Simon Evans on 14/11/2021. 5 | * Copyright © 2021 Simon Evans. All rights reserved. 6 | * 7 | * PML4 Table. 8 | * 9 | */ 10 | 11 | 12 | private let entriesPerTable = 512 13 | // 4K aligned page table physical address mask 14 | private let pageTableAddressMask: RawAddress = 0x0000_ffff_ffff_f000 15 | 16 | struct PageMapLevel4Table { 17 | private let table: UnsafeMutableBufferPointer 18 | 19 | init(at address: VirtualAddress) { 20 | let ptr = UnsafeMutablePointer(bitPattern: address) 21 | table = UnsafeMutableBufferPointer(start: ptr, count: entriesPerTable) 22 | } 23 | 24 | init(at address: PhysAddress) { 25 | self = PageMapLevel4Table(at: PhysAddress(address.value & ~0xfff).vaddr) 26 | } 27 | 28 | subscript(index: Int) -> PageMapLevel4Entry { 29 | get { table[index] } 30 | set { table[index] = newValue } 31 | } 32 | 33 | func pageDirectoryPointerTable(at index: Int, readWrite: Bool, userAccess: Bool, writeThrough: Bool, cacheDisable: Bool, noExec: Bool) 34 | -> PageDirectoryPointerTable { 35 | if let dir = table[index].pageDirectoryPointerTable { return dir } 36 | let newPage = alloc(pages: 1) 37 | newPage.rawBufferPointer.initializeMemory(as: UInt8.self, repeating: 0) 38 | let paddr = newPage.baseAddress 39 | let entry = PageMapLevel4Entry(address: paddr, readWrite: readWrite, userAccess: userAccess, 40 | writeThrough: writeThrough, cacheDisable: cacheDisable, noExec: noExec) 41 | table[index] = entry 42 | return entry.pageDirectoryPointerTable! 43 | } 44 | } 45 | 46 | 47 | // This is a PML4 Entry which acts as a directory of PageDirectoryPageTableEntries (PDPTE) 48 | struct PageMapLevel4Entry { 49 | private let bits: BitArray64 50 | 51 | 52 | init (address: PhysAddress, readWrite: Bool, userAccess: Bool, 53 | writeThrough: Bool, cacheDisable: Bool, noExec: Bool) { 54 | 55 | precondition(address & pageTableAddressMask == address) 56 | 57 | var bits = BitArray64(address.value) 58 | bits[0] = 1 59 | bits[1] = readWrite ? 1 : 0 60 | bits[2] = userAccess ? 1 : 0 61 | bits[3] = writeThrough ? 1 : 0 62 | bits[4] = cacheDisable ? 1 : 0 63 | bits[63] = noExec ? 1 : 0 64 | self.bits = bits 65 | } 66 | 67 | var present: Bool { Bool(bits[0]) } 68 | var readWrite: Bool { Bool(bits[1]) } 69 | var userAccess: Bool { Bool(bits[2]) } 70 | var writeThrough: Bool { Bool(bits[3]) } 71 | var cacheDisable: Bool { Bool(bits[4]) } 72 | var accessed: Bool { Bool(bits[5]) } 73 | var physicalAddress: PhysAddress { PhysAddress(RawAddress(bits.rawValue) & pageTableAddressMask) } 74 | var executeDisable: Bool { Bool(bits[63]) } 75 | 76 | var pageDirectoryPointerTable: PageDirectoryPointerTable? { 77 | guard present else { return nil } 78 | let ptr = UnsafeMutablePointer(bitPattern: physicalAddress.vaddr)! 79 | return PageDirectoryPointerTable(start: ptr) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /kernel/mm/PageSize.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/mm/PageSize.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 25/12/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | struct PageSize: Equatable { 10 | let size: UInt 11 | 12 | init(_ size: UInt) { 13 | precondition(size.nonzeroBitCount == 1) // Must be power of 2 14 | precondition(size >= 1024) 15 | self.size = size 16 | } 17 | 18 | init() { 19 | self.size = UInt(PAGE_SIZE) 20 | } 21 | 22 | init(encoding: Int) { 23 | switch encoding { 24 | case 1: self.size = 4096 25 | case 2: self.size = 2048 * 1024 26 | case 3: self.size = 1024 * 1024 * 1024 27 | default: fatalError("Invalid Page size") 28 | } 29 | } 30 | 31 | var mask: UInt { ~(size - 1) } 32 | 33 | var encoding: Int { 34 | switch size { 35 | case 4096: return 1 36 | case 2048 * 1024: return 2 37 | case 1024 * 1024 * 1024: return 3 38 | default: fatalError("Invalid page size: \(size)") 39 | } 40 | } 41 | 42 | func isPageAligned(_ address: UInt) -> Bool { 43 | address & ~mask == 0 44 | } 45 | 46 | func roundDown(_ address: UInt) -> UInt { 47 | address & mask 48 | } 49 | 50 | func roundToNextPage(_ address: UInt) -> UInt { 51 | (address + (size - 1)) & mask 52 | } 53 | 54 | func lastAddressInPage(_ address: UInt) -> UInt { 55 | address | ~mask 56 | } 57 | 58 | func onSamePage(_ address1: UInt, _ address2: UInt) -> Bool { 59 | address1 & mask == address2 & mask 60 | } 61 | 62 | func pageCountCovering(size: Int) -> Int { 63 | return ((size - 1) + Int(self.size)) / Int(self.size) 64 | } 65 | 66 | func regionSize(forPageCount pages: Int) -> UInt { 67 | size * UInt(pages) 68 | } 69 | 70 | func offsetInPage(_ address: UInt) -> UInt { 71 | address & ~mask 72 | } 73 | } 74 | 75 | extension PageSize: Comparable { 76 | static func < (lhs: PageSize, rhs: PageSize) -> Bool { 77 | lhs.size < rhs.size 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /kernel/mm/PhysRegion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/mm/PhysRegion.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 15/01/2022. 6 | // Copyright © 2022 Simon Evans. All rights reserved. 7 | // 8 | 9 | struct PhysRegion { 10 | let baseAddress: PhysAddress 11 | let size: UInt 12 | 13 | init(start: PhysAddress, size: UInt) { 14 | precondition(size > 0) 15 | self.baseAddress = start 16 | self.size = size 17 | } 18 | 19 | init(start: PhysAddress, end: PhysAddress) { 20 | precondition(start <= end) 21 | baseAddress = start 22 | size = UInt(end - start) + 1 23 | } 24 | 25 | init(_ region: PhysPageAlignedRegion) { 26 | self.baseAddress = region.baseAddress 27 | self.size = region.size 28 | } 29 | 30 | var endAddress: PhysAddress { baseAddress + (size - 1) } 31 | var physPageAlignedRegion: PhysPageAlignedRegion { 32 | PhysPageAlignedRegion(start: baseAddress, size: size, pageSize: PageSize()) 33 | } 34 | 35 | func contains(_ other: Self) -> Bool { 36 | return baseAddress <= other.baseAddress && endAddress >= other.endAddress 37 | } 38 | } 39 | 40 | #if TEST 41 | import Foundation 42 | 43 | extension PhysRegion { 44 | // For testing, create a region with some data in to emulate firmware etc 45 | // This will leak but its only used for testing so keeping the data around 46 | // until the end of the tests is fine. 47 | init(data: Data) { 48 | var ptr: UnsafeMutableRawPointer? = nil 49 | let err = posix_memalign(&ptr, Int(PageSize().size), data.count) 50 | guard err == 0, let ptr2 = ptr else { 51 | fatalError("posix_mmalign, size: \(data.count) failed: \(err)") 52 | } 53 | let dest = ptr2.bindMemory(to: UInt8.self, capacity: data.count) 54 | data.copyBytes(to: UnsafeMutablePointer(dest), count: data.count) 55 | let address = dest.address 56 | self.baseAddress = PhysAddress(address - PHYSICAL_MEM_BASE) 57 | self.size = UInt(data.count) 58 | } 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /kernel/mm/page.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/mm/page.swift 3 | * 4 | * Created by Simon Evans on 22/01/2016. 5 | * Copyright © 2016 - 2017 Simon Evans. All rights reserved. 6 | * 7 | * Page handling routines 8 | * 9 | */ 10 | 11 | 12 | private let entriesPerPage: UInt = 512 13 | private let entriesPerPageMask: UInt = entriesPerPage - 1 14 | 15 | 16 | func virtualToPhys(address: VirtualAddress, base: UInt64 = getCR3()) -> PhysAddress? { 17 | // Quick lookups in premapped areas 18 | if address >= PHYSICAL_MEM_BASE && address < PHYSICAL_MEM_BASE + 0x400_000_000_000 { // 64TB window 19 | return PhysAddress(address - PHYSICAL_MEM_BASE) 20 | } 21 | if address >= _kernel_start_addr && address < _kernel_end_addr { 22 | if kernelPhysBase.value != 0 { 23 | return kernelPhysBase.advanced(by: address - _kernel_start_addr) 24 | } 25 | } 26 | 27 | // Otherwise walk the page tables 28 | let pml4 = PhysAddress(RawAddress(base)) 29 | 30 | let pageDirectory = PageMapLevel4Table(at: pml4) 31 | let idx0 = pml4Index(address) 32 | let pml4e = pageDirectory[idx0] 33 | 34 | let idx1 = pdpIndex(address) 35 | guard let pdpte = pml4e.pageDirectoryPointerTable?[idx1] else { return nil } 36 | if let physAddress = pdpte.largePageAddress { // 1GB Pages 37 | return physAddress + (address & 0x3_ffff_ffff) 38 | } 39 | 40 | let idx2 = pdIndex(address) 41 | guard let pde = pdpte.pageDirectory?[idx2] else { return nil } 42 | if let physAddress = pde.largePageAddress { // 2MB Pages 43 | return physAddress + (address & 0x1f_ffff) 44 | } 45 | 46 | let idx3 = ptIndex(address) 47 | guard let pageAddress = pde.pageTable?[idx3].pageAddress else { return nil } 48 | return pageAddress + (address & 0x0fff) 49 | } 50 | 51 | func pml4Index(_ address: VirtualAddress) -> Int { 52 | return Int((address >> 39) & entriesPerPageMask) 53 | } 54 | 55 | func pdpIndex(_ address: VirtualAddress) -> Int { 56 | return Int((address >> 30) & entriesPerPageMask) 57 | } 58 | 59 | func pdIndex(_ address: VirtualAddress) -> Int { 60 | return Int((address >> 21) & entriesPerPageMask) 61 | } 62 | 63 | func ptIndex(_ address: VirtualAddress) -> Int { 64 | return Int((address >> 12) & entriesPerPageMask) 65 | } 66 | -------------------------------------------------------------------------------- /kernel/tasks/tests.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * kernel/init/tests.swift 3 | * 4 | * Created by Simon Evans on 30/12/2021. 5 | * Copyright © 2021 Simon Evans. All rights reserved. 6 | * 7 | * Random test routines to test subsystems during boot and intialisation. 8 | * 9 | */ 10 | 11 | public func cacheTest() { 12 | let buffer = alloc(pages: 1) 13 | print("cacheTest buffer:", buffer) 14 | if buffer.baseAddress.value < 0x100000 || buffer.endAddress.value > 0x1000000 { 15 | fatalError("Cache test page not in correct region") 16 | } 17 | let start = UnsafeMutablePointer(bitPattern: buffer.vaddr) 18 | let count = buffer.size 19 | printf("Testing default\n") 20 | for _ in 1...3 { 21 | let read = _cacheReadTest(start, UInt64(count), nil) 22 | let write = _cacheWriteTest(start, UInt64(count), 1) 23 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 24 | } 25 | printf("Testing uncacheable\n") 26 | _ = remapAsIORegion(region: buffer, cacheType: .uncacheable) 27 | for _ in 1...3 { 28 | let read = _cacheReadTest(start, UInt64(count), nil) 29 | let write = _cacheWriteTest(start, UInt64(count), 1) 30 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 31 | } 32 | printf("Testing writeBack\n") 33 | _ = remapAsIORegion(region: buffer, cacheType: .writeBack) 34 | for _ in 1...3 { 35 | let read = _cacheReadTest(start, UInt64(count), nil) 36 | let write = _cacheWriteTest(start, UInt64(count), 1) 37 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 38 | } 39 | printf("Testing writeThrough\n") 40 | _ = remapAsIORegion(region: buffer, cacheType: .writeThrough) 41 | for _ in 1...3 { 42 | let read = _cacheReadTest(start, UInt64(count), nil) 43 | let write = _cacheWriteTest(start, UInt64(count), 1) 44 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 45 | } 46 | printf("Testing writeCombining\n") 47 | _ = remapAsIORegion(region: buffer, cacheType: .writeCombining) 48 | for _ in 1...3 { 49 | let read = _cacheReadTest(start, UInt64(count), nil) 50 | let write = _cacheWriteTest(start, UInt64(count), 1) 51 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 52 | } 53 | _ = remapAsIORegion(region: buffer, cacheType: .writeBack) 54 | freePages(pages: buffer) 55 | 56 | let ioBuffer = allocIOPage() 57 | let ioStart = UnsafeMutablePointer(bitPattern: ioBuffer.vaddr) 58 | let ioCount = ioBuffer.size 59 | printf("Testing IO Page\n") 60 | for _ in 1...3 { 61 | let read = _cacheReadTest(ioStart, UInt64(ioCount), nil) 62 | let write = _cacheWriteTest(ioStart, UInt64(ioCount), 1) 63 | printf("Timing to read buffer: %lu write: %lu\n", read, write) 64 | } 65 | freeIOPage(ioBuffer) 66 | } 67 | 68 | func sleepTest(milliseconds: Int) { 69 | // sleepTest 70 | if let cmos = system.deviceManager.rtc { 71 | print(milliseconds, "ms sleep test") 72 | print(cmos.readTime()) 73 | sleep(milliseconds: milliseconds) 74 | print(cmos.readTime()) 75 | } 76 | } 77 | 78 | func dateTest() { 79 | if let cmos = system.deviceManager.rtc { 80 | print(cmos.readTime()) 81 | } else { 82 | print("Cant find a RTC") 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /kernel/traps/IRQSetting.swift: -------------------------------------------------------------------------------- 1 | // 2 | // kernel/traps/IRQSetting.swift 3 | // project1 4 | // 5 | // Created by Simon Evans on 04/05/2021. 6 | // Copyright © 2021 Simon Evans. All rights reserved. 7 | // 8 | 9 | // Describes a hardware interrupt. The interrupt pin may be an IRQ or a 10 | // GSI (Global System Interrupt). The only difference is that an IRQ may need 11 | // to be remapped according to possible MADT.InterruptSourceOverrideTable entries. 12 | struct IRQSetting: CustomStringConvertible { 13 | 14 | private let bits: BitArray16 15 | 16 | // IRQ: Interrupt Request, will need to be mapped to a GSI before use. 17 | init(irq: UInt8, activeHigh: Bool, levelTriggered: Bool, shared: Bool, wakeCapable: Bool) { 18 | var _bits = BitArray16(UInt16(irq)) // bits 0-7 19 | _bits[8] = activeHigh ? 1 : 0 20 | _bits[9] = levelTriggered ? 1 : 0 21 | _bits[10] = shared ? 1 : 0 22 | _bits[11] = wakeCapable ? 1 : 0 23 | _bits[12] = 1 // isIRQ 24 | bits = _bits 25 | } 26 | 27 | // GSI: Global System Interrupt. 28 | init(gsi: UInt32, activeHigh: Bool, levelTriggered: Bool, shared: Bool, wakeCapable: Bool) { 29 | var _bits = BitArray16(UInt16(gsi)) // bits 0-7 30 | _bits[8] = activeHigh ? 1 : 0 31 | _bits[9] = levelTriggered ? 1 : 0 32 | _bits[10] = shared ? 1 : 0 33 | _bits[11] = wakeCapable ? 1 : 0 34 | _bits[12] = 0 // isGSI 35 | bits = _bits 36 | } 37 | 38 | init(isaIrq: UInt8) { 39 | // Active high, edge triggered, not shared, not wake capable, isIRQ 40 | var _bits = BitArray16(UInt16(isaIrq)) // bits 0-7 41 | _bits[8] = 1 42 | _bits[12] = 1 // isIRQ 43 | bits = _bits 44 | } 45 | 46 | var description: String { "\(isGSI ? "GSI" : "IRQ")\(irq) activeHigh: \(activeHigh) levelTrig: \(levelTriggered) shared: \(shared) wake: \(wakeCapable)" } 47 | 48 | var irq: Int { Int(bits[0...7]) } 49 | var activeHigh: Bool { Bool(bits[8]) } 50 | var levelTriggered: Bool { Bool(bits[9]) } 51 | var egdeTriggered: Bool { !levelTriggered } 52 | var shared: Bool { Bool(bits[10]) } 53 | var wakeCapable: Bool { Bool(bits[11]) } 54 | var isIRQ: Bool { Bool(bits[12]) } 55 | var isGSI: Bool { !isIRQ } 56 | } 57 | -------------------------------------------------------------------------------- /kernel/vm/vmentry.asm: -------------------------------------------------------------------------------- 1 | ;;; kernel/vm/vmentry.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 20/07/2019. 4 | ;;; Copyright © 2019 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; Entry point for calling vmlaunch, vmentry and vmexit 7 | 8 | 9 | BITS 64 10 | 11 | DEFAULT REL 12 | SECTION .text 13 | 14 | global vmentry 15 | global vmreturn 16 | 17 | 18 | LAUNCHED EQU 0 19 | VMEXIT_STATUS EQU 1 20 | VCPU_REGS EQU 24 21 | 22 | ;; RDI => struct vpcu 23 | vmentry: 24 | push rbp 25 | push rbx 26 | push r12 27 | push r13 28 | push r14 29 | push r15 30 | push rdi 31 | 32 | push rdi ; Extra storage to save RDI after vmreturn 33 | ;; Save RSP to be restored on VM exit 34 | mov rdx, 0x6C14 ; HOST_RSP 35 | vmwrite rdx, rsp 36 | mov rdx, 0x6C16 37 | mov rbx, vmentry.entered 38 | vmwrite rdx, rbx 39 | 40 | ;; Load guest registers 41 | mov rax, [rdi + VCPU_REGS + 0] 42 | mov rbx, [rdi + VCPU_REGS + 8] 43 | mov rcx, [rdi + VCPU_REGS + 16] 44 | mov rdx, [rdi + VCPU_REGS + 24] 45 | mov rsi, [rdi + VCPU_REGS + 40] 46 | mov rbp, [rdi + VCPU_REGS + 48] 47 | mov r8, [rdi + VCPU_REGS + 56] 48 | mov r9, [rdi + VCPU_REGS + 64] 49 | mov r10, [rdi + VCPU_REGS + 72] 50 | mov r11, [rdi + VCPU_REGS + 80] 51 | mov r12, [rdi + VCPU_REGS + 88] 52 | mov r13, [rdi + VCPU_REGS + 96] 53 | mov r14, [rdi + VCPU_REGS + 104] 54 | mov r15, [rdi + VCPU_REGS + 112] 55 | 56 | cmp BYTE [rdi + LAUNCHED], 1 57 | mov rdi, [rdi + VCPU_REGS + 32] 58 | je .resume 59 | vmlaunch 60 | jmp .entered 61 | .resume: 62 | vmresume 63 | 64 | .entered: 65 | ;; save guest RDI to stack 66 | mov [rsp + 8], rdi 67 | pop rdi 68 | pop QWORD [rdi + VCPU_REGS + 32] 69 | ;; Save ZF/CF 70 | setbe BYTE [rdi + VMEXIT_STATUS] 71 | ;; Save guest registers 72 | mov [rdi + VCPU_REGS + 112], r15 73 | mov [rdi + VCPU_REGS + 104], r14 74 | mov [rdi + VCPU_REGS + 96], r13 75 | mov [rdi + VCPU_REGS + 88], r12 76 | mov [rdi + VCPU_REGS + 80], r11 77 | mov [rdi + VCPU_REGS + 72], r10 78 | mov [rdi + VCPU_REGS + 64], r9 79 | mov [rdi + VCPU_REGS + 56], r8 80 | mov [rdi + VCPU_REGS + 48], rbp 81 | mov [rdi + VCPU_REGS + 40], rsi 82 | mov [rdi + VCPU_REGS + 24], rdx 83 | mov [rdi + VCPU_REGS + 16], rcx 84 | mov [rdi + VCPU_REGS + 8], rbx 85 | mov [rdi + VCPU_REGS + 0], rax 86 | pushf 87 | pop rax 88 | and rax, 0x41 89 | mov BYTE [rdi + VMEXIT_STATUS], al 90 | 91 | pop r15 92 | pop r14 93 | pop r13 94 | pop r12 95 | pop rbx 96 | pop rbp 97 | ret 98 | -------------------------------------------------------------------------------- /klibc/Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR := .. 2 | include $(TOPDIR)/Makedefs 3 | 4 | OBJS := misc.o string.o io.o kprintf.o printf.o pthread.o \ 5 | libcpp.o x86_string.o x86_misc.o koops.o early_tty.o malloc.o \ 6 | std_cxx11_string.o 7 | 8 | all: klibc.o 9 | 10 | klibc.o: $(OBJS) ../include/klibc.h ../include/x86funcs.h ../include/x86defs.h ../include/mm.h 11 | ld -r -no_eh_labels -o $@ $(OBJS) 12 | 13 | clean: 14 | rm -f *.o *.s 15 | -------------------------------------------------------------------------------- /klibc/README.md: -------------------------------------------------------------------------------- 1 | klibc is the interface between Swift's stdlib and the underlying hardware. 2 | It exports the functions that are needed in libc/libc++ and matches the glibc 3 | versions since the stdlib is compiled on Linux. The functions fall into three 4 | categories: 5 | 6 | 1. Unimplemented. Print a message and halt. These are not always needed or can 7 | be implemented later. 8 | 9 | 2. Bare minimum implementation. Sometimes these are written to provide just 10 | enough for stdlib to work and expect specific parameters, eg `write` and 11 | `fprintf` which only accept stdout and stder as output channels. 12 | 13 | 3. Full implementations. These often wrap functions provided in other parts 14 | of the code, eg `printf` or `vasprintf`. 15 | 16 | 17 | Some functions are also required by other parts of the kernel, eg `malloc/free` 18 | etc 19 | 20 | Since a special build of Swift / stdlib is used, some functionality has been 21 | removed eg Math functions `sin`, `cos` etc. This has been done by removing the 22 | files from the Stdlib CMakeLists.txt. Some more files may be removed in the 23 | future if the functionality isnt needed. 24 | 25 | 26 | The eventual aim would be to export some header files directly to the stdlib 27 | build process so that direct implementations can be used instead of the 28 | Linux/glibc versions 29 | -------------------------------------------------------------------------------- /klibc/io.c: -------------------------------------------------------------------------------- 1 | /* 2 | * klibc/io.c 3 | * 4 | * Created by Simon Evans on 21/05/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Fake io calls used by libswiftCore 8 | * 9 | */ 10 | 11 | #include "klibc.h" 12 | 13 | #pragma GCC diagnostic ignored "-Wunused-parameter" 14 | 15 | // Default FILE * for stdio, faked values 16 | // Linux symbol names 17 | void *stderr = (void *)0xF2; 18 | void *stdin = (void *)0xF0; 19 | void *stdout = (void *)0xF1; 20 | 21 | 22 | /* 23 | * I/O functions 24 | */ 25 | 26 | int 27 | fprintf(void *stream, const char *format, ...) 28 | { 29 | if (stream != stderr && stream != stdout) { 30 | koops("fprintf stream = %p", stream); 31 | } 32 | va_list argp; 33 | va_start(argp, format); 34 | int len = kvprintf(format, argp); 35 | va_end(argp); 36 | 37 | return len; 38 | } 39 | 40 | 41 | int 42 | printf(const char *format, ...) 43 | { 44 | va_list argp; 45 | va_start(argp, format); 46 | int len = kvprintf(format, argp); 47 | va_end(argp); 48 | 49 | return len; 50 | } 51 | 52 | int 53 | puts(const char *str) 54 | { 55 | kprint(str); 56 | kprint("\n"); 57 | return 0; 58 | } 59 | 60 | 61 | int 62 | fputs(const char *string, void *stream) 63 | { 64 | return fprintf(stream, "%s", string); 65 | } 66 | 67 | 68 | int 69 | fputc(int c, void *stream) 70 | { 71 | if (stream != stderr && stream != stdout) { 72 | koops("fputc stream = %p", stream); 73 | } 74 | early_print_char((char)c); 75 | return c; 76 | } 77 | 78 | 79 | int 80 | putchar(int c) 81 | { 82 | early_print_char((char)c); 83 | return c; 84 | } 85 | 86 | 87 | size_t 88 | fwrite(const void *ptr, size_t size, size_t nmemb, void *stream) 89 | { 90 | debugf("fwrite(%p, %lu, %lu, %p)", ptr, size, nmemb, stream); 91 | if (stream != stderr && stream != stdout) { 92 | koops("fwrite stream = %p", stream); 93 | } 94 | size_t len; 95 | if (__builtin_umull_overflow(size, nmemb, &len)) { 96 | koops("fwrite size too large (%lu,%lu)", size, nmemb); 97 | } 98 | early_print_string_len(ptr, len); 99 | 100 | return len; 101 | } 102 | 103 | 104 | ssize_t 105 | write(int fd, const void *buf, size_t nbyte) 106 | { 107 | debugf("write(fd=%d, buf=%p nbyte=%lu)\n", fd, buf, nbyte); 108 | 109 | if (fd == 1 || fd == 2) { 110 | early_print_string_len(buf, nbyte); 111 | } else { 112 | koops("write() with fd = %d\n", fd); 113 | } 114 | return nbyte; 115 | } 116 | -------------------------------------------------------------------------------- /klibc/printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * klibc/printf.c 3 | * 4 | * Created by Simon Evans on 21/05/2016. 5 | * Copyright © 2016, 2018 Simon Evans. All rights reserved. 6 | * 7 | * Fake printf calls used by libswiftCore 8 | * 9 | */ 10 | 11 | #include "klibc.h" 12 | 13 | #pragma GCC diagnostic ignored "-Wunused-parameter" 14 | 15 | /* 16 | * printf 17 | */ 18 | extern int kvasnprintf(char **strp, const char *fmt, va_list args); 19 | 20 | int 21 | vasprintf(char **strp, const char * restrict format, va_list argp) 22 | { 23 | debugf("vasprintf(%p,%s)\n", strp, format); 24 | 25 | // len = number of characters in final string, not that fit in buffer 26 | // excludes terminating '\0' 27 | return kvasnprintf(strp, format, argp); 28 | } 29 | 30 | 31 | int 32 | asprintf(char **strp, const char * restrict format, ...) 33 | { 34 | va_list argp; 35 | 36 | va_start(argp, format); 37 | int len = vasprintf(strp, format, argp); 38 | va_end(argp); 39 | 40 | return len; 41 | } 42 | 43 | 44 | int 45 | vsnprintf(char * restrict buf, size_t size, const char *format, va_list argp) 46 | { 47 | debugf("vsnprintf(%s)\n", format); 48 | int len = kvsnprintf(buf, size, format, argp); 49 | 50 | return len; 51 | } 52 | 53 | 54 | int 55 | snprintf(char * restrict buf, size_t size, const char * restrict format, ...) 56 | { 57 | va_list argp; 58 | 59 | debugf("snprintf(\"%s\", %lu)\n", format, size); 60 | va_start(argp, format); 61 | int len = kvsnprintf(buf, size, format, argp); 62 | va_end(argp); 63 | 64 | return len; 65 | } 66 | -------------------------------------------------------------------------------- /klibc/x86_misc.asm: -------------------------------------------------------------------------------- 1 | ;;; klibc/x86_misc.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 28/12/2015. 4 | ;;; Copyright © 2015, 2016 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; x86 CPU specific functions. 7 | 8 | BITS 64 9 | 10 | global reload_segments 11 | 12 | 13 | ;;; void reload_segments() 14 | ;;; Just a test routine to check the GDT has been set correctly, 15 | ;;; The segment registers are reloaded with the values they already had 16 | reload_segments: 17 | push qword CODE_SEG 18 | push qword .here 19 | db 0x48 20 | ;; Effectively a far jmp to .here to reload CS 21 | retf 22 | .here: 23 | mov ax, DATA_SEG 24 | mov ds, ax 25 | mov es, ax 26 | mov ss, ax 27 | ret 28 | -------------------------------------------------------------------------------- /klibc/x86_string.asm: -------------------------------------------------------------------------------- 1 | ;;; klibc/x86_string.asm 2 | ;;; 3 | ;;; Created by Simon Evans on 21/12/2015. 4 | ;;; Copyright © 2015, 2016 Simon Evans. All rights reserved. 5 | ;;; 6 | ;;; Misc mem* and str* functions that are easier to do directly in x86 asm. 7 | 8 | global memchr 9 | global memcmp 10 | global memcpy 11 | global memmove 12 | global memsetw 13 | global strchr 14 | 15 | 16 | ;;; void *memchr(const void *src, int c, size_t n); 17 | ;;; RDI: src, RSI: c, RDX: count 18 | memchr: 19 | mov r8, 1 20 | cmp rdx, 0 21 | mov rax, rsi 22 | mov rsi, rdi 23 | mov rcx, rdx 24 | je .notfound 25 | repnz scasb 26 | jne .notfound 27 | mov r8, rdi 28 | .notfound: 29 | dec r8 30 | mov rax, r8 31 | ret 32 | 33 | 34 | ;;; int memcmp(const void *s1, const void *s2, size_t n); 35 | ;;; RDI: s1, RDI: s2, RDX: count, returns 0 if same, 1 if diff 36 | memcmp: 37 | xor rax, rax 38 | mov rcx, rdx 39 | rep cmpsb 40 | setnz al 41 | ret 42 | 43 | 44 | ;;; void *memcpy(void *dest, const void *src, size_t n) 45 | ;;; RDI: dest, RSI: src, RDX: count, returns dest 46 | memcpy: 47 | mov rcx, rdx 48 | mov rax, rdi 49 | test rdx, rdx 50 | jz .exit 51 | shr rcx, 3 52 | rep movsq 53 | and rdx, 7 54 | mov rcx, rdx 55 | rep movsb 56 | .exit: 57 | ret 58 | 59 | 60 | ;;; void *memmove(void *dest, const void *src, size_t n); 61 | ;;; RDI: dest, RSI: src, RDX: count, returns dest 62 | memmove: 63 | mov rcx, rdx 64 | mov rax, rdi 65 | dec rdx 66 | test rcx, rcx 67 | je .exit 68 | cmp rdi, rsi 69 | je .exit 70 | jl .forward ; dest < src so no overlap with forward copy 71 | add rsi, rdx 72 | add rdi, rdx 73 | std ; copy backwards 74 | 75 | .forward: 76 | rep movsb 77 | cld 78 | .exit: 79 | ret 80 | 81 | 82 | ;;; void *memsetw(void *dest, uint16_t w, size_t count) 83 | ;;; RDI: dest, RSI: w, RDX: count. returns dest 84 | memsetw: 85 | cld 86 | mov r8, rdi 87 | mov ax, si 88 | mov rcx, rdx 89 | rep stosw 90 | mov rax, r8 91 | ret 92 | 93 | 94 | ;;; char *strchr(const char *s, int c) 95 | ;;; RDI: s, RSI:c returns first occurance of c or NULL 96 | strchr: 97 | cld 98 | mov dx, si 99 | .loop: 100 | mov al, [rdi] 101 | cmp al, dl 102 | je .found 103 | test al, al 104 | je .notfound 105 | inc rdi 106 | jmp .loop 107 | .notfound: 108 | xor rdi, rdi 109 | .found: 110 | mov rax, rdi 111 | ret 112 | -------------------------------------------------------------------------------- /lib/font_8x16.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/lib/font_8x16.c -------------------------------------------------------------------------------- /linker.script: -------------------------------------------------------------------------------- 1 | ENTRY(main) 2 | OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") 3 | 4 | PAGE_SIZE = 0x1000; 5 | /* Needs to be bigger for DEBUG mode, can be 16 for non debug */ 6 | /* FIXME: Needs to be more accurately sized in both modes once guard page is fixed */ 7 | STACK_SIZE = 16 * PAGE_SIZE; 8 | 9 | PHDRS { 10 | text PT_LOAD FLAGS(5); /* R_E */ 11 | rodata PT_LOAD FLAGS(4); /* R__ */ 12 | data PT_LOAD FLAGS(6); /* RW_ */ 13 | } 14 | 15 | SECTIONS { 16 | . = 0x1000; 17 | /* 2^64 - 2GB + 16MB */ 18 | /* Kernel is loaded at Physical Address 16MB (with BIOS load) */ 19 | .text (0xffffffff81000000) : { 20 | _kernel_start = .; 21 | _text_start = .; 22 | *(.text .text.*) 23 | } :text 24 | 25 | .rela.plt :{ 26 | *(.rela.plt) 27 | PROVIDE_HIDDEN (__rela_iplt_start = .); 28 | *(.rela.iplt) 29 | PROVIDE_HIDDEN (__rela_iplt_end = .); 30 | } 31 | 32 | .init : { 33 | KEEP (*(SORT_NONE(.init))) 34 | } 35 | PROVIDE(_text_end = .); 36 | 37 | 38 | .rodata : ALIGN(0x1000) { 39 | _rodata_start = .; 40 | *(.rodata .rodata.*) 41 | _rodata_end = .; 42 | } :rodata 43 | . = ALIGN(0x1000); 44 | 45 | .data : ALIGN(0x10) { 46 | _data_start = .; 47 | *(.data .data.*) 48 | } :data 49 | 50 | .preinit_array : { 51 | PROVIDE_HIDDEN (__preinit_array_start = .); 52 | KEEP (*(.preinit_array)) 53 | PROVIDE_HIDDEN (__preinit_array_end = .); 54 | } 55 | .init_array : { 56 | PROVIDE_HIDDEN (__init_array_start = .); 57 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 58 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 59 | PROVIDE_HIDDEN (__init_array_end = .); 60 | } 61 | .fini_array : { 62 | PROVIDE_HIDDEN (__fini_array_start = .); 63 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 64 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 65 | PROVIDE_HIDDEN (__fini_array_end = .); 66 | } 67 | 68 | .got : { *(.got) *(.igot) } 69 | .got.plt : { *(.got.plt) *(.igot.plt) } 70 | .plt : { *(.plt) *(.iplt) } 71 | .plt.got : { *(.plt.got) } 72 | .plt.bnd : { *(.plt.bnd) } 73 | 74 | PROVIDE(_data_end = .); 75 | . = ALIGN(0x1000); 76 | 77 | /* Thread Local Storage sections */ 78 | .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } 79 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } 80 | 81 | .bss ALIGN(0x1000) : { 82 | _bss_start = .; 83 | *(.bss..allocated_pages) 84 | *(.bss .bss.*) 85 | *(COMMON) 86 | . = ALIGN(PAGE_SIZE); 87 | _guard_page = .; 88 | . += PAGE_SIZE; 89 | _stack_start = .; 90 | . += STACK_SIZE; 91 | _kernel_stack = .; /* Top of stack so label comes after */ 92 | . += PAGE_SIZE; 93 | _ist1_stack_top = .; 94 | _heap_start = .; 95 | . += PAGE_SIZE * 128; 96 | _heap_end = .; 97 | 98 | _bss_end = .; 99 | } 100 | 101 | . = ALIGN(PAGE_SIZE); 102 | _kernel_end = .; 103 | 104 | /DISCARD/ : { 105 | *(.comment) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lldb-cmds: -------------------------------------------------------------------------------- 1 | command script import debugtools/dump_swift_string.py 2 | settings set target.source-map /home/spse/swift-kernel-lib /Users/spse/Files/src/swift-kernel-lib 3 | settings set target.source-map /home/spse/src/project1 /Users/spse/Files/src/project1 4 | file output/kernel.elf 5 | set set stop-disassembly-display always 6 | b debugger_hook 7 | b stop 8 | -------------------------------------------------------------------------------- /ovmf.bios: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spevans/swift-project1/51af71dcd1d3719af33b4e20e333e80e812ed059/ovmf.bios -------------------------------------------------------------------------------- /run_qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BOOT="-hda output/boot-hd.img" 4 | DEBUG="" 5 | ARGS="" 6 | MEM=${MEM:=256m} 7 | 8 | ACCEL=kvm 9 | if [ `uname -s` == "Darwin" ]; then 10 | ACCEL=hvf 11 | fi 12 | 13 | for arg in "$@" 14 | do 15 | case $arg in 16 | --efi) 17 | BOOT="-bios ovmf.bios -cdrom output/boot-cd.iso" 18 | ACCEL="" 19 | ;; 20 | 21 | -d) 22 | DEBUG="-s -S" 23 | ACCEL="" 24 | ;; 25 | 26 | *) 27 | ARGS="$ARGS $arg" 28 | esac 29 | done 30 | 31 | if [ "$ACCEL" != "" ]; then 32 | echo Using Acceleration $ACCEL 33 | CMD="qemu-system-x86_64 $DEBUG -accel $ACCEL -cpu host -m $MEM $BOOT -usb -serial stdio -D log -d int,cpu_reset,guest_errors,unimp -no-reboot $ARGS" 34 | echo $CMD 35 | $CMD 36 | else 37 | CMD="qemu-system-x86_64 $DEBUG -m $MEM $BOOT -usb -serial stdio -D log -d int,cpu_reset,guest_errors,unimp -no-reboot $ARGS" 38 | echo $CMD 39 | $CMD 40 | fi 41 | 42 | -------------------------------------------------------------------------------- /utils/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /utils/Makefile: -------------------------------------------------------------------------------- 1 | TOPDIR := .. 2 | include $(TOPDIR)/Makedefs 3 | 4 | all: $(BINS) 5 | $(SWIFT) build -c release 6 | 7 | clean: 8 | rm -rf .build 9 | -------------------------------------------------------------------------------- /utils/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "PatchUtils", 7 | products: [ 8 | .library(name: "PatchUtils", targets: [ "PatchUtils" ]), 9 | .executable(name: "mkdiskimg", targets: [ "mkdiskimg" ]), 10 | .executable(name: "efi_patch", targets: [ "efi_patch" ]), 11 | .executable(name: "foverride", targets: [ "foverride" ]) 12 | ], 13 | targets: [ 14 | .target( 15 | name: "PatchUtils"), 16 | .target( 17 | name: "mkdiskimg", 18 | dependencies: [ "PatchUtils" ]), 19 | .target( 20 | name: "efi_patch", 21 | dependencies: [ "PatchUtils" ]), 22 | .target( 23 | name: "foverride", 24 | dependencies: [ "PatchUtils" ]) 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /utils/Sources/efi_patch/main.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * utils/efi_patch.swift 3 | * 4 | * Created by Simon Evans on 12/02/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Patch values into the EFI header 8 | * 9 | */ 10 | 11 | import Foundation 12 | import PatchUtils 13 | 14 | 15 | func main() { 16 | let args = CommandLine.arguments 17 | guard args.count == 5 else { 18 | fatalError("usage: \(args[0]) ") 19 | } 20 | 21 | var bootsect = openOrQuit(args[1]) 22 | guard bootsect.count == sectorSize else { 23 | fatalError("Bootsector should be \(sectorSize) bytes but is \(bootsect.count)") 24 | } 25 | var loader = openOrQuit(args[2]) 26 | let loaderSectors = UInt16((loader.count + sectorSize - 1) / sectorSize) 27 | let mapFile = args[3] 28 | let outputFile = args[4] 29 | print("Header: \(args[1]) body: \(args[2]) mapfile: \(mapFile) output: \(outputFile)") 30 | 31 | 32 | let sig: UInt16 = readValue(bootsect, offset: 0) 33 | // Look for 'MZ' EFI signature 34 | guard sig == 0x5a4d else { 35 | fatalError("Cant Found EFI header") 36 | } 37 | 38 | print("Parsing map file") 39 | let symbols = parseMap(mapFile) 40 | guard let bssStart = symbols["_bss_start"] else { 41 | fatalError("Cant find _bss_start in \(mapFile)") 42 | } 43 | 44 | guard let bssEnd = symbols["_bss_end"] else { 45 | fatalError("Cant find _bss_end in \(mapFile)") 46 | } 47 | 48 | let bssSize = bssEnd - bssStart 49 | print("bssStart:", bssStart.asHex(), "bssEnd:", bssEnd.asHex(), 50 | "bssSize:", bssSize.asHex()) 51 | patchValue(&loader, offset: 8, value: bssSize) 52 | 53 | let imageSize = patchEFIHeader(&bootsect, loaderSectors) 54 | writeOutImage(outputFile, bootsect, loader, padding: imageSize) 55 | exit(0) 56 | } 57 | 58 | 59 | func patchEFIHeader(_ header: inout Data, _ loaderSectors: UInt16) -> Int { 60 | // SizeOfCode 61 | let sizeOfCode = UInt32(loaderSectors) * UInt32(sectorSize) 62 | print("SizeOfCode:", sizeOfCode.asHex()) 63 | patchValue(&header, offset: 92, value: sizeOfCode) 64 | 65 | // SizeOfImage (header + loader + kernel) 66 | let sizeOfImage = UInt32(1 + loaderSectors) * UInt32(sectorSize) 67 | print("SizeOfImage:", sizeOfImage) 68 | patchValue(&header, offset: 144, value: sizeOfImage) 69 | 70 | // .text section 71 | // .text.VirtualSize 72 | patchValue(&header, offset: 296, value: sizeOfCode) 73 | // .text.SizeOfRawData 74 | patchValue(&header, offset: 304, value: sizeOfCode) 75 | 76 | return Int(sizeOfImage) // Image size rounded up to sector size 77 | } 78 | 79 | 80 | func writeOutImage(_ filename: String, _ bootsect: Data, _ loader: Data, 81 | padding: Int = 0) { 82 | 83 | var outputData = bootsect 84 | outputData.append(loader) 85 | 86 | // FIXME: make padding a cmd line arg, this is needed to make a bochs disk image 87 | if padding > outputData.count { 88 | print("Padding output to \(padding) bytes") 89 | outputData.append(Data(count: padding - outputData.count)) 90 | } 91 | 92 | do { 93 | try outputData.write(to: URL(fileURLWithPath: filename)) 94 | } catch { 95 | fatalError("Cant write to output file \(filename)") 96 | } 97 | } 98 | 99 | main() 100 | -------------------------------------------------------------------------------- /utils/Sources/foverride/main.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * utils/foverride.swift 3 | * 4 | * Created by Simon Evans on 10/02/2016. 5 | * Copyright © 2016 Simon Evans. All rights reserved. 6 | * 7 | * Patch a function to directly jmp to another function. This can be 8 | * used if a function in the libswiftcore.a needs to be overriden. A 9 | * relative jmp instruction is patched in to make the code jump to a 10 | * alternate instruction instead 11 | */ 12 | 13 | import Foundation 14 | import PatchUtils 15 | 16 | 17 | func main() { 18 | let args = CommandLine.arguments 19 | guard args.count == 5 else { 20 | fatalError("usage: \(args[0]) ") 21 | } 22 | 23 | let (binFile, mapFile, oldFunction, newFunction) = (args[1], args[2], 24 | args[3], args[4]) 25 | 26 | print("Parsing", mapFile) 27 | let symbols = parseMap(mapFile) 28 | guard let textStart = symbols["_text_start"] else { 29 | fatalError("Cant find _text_start address") 30 | } 31 | 32 | guard let oldFunc = symbols[oldFunction] else { 33 | fatalError("Cant find \(args[3]) address") 34 | } 35 | 36 | guard let newFunc = symbols[newFunction] else { 37 | fatalError("Cant find \(args[4]) address") 38 | } 39 | 40 | let address = oldFunc - textStart 41 | let target = newFunc - textStart 42 | // May overflow if offset is > ± signed 32bit 43 | // +5 since the jmp is relative to the next instruction 44 | let offset = Int32(Int(target) - Int(address + 5)); 45 | 46 | print("\(oldFunction):", oldFunc.asHex(), "\(newFunction):", newFunc.asHex()) 47 | print("Patching", args[3], oldFunc.asHex(), "[\(address.asHex())] -> ", 48 | args[4], newFunc.asHex(), "[\(target.asHex())] offset:", offset.asHex()) 49 | let bin = NSMutableData(data: openOrQuit(binFile)) 50 | let rawPtr = bin.mutableBytes + Int(address) 51 | let ptr = rawPtr.bindMemory(to: UInt8.self, capacity: 5) 52 | let buf = UnsafeMutableBufferPointer(start: ptr, count: 5) 53 | buf[0] = 0xe9 // jmp with 32bit realative offset 54 | buf[1] = UInt8(truncatingIfNeeded: offset >> 0) 55 | buf[2] = UInt8(truncatingIfNeeded: offset >> 8) 56 | buf[3] = UInt8(truncatingIfNeeded: offset >> 16) 57 | buf[4] = UInt8(truncatingIfNeeded: offset >> 24) 58 | 59 | guard bin.write(toFile: binFile, atomically: true) else { 60 | fatalError("Cant write output") 61 | } 62 | exit(0) 63 | } 64 | 65 | main() 66 | -------------------------------------------------------------------------------- /utils/linux.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | struct hd_partition { 5 | uint8_t active_flag; 6 | uint8_t start_head; 7 | uint16_t start_cylsec; 8 | uint8_t system; 9 | uint8_t end_head; 10 | uint16_t end_cylsec; 11 | uint32_t LBA_start; 12 | uint32_t part_len; 13 | } __attribute__((__packed__)); 14 | 15 | --------------------------------------------------------------------------------