diff --git a/.gitignore b/.gitignore index d4faf943..de756d76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,18 @@ *.BIN +*.bin *.ZXE *.MAP src/Boot/ -docs/Boot/ -ZealOS-*.iso +*.ELF +*.elf +*.sys +*.SYS +src/EFI/ +build/limine +build/ovmf +*.iso +*.raw +*.hdd +*.o +*.d +zealbooter/limine.h diff --git a/README.md b/README.md index 3ff95b7e..e19308f5 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Features in development include: - [32-bit color VBE graphics](https://github.com/TempleProgramming/HolyGL) - Fully-functional AHCI support - Network card drivers and a networking stack + - UEFI booting via [BSD2-licensed Limine bootloader](https://github.com/limine-bootloader/limine) and [Public Domain ZealBooter prekernel](/zealbooter/zealbooter.c) [Changes include](https://zeal-operating-system.github.io/Doc/ChangeLog.DD.html): - 60 FPS @@ -51,7 +52,7 @@ In July of 2021, ZealOS was forked from ZenithOS. ## Screenshots -Network Report, UDP Chat Application and AutoComplete, with Stars wallpaper +Network Report, Gopher Client, FTP Client, GrDir, and AutoComplete, with Stars wallpaper ![](/screenshots/screenshot3.png) diff --git a/build/AUTO.ISO b/build/AUTO.ISO index 96c44221..eeb24e6e 100755 Binary files a/build/AUTO.ISO and b/build/AUTO.ISO differ diff --git a/build/build-iso.ps1 b/build/build-iso.ps1 index 78ccd4de..12710adc 100755 --- a/build/build-iso.ps1 +++ b/build/build-iso.ps1 @@ -49,29 +49,33 @@ function Unmount-TempDisk Write-Output "Making temp vdisk, running auto-install..." -qemu-img create -f vhdx $TMPDISK 512M +qemu-img create -f vhdx $TMPDISK 1024M fsutil sparse setflag $TMPDISK 0 fsutil sparse queryflag $TMPDISK qemu-system-x86_64 -machine q35,accel=whpx,kernel-irqchip=off -drive format=vhdx,file=$TMPDISK -m 2G -rtc base=localtime -cdrom AUTO.ISO -device isa-debug-exit +Write-Output "Copying all src/ code into vdisk Tmp/OSBuild/ ..." + Remove-Item "..\src\Home\Registry.ZC" -errorAction SilentlyContinue Remove-Item "..\src\Home\MakeHome.ZC" -errorAction SilentlyContinue +Remove-Item "..\src\Boot\Kernel.ZXE" -errorAction SilentlyContinue Mount-TempDisk - -Copy-Item -Path "..\src\*" -Destination "${QEMULETTER}:\" -Recurse -Force +New-Item -Path "${QEMULETTER}:\Tmp\" -Name "OSBuild" -ItemType "directory" +Copy-Item -Path "..\src\*" -Destination "${QEMULETTER}:\Tmp\OSBuild\" -Recurse -Force Unmount-TempDisk -Write-Output "Generating ISO..." +Write-Output "Rebuilding kernel headers, kernel, OS, and building Distro ISO ..." + qemu-system-x86_64 -machine q35,accel=whpx,kernel-irqchip=off -drive format=vhdx,file=$TMPDISK -m 2G -rtc base=localtime -device isa-debug-exit + Write-Output "Extracting ISO from vdisk..." + Remove-Item "ZealOS-*.iso" -errorAction SilentlyContinue Mount-TempDisk - -$ZEALISO = "ZealOS-" + (Get-Date -Format "yyyy-MM-dd-HH_mm_ss").toString() + ".iso" - -Copy-Item "${QEMULETTER}:\Tmp\MyDistro.ISO.C" -Destination $ZEALISO +$ZEALISO = "ZealOS-PublicDomain-BIOS-" + (Get-Date -Format "yyyy-MM-dd-HH_mm_ss").toString() + ".iso" +Copy-Item "${QEMULETTER}:\Tmp\MyDistro.ISO.C" -Destination $ZEALISO Unmount-TempDisk Remove-Item $TMPDISK Write-Output "Finished." -Get-ChildItem "ZealOS*.iso" \ No newline at end of file +Get-ChildItem "ZealOS*.iso" diff --git a/build/build-iso.sh b/build/build-iso.sh index ae6eca77..5e7199d6 100755 --- a/build/build-iso.sh +++ b/build/build-iso.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Build Distro ISO using AUTO.ISO minimal auto-install as bootstrap to merge codebase, recompile system, and export ISO +# Build OS using AUTO.ISO minimal auto-install as bootstrap to merge codebase, recompile system, attempt build limine UEFI hybrid ISO # make sure we are in the correct directory SCRIPT_DIR=$(realpath "$(dirname "$0")") @@ -16,7 +16,11 @@ fi # Uncomment if you use doas instead of sudo #alias sudo=doas +# Set this true if you want to test ISOs in QEMU after building. +TESTING=false + TMPDIR="/tmp/zealtmp" +TMPISODIR="$TMPDIR/iso" TMPDISK="$TMPDIR/ZealOS.raw" TMPMOUNT="$TMPDIR/mnt" @@ -34,29 +38,116 @@ umount_tempdisk() { } [ ! -d $TMPMOUNT ] && mkdir -p $TMPMOUNT +[ ! -d $TMPISODIR ] && mkdir -p $TMPISODIR -echo "Making temp vdisk, running auto-install..." -qemu-img create -f raw $TMPDISK 192M -qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -cdrom AUTO.ISO -device isa-debug-exit +set -e +echo "Building ZealBooter..." +( cd ../zealbooter && make distclean all || echo "ERROR: ZealBooter build failed !") +set +e -echo "Mounting vdisk and copying src/..." +echo "Making temp vdisk, running auto-install ..." +qemu-img create -f raw $TMPDISK 1024M +qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -smp 4 -cdrom AUTO.ISO -device isa-debug-exit + +echo "Copying all src/ code into vdisk Tmp/OSBuild/ ..." rm ../src/Home/Registry.ZC 2> /dev/null rm ../src/Home/MakeHome.ZC 2> /dev/null +rm ../src/Boot/Kernel.ZXE 2> /dev/null mount_tempdisk -sudo cp -r ../src/* $TMPMOUNT +sudo mkdir $TMPMOUNT/Tmp/OSBuild/ +sudo cp -r ../src/* $TMPMOUNT/Tmp/OSBuild umount_tempdisk -echo "Generating ISO..." -qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -device isa-debug-exit +echo "Rebuilding kernel headers, kernel, OS, and building Distro ISO ..." +qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -smp 4 -device isa-debug-exit + +LIMINE_BINARY_BRANCH="v4.x-branch-binary" + +if [ -d "limine" ] +then + cd limine + git remote set-branches origin $LIMINE_BINARY_BRANCH + git fetch + git remote set-head origin $LIMINE_BINARY_BRANCH + git switch $LIMINE_BINARY_BRANCH + git pull + rm limine-deploy + rm limine-version + + cd .. +fi +if [ ! -d "limine" ]; then + git clone https://github.com/limine-bootloader/limine.git --branch=$LIMINE_BINARY_BRANCH --depth=1 +fi +make -C limine + +touch limine/Limine-HDD.HH +echo "/*\$WW,1\$" > limine/Limine-HDD.HH +cat limine/LICENSE.md >> limine/Limine-HDD.HH +echo "*/\$WW,0\$" >> limine/Limine-HDD.HH +cat limine/limine-hdd.h >> limine/Limine-HDD.HH +sed -i 's/const uint8_t/U8/g' limine/Limine-HDD.HH +sed -i "s/\[\]/\[$(grep -o "0x" ./limine/limine-hdd.h | wc -l)\]/g" limine/Limine-HDD.HH -echo "Extracting ISO from vdisk..." -rm ./ZealOS-*.iso 2> /dev/null # comment this line if you want lingering old ISOs mount_tempdisk -cp $TMPMOUNT/Tmp/MyDistro.ISO.C ./ZealOS-$(date +%Y-%m-%d-%H_%M_%S).iso +echo "Extracting MyDistro ISO from vdisk ..." +cp $TMPMOUNT/Tmp/MyDistro.ISO.C ./ZealOS-MyDistro.iso +sudo rm $TMPMOUNT/Tmp/MyDistro.ISO.C 2> /dev/null +echo "Setting up temp ISO directory contents for use with limine xorriso command ..." +sudo cp -rf $TMPMOUNT/* $TMPISODIR +sudo rm $TMPISODIR/Boot/OldMBR.BIN 2> /dev/null +sudo rm $TMPISODIR/Boot/BootMHD2.BIN 2> /dev/null +sudo mkdir -p $TMPISODIR/EFI/BOOT +sudo cp limine/Limine-HDD.HH $TMPISODIR/Boot/Limine-HDD.HH +sudo cp limine/BOOTX64.EFI $TMPISODIR/EFI/BOOT/BOOTX64.EFI +sudo cp limine/limine-cd-efi.bin $TMPISODIR/Boot/Limine-CD-EFI.BIN +sudo cp limine/limine-cd.bin $TMPISODIR/Boot/Limine-CD.BIN +sudo cp limine/limine.sys $TMPISODIR/Boot/Limine.SYS +sudo cp ../zealbooter/zealbooter.elf $TMPISODIR/Boot/ZealBooter.ELF +sudo cp ../zealbooter/Limine.CFG $TMPISODIR/Boot/Limine.CFG +echo "Copying DVDKernel.ZXE over ISO Boot/Kernel.ZXE ..." +sudo mv $TMPMOUNT/Tmp/DVDKernel.ZXE $TMPISODIR/Boot/Kernel.ZXE +sudo rm $TMPISODIR/Tmp/DVDKernel.ZXE 2> /dev/null umount_tempdisk -echo "Deleting temp folder..." -rm -rf $TMPDIR +xorriso -joliet "on" -rockridge "on" -as mkisofs -b Boot/Limine-CD.BIN \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + --efi-boot Boot/Limine-CD-EFI.BIN \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + $TMPISODIR -o ZealOS-limine.iso + +./limine/limine-deploy ZealOS-limine.iso + +if [ "$TESTING" = true ]; then + if [ ! -d "ovmf" ]; then + echo "Downloading OVMF..." + mkdir ovmf + cd ovmf + curl -o OVMF-X64.zip https://efi.akeo.ie/OVMF/OVMF-X64.zip + 7z x OVMF-X64.zip + cd .. + fi + echo "Testing limine-zealbooter-xorriso isohybrid boot in UEFI mode ..." + qemu-system-x86_64 -machine q35,accel=kvm -m 1G -rtc base=localtime -bios ovmf/OVMF.fd -smp 4 -cdrom ZealOS-limine.iso + echo "Testing limine-zealbooter-xorriso isohybrid boot in BIOS mode ..." + qemu-system-x86_64 -machine q35,accel=kvm -m 1G -rtc base=localtime -smp 4 -cdrom ZealOS-limine.iso + echo "Testing native ZealC MyDistro legacy ISO in BIOS mode ..." + qemu-system-x86_64 -machine q35,accel=kvm -m 1G -rtc base=localtime -smp 4 -cdrom ZealOS-MyDistro.iso +fi + +# comment these 2 lines if you want lingering old Distro ISOs +rm ./ZealOS-PublicDomain-BIOS-*.iso 2> /dev/null +rm ./ZealOS-BSD2-UEFI-*.iso 2> /dev/null + +mv ./ZealOS-MyDistro.iso ./ZealOS-PublicDomain-BIOS-$(date +%Y-%m-%d-%H_%M_%S).iso +mv ./ZealOS-limine.iso ./ZealOS-BSD2-UEFI-$(date +%Y-%m-%d-%H_%M_%S).iso + +echo "Deleting temp folder ..." +sudo rm -rf $TMPDIR +sudo rm -rf $TMPISODIR echo "Finished." -ls -lh ZealOS-*.iso - +echo +echo "ISOs built:" +ls | grep ZealOS-P +ls | grep ZealOS-B +echo diff --git a/screenshots/screenshot1.png b/screenshots/screenshot1.png index ddb5b541..bec88a74 100644 Binary files a/screenshots/screenshot1.png and b/screenshots/screenshot1.png differ diff --git a/screenshots/screenshot2.png b/screenshots/screenshot2.png index 2661d3c7..6e5c55e8 100644 Binary files a/screenshots/screenshot2.png and b/screenshots/screenshot2.png differ diff --git a/screenshots/screenshot3.png b/screenshots/screenshot3.png index c04765b3..085e1a8e 100644 Binary files a/screenshots/screenshot3.png and b/screenshots/screenshot3.png differ diff --git a/src/Demo/AcctExample/TOS/TOSConfig.ZC b/src/Demo/AcctExample/TOS/TOSConfig.ZC index 52c3fa8e..f5060331 100755 --- a/src/Demo/AcctExample/TOS/TOSConfig.ZC +++ b/src/Demo/AcctExample/TOS/TOSConfig.ZC @@ -52,8 +52,8 @@ U0 TOSInit() #define CONFIG_OPTS "MountAHCIAuto\nCT\n" #define CONFIG_DEBUG_OPTS "MountAHCIAuto\nCTHeapInit\n130\nMemInit\n131\nVarInit\n132\n\n" #define CONFIG_DEBUGZ_OPTS "MountAHCIAuto\nCTHeapInit\n0\nMemInit\n0\nVarInit\n0\n\n" -#define TOS_CONFIG "\n" CONFIG_RAM_DRIVES CONFIG_DVD_DRIVES CONFIG_HARD_DRIVES "\n1024\n768\n" CONFIG_DISK_CACHE CONFIG_OPTS -#define TOS_DVD_CONFIG "TB\n0x20000\nT \n\n1024\n768\n\nMountAHCIAuto\nCT\n" +#define TOS_CONFIG "\n" CONFIG_RAM_DRIVES CONFIG_DVD_DRIVES CONFIG_HARD_DRIVES "\n" CONFIG_DISK_CACHE CONFIG_OPTS +#define TOS_DVD_CONFIG "TB\n0x20000\nT\n\n\nMountAHCIAuto\nCT\n" #define TOS_DVD_DEBUG_CONFIG "A" CONFIG_DEBUG_DISTRO\ "B\nScale2Mem(2048,0x40000)\n\n\n"\ diff --git a/src/Demo/Games/ZoneOut.ZC b/src/Demo/Games/ZoneOut.ZC index bdd0db93..8eddaaa8 100755 Binary files a/src/Demo/Games/ZoneOut.ZC and b/src/Demo/Games/ZoneOut.ZC differ diff --git a/src/Demo/Graphics/GrDir.ZC b/src/Demo/Graphics/GrDir.ZC index b512b63c..a4283490 100755 Binary files a/src/Demo/Graphics/GrDir.ZC and b/src/Demo/Graphics/GrDir.ZC differ diff --git a/src/Doc/Boot.DD b/src/Doc/Boot.DD index ca911174..6ce6b8fe 100755 Binary files a/src/Doc/Boot.DD and b/src/Doc/Boot.DD differ diff --git a/src/Doc/ChangeLog.DD b/src/Doc/ChangeLog.DD index 26091eb9..4c92ea5d 100755 --- a/src/Doc/ChangeLog.DD +++ b/src/Doc/ChangeLog.DD @@ -1,4 +1,35 @@ $WW,1$$FG,5$$TX+CX,"ChangeLog"$$FG$ +$IV,1$----11/02/22 20:26:55----$IV,0$ +* Raised version number to 2.00. +* Updated the $LK,"Charter",A="FI:::/Doc/Charter.DD"$ to allow non-Public-Domain MBR/UEFI bootloaders, as long as the Public Domain ZealOS HDD/DVD Boot Loaders are included, offered, and functional. The Charter upholds that all operating system code must still be 100% public domain. Updated $LK+PU,"Credits",A="FI:::/Doc/Credits.DD"$, $LK+PU,"FAQ",A="FI:::/Doc/FAQ.DD"$, $LK+PU,"Features.DD",A="FI:::/Doc/Features.DD"$, $LK+PU,"Welcome.DD",A="FI:::/Doc/Welcome.DD"$. +* Added 128-bit signature to $LK+PU,"KStart32",A="FF:::/Kernel/KStart32.ZC,JMP @@02"$ to allow for booting the ZealOS Kernel.ZXE from 32-bit mode via a prekernel booted from any other bootloader. The signature is jumped over with JMP if booted from the Public Domain ZealOS Boot Loaders to KStart16 to KStart32. +* Created external Public Domain "ZealBooter" prekernel written in C, for use with booting Kernel.ZXE from other bootloaders, primarily targeting Limine. ZealBooter compiles to an ELF file that Limine boots into and passes boot-time information to, which ZealBooter then uses to boot into and pass information to the Kernel.ZXE kernel header. +* Implemented Limine bootloader install prompt to $LK+PU,"OSInstall",A="FI:::/Misc/OSInstall.ZC"$. Created $LK+PU,"LimineCFGMake and LimineMHDIns",A="FI:::/System/Boot/LimineMHDIns.ZC"$ to allow for installing Limine to MBR, and for generating the Limine.CFG file required. +* Added ";*.CFG*" to $LK+PU,"FILEMASK_TXT",A="MN:FILEMASK_TXT"$ +* Added Kernel header fields $LK+PU,"SYS_FRAMEBUFFER_ADDR",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_ADDR"$, $LK+PU,"SYS_FRAMEBUFFER_WIDTH",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_WIDTH"$, $LK+PU,"SYS_FRAMEBUFFER_HEIGHT",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_HEIGHT"$, $LK+PU,"SYS_FRAMEBUFFER_PITCH",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_PITCH"$, $LK+PU,"SYS_FRAMEBUFFER_BPP",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_BPP"$, $LK+PU,"SYS_SMBIOS_ENTRY",A="FF:::/Kernel/KStart16.ZC,SYS_SMBIOS_ENTRY"$, $LK+PU,"SYS_DISK_UUID",A="FF:::/Kernel/KStart16.ZC,SYS_DISK_UUID"$, $LK+PU,"SYS_BOOT_STACK",A="FF:::/Kernel/KStart16.ZC,SYS_BOOT_STACK"$, $LK+PU,"SYS_IS_UEFI_BOOTED",A="FF:::/Kernel/KStart16.ZC,SYS_IS_UEFI_BOOTED"$, $LK+PU,"SYS_FRAMEBUFFER_LIST",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_LIST"$. + - Updated $LK+PU,"CKernel",A="MN:CKernel"$ class struct to match $LK+PU,"SYS_KERNEL",A="MN:SYS_KERNEL"$ changes by adding fields: sys_framebuffer_addr, sys_framebuffer_width, sys_framebuffer_height, sys_framebuffer_pitch, sys_framebuffer_bpp, sys_smbios_entry, sys_disk_uuid, sys_boot_stack, sys_is_uefi_booted, sys_framebuffer_list. + - Added externs for these to $LK+PU,"KernelB.HH",A="FF:::/Kernel/KernelB.HH,Framebuffer"$. + - Removed externs for sys_vbe_info, sys_vbe_final_mode, sys_vbe_mode_num, sys_vbe_modes. Changed all code previously using sys_vbe_mode to $MA-X+PU,"instead use framebuffer externs",LM="Find(\"sys_framebuffer_\", \"::/\");View;"$. + - Moved SYS_VBE_INFO and SYS_VBE_FINAL_MODE_NUM out of the Kernel header, renamed to $LK+PU,"VBE_INFO",A="FF:::/Kernel/KStart16.ZC,VBE_INFO"$ and $LK+PU,"VBE_FINAL_MODE_NUM",A="FF:::/Kernel/KStart16.ZC,VBE_FINAL_MODE_NUM"$. + - Replaced SYS_VBE_MODES with $LK+PU,"SYS_FRAMEBUFFER_LIST",A="FF:::/Kernel/KStart16.ZC,SYS_FRAMEBUFFER_LIST"$, changed KStart16 $LK+PU,"VBE Mode iteration",A="FF:::/Kernel/KStart16.ZC,height[DX]"$ to put VBE Mode values into this list. + - Removed SYS_VBE_FINAL_MODE. + - Removed compile-time StreamPrint-ed SCREEN_WIDTH and SCREEN_HEIGHT with $LK+PU,"REQUESTED_SCREEN_WIDTH",A="FF:::/Kernel/KStart16.ZC,REQUESTED_SCREEN_WIDTH"$ and $LK+PU,"REQUESTED_SCREEN_HEIGHT",A="FF:::/Kernel/KStart16.ZC,REQUESTED_SCREEN_HEIGHT"$, and removed resolution In() strings from all DoDistro related files and define values. By default, ZealOS will always try to look for and use a VBE mode with 1024x768 screen resolution. These can be changed to request a different screen resolution from the VBE Mode list returned from the BIOS. The Kernel must still be recompiled with $LK+PU,"BootHDIns",A="MN:BootHDIns"$ to make changes to these variables take effect. + - Removed MAX_VBE_MODE and MAX_SCREEN_HEIGHT, replaced with $LK+PU,"VBE_STD_MODE_NUM",A="FF:::/Kernel/KStart16.ZC,VBE_STD_MODE_NUM"$ which gets set to the VBE mode that has a 1024x768 resolution, to use as a fallback mode if the requested resolution isn't available. + - Changed $LK+PU,"KStart32 temp stack",A="FF:::/Kernel/KStart32.ZC,SYS_BOOT_STACK"$ to use new $LK+PU,"SYS_BOOT_STACK",A="FF:::/Kernel/KStart16.ZC,SYS_BOOT_STACK"$ kernel header variable, rather than hardcoded constant value. Default value is $LK+PU,"BOOT_RAM_LIMIT",A="MN:BOOT_RAM_LIMIT"$, same as what it was previously hardcoded to. + - Changed $LK+PU,"KStart64 boot stack PUSH",A="FF:::/Kernel/KStart64.ZC,SYS_BOOT_STACK"$ from hardcoded value to use value stored in new $LK+PU,"SYS_BOOT_STACK",A="FF:::/Kernel/KStart16.ZC,SYS_BOOT_STACK"$ header field. +* Alter $LK+PU,"VideoRep",A="MN:VideoRep"$ to use new externs, removed lines reporting information no longer acquired by the kernel; added aspect ratio calculation and reporting. +* Raised $LK+PU,"MEM_E820_ENTRIES_NUM",A="MN:MEM_E820_ENTRIES_NUM"$ from 48 to 256. +* Replaced CVBEModeShort with $LK+PU,"CVideoInfo",A="MN:CVideoInfo"$. +* Implemented $LK+PU,"PCIBt",A="MN:PCIBt"$, $LK+PU,"PCIBts",A="MN:PCIBts"$, $LK+PU,"PCIBtr",A="MN:PCIBtr"$ due to bare-metal testing of PCI drivers demonstrating undefined behaviour when accessing memory-mapped IO areas using the standard API $LK+PU,"Bt",A="MN:Bt"$, $LK+PU,"Bts",A="MN:Bts"$, $LK+PU,"Btr",A="MN:Btr"$. Replaced all Bt/Bts/Btr calls with PCIBt/PCIBts/PCIBtr in AHCI code, as well as all networking drivers and auxiliary code accessing AHCI memory-mapped variables. Added externs for new PCI bit test functions to $LK+PU,"KernelC.HH",A="FF:::/Kernel/KernelC.HH,PCIBt("$. +* Changed $LK+PU,"gr.continuous_scroll",A="FF:::/System/Gr/GrGlobals.ZC,continuous_scroll"$ to TRUE in $LK+PU,"HomeLocalize",A="FI:::/Home/HomeLocalize.ZC"$. +* Add simple progress indicator to $LK+PU,"CopySingle",A="FF:::/Kernel/BlkDev/DiskCopy.ZC,jiffies > time"$ that progress as a percentage every 2 seconds. +* Replace SYS_FONT_PTR VGA ROM 16-bit mode aux font retrieval with $LK+PU,"FontAux",A="FI:::/Kernel/FontAux.ZC"$. +* Lowered $LK+PU,"PTR_STARS_NUM",A="MN:PTR_STARS_NUM"$ from 4 to 3. +* Moved $LK+PU,"PCILookUpSingle",A="MN:PCILookUpSingle"$ out of System/DevInfo.ZC to new file $LK+PU,"System/PCILookUpSingle.ZC",A="FI:::/System/PCILookUpSingle.ZC"$. Added including this file to $LK+PU,"MakeSystem",A="FF:::/System/MakeSystem.ZC,PCILook"$. This change makes it simpler to change and update the PCI device list text file parsing behaviour for modern PCI device lists. +* Removed VGAM_GRAPHICS, text.vga_alias, and all code/documentation referencing them or legacy VGA graphics. MiniGrLib now needs a complete rewrite. +* Added $LK+PU,"DF_KEEP_FLAGS",A="MN:DF_KEEP_FLAGS"$ and corresponding logic to $LK+PU,"Diff",A="FF:::/System/Utils/Diff.ZC,& DF_KEEP_FLAGS"$. +* Changed $LK+PU,"BootMHDOldRead",A="MN:BootMHDOldRead"$ to take optional size argument, and changed $LK+PU,"BootMHDOldWrite",A="MN:BootMHDOldWrite"$ to use the OldMBR.BIN filesize to determine how many blocks to write. Used in $LK+PU,"LimineMHDIns",A="FF:::/System/Boot/LimineMHDIns.ZC,LimineMHDIns("$ to backup the MBR and post-MBR-gap to OldMBR.BIN. + $IV,1$----04/16/22 20:24:18----$IV,0$ * Inverted $LK+PU,"DocBorderNew",A="MN:DocBorderNew"$ and $LK+PU,"DocEd",A="MN:DocEd"$ bottom-right window text, adjusted DolDoc tag placement to make solid, changed Ed callbacks ($LK+PU,"EdOverStrikeCB",A="MN:EdOverStrikeCB"$, $LK+PU,"EdAutoSaveCB",A="MN:EdAutoSaveCB"$, $LK+PU,"EdFilterCB",A="MN:EdFilterCB"$, $LK+PU,"EdDollarCB",A="MN:EdDollarCB"$, $LK+PU,"EdMoreCB",A="MN:EdMoreCB"$) to return ' ' SPACE character(s) for disabled flags now since invert renders it solid foreground color, appended ' ' SPACE character at $LK+PU,"EdDollarTypeCB",A="FF:::/System/DolDoc/DocEd.ZC,\"%-3ts \""$ to pad. diff --git a/src/Doc/Charter.DD b/src/Doc/Charter.DD index 9c01a8bb..25385d24 100755 --- a/src/Doc/Charter.DD +++ b/src/Doc/Charter.DD @@ -1,12 +1,13 @@ + $FG,5$$WW,1$$TX+CX,"ZealOS Charter"$$FG$ * The vision is the same usage model and niche as the Commodore 64 -- a simple machine where programming was the goal, not just a means to an end. However, it is modern, 64-bit and $FG,2$multi-cored$FG$. It is special purpose, not general purpose, so some things it will not do. Also, it's a kayak, not a Titanic. The priority is $FG,2$user developers$FG$, not $FG,2$3rd party developers$FG$. * $FG,4$We don't think twice about breaking compatibility. $FG$ We do not put any hooks for future changes. "Perfect" means we always act as though it is final, for all time. Microsoft allowed the $FG,2$$TX,"Windows BMP",HTML="http://en.wikipedia.org/wiki/BMP_file"$$FG$ file format to adapt to the future and it became grotesque. -* Low line count and code complexity is the highest good, so it is easy to learn the whole thing. Users should see the light at the end of the tunnel. One file system, for example, is better than many file systems. +* Low line count and low code complexity is the highest good, so it is easy to learn the whole thing. Users should see the light at the end of the tunnel. -* There is a limit of 100,000 lines of code for all time, not including applications and demos. Currently, there are $TX,"98,216",D="DD_ZEALOS_LOC"$ lines of code. $FG,4$3rd party libraries are banned$FG$ because they circumvent the intent of this limit. The vision is a Commodore 64 ROM -- a fixed core API that is the only dependency of applications. Dependency on components and libraries creates a hell that is no longer blissful. +* There is a limit of 100,000 lines of code for all time, not including applications and demos. Currently, there are $TX,"98,661",D="DD_ZEALOS_LOC"$ lines of code. $FG,4$3rd party libraries are banned from being required$FG$ because they circumvent the intent of this limit. The vision is a Commodore 64 ROM -- a fixed core API that is the only dependency of applications. Dependency on components and libraries creates a hell that is no longer blissful. * The primary metric for resolving all ZealOS code governance issues is how fast the compiler compiles itself and the kernel with $LK,"BootHDIns",A="MN:BootHDIns"$(). The secondary metric is how understandable the code is. The $LK,"ZealC",A="FI:::/Doc/ZealC.DD"$ language should be changed to optimize these metrics, as Terry Davis did when he changed type casting from prefix to $LK+PU,"postfix",A="FF:::/Doc/ZealC.DD,postfix"$. @@ -14,7 +15,7 @@ $FG,5$$WW,1$$TX+CX,"ZealOS Charter"$$FG$ * It is for one platform -- $FG,4$$TX,"x86_64",HTML="http://en.wikipedia.org/wiki/Amd64#AMD64"$$FG$ desktop PC compatibles, more like super-computers than battery efficient wimpy mobiles. -* One driver for each class of device. Limited exceptions are allowed. With divergent device capabilities, it is a nightmare for user applications and what is gained? +* One driver for each class of device. The only exceptions are networking, sound, and keyboard/mouse. With divergent device capabilities, it is a nightmare for user applications and what is gained? * $FG,2$Ring-0-only$FG$. Everything runs in kernel mode, including user applications. @@ -26,13 +27,15 @@ $FG,5$$WW,1$$TX+CX,"ZealOS Charter"$$FG$ * $FG,2$Single-address-map$FG$ as though paging is not used. Long mode requires paging, however, so the nearest thing is keeping all memory $FG,2$identity-mapped$FG$. -* $FG,2$Free$FG$ and $FG,2$public domain$FG$. +* $FG,2$Free$FG$ and $FG,2$public domain$FG$ operating system code. Bootloaders of other open-source licenses (Grub, Limine, etc) are permitted. The Public Domain ZealOS HDD/DVD Bootloaders written in ZealC must always be kept functional, must always be offered as a bootloader option during BIOS-mode install, and must always be included in Distro ISOs. -* $FG,2$100% open source$FG$ with all source included. +* $FG,2$100% open source$FG$ operating system code with all source included. Bootloaders are excluded from this requirement. * Documents are not for printing. They're dynamic, intended for the screen. * Just one 8x8 fixed-width font. $FG,4$No Unicode, just Extended ASCII$FG$. Other countries can make their own versions. The versions should be just for one language and platform. + +* Fully self-hosted self-reproducing functionality on bare-metal and in VMs, primarily via AHCI ATAPI burned CD/DVD discs (ñR/W). $FG,8$ * "Commodore 64" is a trademark owned by Polabe Holding NV. * "Windows" is a trademark owned by MicroSoft Corp. diff --git a/src/Doc/Credits.DD b/src/Doc/Credits.DD index efcf085e..aeab6a7a 100755 --- a/src/Doc/Credits.DD +++ b/src/Doc/Credits.DD @@ -1,6 +1,6 @@ $WW,1$$FG,5$$TX+CX,"Credits"$$FG$ -$FG,2$Terry A. Davis$FG$ wrote all of TempleOS over a span of $FG,2$$TX,"15.0",D="DD_TEMPLEOS_AGE"$$FG$ years (full-time). ZealOS, written over a span of $FG,2$$TX,"2.6",D="DD_ZEALOS_AGE"$$FG$ years, is a fork of TempleOS. It can run on some bare metal 64-bit PC's from about 2007-2019 with no layering, libraries, tools, modules or anything from other sources. Otherwise, you run it in a virtual machine, like $FG,2$VMware$FG$, $FG,2$QEMU$FG$ or $FG,2$VirtualBox$FG$. It is independent and stands alone. 100% of the src code is including on all distro's, from the kernel to the compiler to the boot loaders! It is public domain, not GPL. +$FG,2$Terry A. Davis$FG$ wrote all of TempleOS over a span of $FG,2$$TX,"15.0",D="DD_TEMPLEOS_AGE"$$FG$ years (full-time). ZealOS, written over a span of $FG,2$$TX,"3.1",D="DD_ZEALOS_AGE"$$FG$ years (part-time), is a fork of TempleOS. It can run on bare metal 64-bit PC's from about 2007-2019 with no layering, libraries, tools, modules or anything from other sources. Otherwise, you run it in a virtual machine, like $FG,2$VMware$FG$, $FG,2$QEMU$FG$ or $FG,2$VirtualBox$FG$. It is independent and can stand alone. 100% of the operating system source code is included on all distros, from the kernel to the compiler to the applications, including public-domain BIOS-mode boot loaders! It is public domain, not GPL. *) $LK,"ATA Reg and Cmd Definitions",A="MN:ATA_NOP"$ are originally from Linux. Later, Terry got the spec. @@ -38,6 +38,7 @@ $FG,2$Terry A. Davis$FG$ wrote all of TempleOS over a span of $FG,2$$TX,"15.0",D *) The random number generator is from Donald Knuth in the wikipedia entry for $TX,"Linear_congruential_generator",HTML="http://en.wikipedia.org/wiki/Linear_congruential_generator"$. +*) The $FG,4$optional$FG$ UEFI-compatible Limine bootloader is copyrighted by GitHub user 'mintsuki' and project contributors, under the BSD-2 License. $FG,4$This bootloader is NOT included by default$FG$, and is only available on ZealOS distro ISO builds marked "BSD2-UEFI" in the ISO filename. $FG,8$ * "MSDOS", "Windows", and "FAT32" are trademarks owned by MicroSoft Corp. * "MATLAB" is a trademark owned by The Math Works, Inc. diff --git a/src/Doc/Customize.DD b/src/Doc/Customize.DD index 4bd3a569..6faa4b07 100755 --- a/src/Doc/Customize.DD +++ b/src/Doc/Customize.DD @@ -2,6 +2,6 @@ $WW,1$* You can adjust the mouse movement rate by setting global variables in yo * You can set your local time zone by setting the $FG,4$local_time_offset$FG$ global variable in a start-up file. Its units are $LK,"CDATE_FREQ",A="MN:CDATE_FREQ"$. See $LK,"local time",A="FF:~/HomeLocalize.ZC,local_time"$. -* You can change the palette using the $LK+PU,"PaletteSet",A="FF:::/System/Gr/GrPalette.ZC,U0 PaletteSet"$ functions. Pressing $FG,2$$FG$ toggles standard and VGA ROM font. +* You can change the palette using the $LK+PU,"PaletteSet",A="FF:::/System/Gr/GrPalette.ZC,U0 PaletteSet"$ functions. Pressing $FG,2$$FG$ toggles standard and auxiliary font. * Get rid of this message $LK,"here",A="FF:~/Once.ZC,Customize.DD"$. diff --git a/src/Doc/FAQ.DD b/src/Doc/FAQ.DD index ec7be4ad..117f768f 100755 --- a/src/Doc/FAQ.DD +++ b/src/Doc/FAQ.DD @@ -1,15 +1,15 @@ $WW,1$$FG,5$$TX+CX,"Frequently Asked Questions"$$FG$ $TR,"How come it is public domain, not GPL?"$ -$ID,2$$FG,2$Terry A. Davis$FG$, wrote all of TempleOS over a span of $FG,2$$TX,"15.0",D="DD_TEMPLEOS_AGE"$$FG$ years (full-time). ZealOS, written over a span of $FG,2$$TX,"2.6",D="DD_ZEALOS_AGE"$$FG$ years, is a fork of TempleOS. It can run on some bare metal 64-bit PC's from about 2007-2019 with no layering, libraries, tools, modules or anything from other sources. Otherwise, you run it in a virtual machine, like $FG,2$VMware$FG$, $FG,2$QEMU$FG$ or $FG,2$VirtualBox$FG$. It is independent and stands alone. 100% of the src code is including on all distro's, from the kernel to the compiler to the boot loaders! See $LK,"::/Doc/Credits.DD"$. +$ID,2$$FG,2$Terry A. Davis$FG$, wrote all of TempleOS over a span of $FG,2$$TX,"15.0",D="DD_TEMPLEOS_AGE"$$FG$ years (full-time). ZealOS, written over a span of $FG,2$$TX,"3.2",D="DD_ZEALOS_AGE"$$FG$ years (part-time), is a fork of TempleOS. It can run on bare metal 64-bit PC's from about 2007-2019 with no layering, libraries, tools, modules or anything from other sources. Otherwise, you run it in a virtual machine, like $FG,2$VMware$FG$, $FG,2$QEMU$FG$ or $FG,2$VirtualBox$FG$. It is independent and can stand alone. 100% of the public-domain operating system source code is included on all distros, from the kernel to the compiler to the applications, including public-domain BIOS-mode boot loaders! See $LK,"::/Doc/Credits.DD"$. $ID,-2$$TR,"Shouldn't it be GNU/ZealOS?"$ -$ID,2$ZealOS executes 100% public-domain code. Boot-loaders were even written, so we do not need Grub. See $LK,"::/Doc/Credits.DD"$. +$ID,2$ZealOS executes 100% public-domain operating system code. Public-domain boot-loaders were even written, so we do not require Grub. Optional UEFI-compatible ZealOS distro builds can be made using Limine, a BSD-2 licensed bootloader, but this is never required for BIOS-mode. See $LK,"::/Doc/Credits.DD"$. $ID,-2$$TR,"Don't you use GNU's gcc?"$ $ID,2$ZealOS was written from scratch, starting with $FG,2$TASM$FG$ long ago, launching from real-mode DOS. Now, there is no $FG,2$Linux$FG$ or $FG,2$GNU$FG$ or any other code in ZealOS. Yes, the compiler was written from scratch. See $LK,"::/Doc/Credits.DD"$. $ID,-2$$TR,"Why do you dual boot?"$ $ID,2$ZealOS is 100% independent -- it does not access the files of your primary operating system and ZealOS will work as the only operating system on your computer. In your off hours, you will probably use your other operating system. $ID,-2$$TR,"It has links, so is it a browser?"$ -$ID,2$ZealOS is an operating system, not a browser. $LK,"ZealOS links",A="MN:LK_FILE"$ are a special format and only link too local files and symbol source addresses. +$ID,2$ZealOS is an operating system, not a browser. $LK,"ZealOS links",A="MN:LK_FILE"$ are a special format and only link to local files and symbol source addresses. $ID,-2$$TR,"Where are the animated 3D icon GIFs?"$ $ID,2$3D $LK,"Sprites",A="FI:::/Doc/Sprite.DD"$ are stored as a mesh of triangles. There are no GIF files. It $LK,"rotates",A="MN:Mat4x4MulXYZ"$ 3D sprite objects on the fly. $ID,-2$$TR,"If the compiler is JIT, isn't it an interpretor?"$ @@ -55,11 +55,11 @@ $ID,2$If you use Grub, you $FG,2$chain-load$FG$ like Windows. See $LK,"Boot",A= $ID,-2$$TR,"How do I get Kernel.ZXE to boot?"$ $ID,2$The boot-loaders must be patched by you running $LK,"BootHDIns",A="MN:BootHDIns"$() or $LK,"BootMHDIns",A="MN:BootMHDIns"$(). Those will write the block address into the boot-loader because the boot-loaders do not navigate file systems to find the $LK,"Stage2",A="FI:::/Kernel/KStart16.ZC"$ if you relocate it. $ID,-2$$TR,"Why is there some 16-Bit code?"$ -$ID,2$ZealOS is 64-bit. Like all PC operating systems, the boot-loader starts in 16-bit real-mode. ZealOS calls a few $FG,2$BIOS$FG$ info routines, switches to VGA-640x480x4bit, switches to 32-bit, then, 64-bit mode. There is an odd thing called a $FG,2$$TX,"PCI BIOS",HTML="http://www.o3one.org/hwdocs/bios_doc/pci_bios_21.pdf"$$FG$ which is 32-bit used for $FG,2$PCI$FG$ config space access. If supported, ZealOS calls $LK,"that",A="FI:::/Kernel/PCIBIOS.ZC"$ a couple times, otherwise using Port I/O for PCI. It must temporarily drop-out-of 64-bit mode for that and stop multi-tasking. +$ID,2$ZealOS is 64-bit. Like all PC operating systems, the MBR boot-loader starts in 16-bit real-mode. ZealOS calls a few $FG,2$BIOS$FG$ info routines, switches to 32-bit, then, 64-bit mode. There is an odd thing called a $FG,2$$TX,"PCI BIOS",HTML="http://www.o3one.org/hwdocs/bios_doc/pci_bios_21.pdf"$$FG$ which is 32-bit used for $FG,2$PCI$FG$ config space access. If supported, ZealOS calls $LK,"that",A="FI:::/Kernel/PCIBIOS.ZC"$ a couple times, otherwise using Port I/O for PCI. It must temporarily drop-out-of 64-bit mode for that and stop multi-tasking. $ID,-2$$TR,"Why are you pushing 32-bit values on the stack?"$ $ID,2$$FG,2$PUSH EAX$FG$ : All stack operations in 64-bit mode are 64-bits. $ID,-2$$TR,"Why are you using 32-bit insts and not setting high 32-bits?"$ -$ID,2$$FG,2$XOR EAX,EAX$FG$ : Operations on 32-bit registers clear the high 32-bits. +$ID,2$$FG,2$XOR EAX, EAX$FG$ : Operations on 32-bit registers clear the high 32-bits. $ID,-2$$TR,"How do you use the FS and GS segment registers."$ $ID,2$$FG,2$MOV RAX,FS:[RAX]$FG$ : FS can be set with a $FG,2$WRMSR$FG$, but displacement is RIP relative, so it's tricky to use. FS is used for the current $LK,"CTask",A="MN:CTask"$, GS for $LK,"CCPU",A="MN:CCPU"$. $ID,-2$$TR,"How do I set ORG for position of code?"$ @@ -89,4 +89,4 @@ $FG,8$ * "QEMU" is a trademark owned by Fabrice Bellard. * "VMware" is a trademark owned by VMware, Inc. * "VirtualBox" is a trademark owned by Oracle. -$FG$ \ No newline at end of file +$FG$ diff --git a/src/Doc/Features.DD b/src/Doc/Features.DD index 20657e98..e5d48859 100755 --- a/src/Doc/Features.DD +++ b/src/Doc/Features.DD @@ -6,7 +6,7 @@ * Master/Slave MultiCore -* Free, $FG,2$public domain$FG$, $FG,2$100% open source$FG$. +* Free, $FG,2$public domain$FG$, $FG,2$100% open source$FG$ operating system code. * 64-bit $FG,2$compiler/assembler$FG$ for $LK,"ZealC",A="FI:::/Doc/ZealC.DD"$. Truly compiles, doesn't interpret. $FG,2$Just-in-Time$FG$ and $FG,2$Ahead-of-Time$FG$ compilation. With $FG,2$JIT$FG$, no need for object or exe files. @@ -50,4 +50,4 @@ * Many games, $LK,"demos",A="FI:::/Doc/DemoIndex.DD"$ and $LK,"documentation",A="FI:::/Doc/HelpIndex.DD"$. -* $FG,2$All source code$FG$ included. Only compiles with the included ZealOS compiler and assembler. +* $FG,2$All operating system source code$FG$ included. Only compiles with the included ZealOS compiler and assembler. diff --git a/src/Doc/MemoryOverview.DD b/src/Doc/MemoryOverview.DD index c6e51555..21e4d552 100755 --- a/src/Doc/MemoryOverview.DD +++ b/src/Doc/MemoryOverview.DD @@ -8,7 +8,7 @@ You can create new, independent heaps using $LK,"HeapCtrlInit",A="MN:HeapCtrlIni Memory alloced by a task will be freed when the task is killed. The $LK,"System Task",A="FF:::/Doc/Glossary.DD,System Task"$ is a task that never dies. Its memory is like kernel memory in other operating systems. See $LK,"SysCAlloc",A="MN:SysCAlloc"$(), $LK,"SysMAlloc",A="MN:SysMAlloc"$(), $LK,"SysMAllocIdent",A="MN:SysMAllocIdent"$() and $LK,"SysStrNew",A="MN:SysStrNew"$(). -All of the regular page tables are marked, "cached". When accessing hardware, however, you need uncached page table. The lowest 4Gig addresses have an alias to access hardware located toward the top of mapped space, $FG,2$0x$TX,"0100000000",D="DD_UNCACHED_ALIAS"$$FG$. See $LK,"dev.uncached_alias",A="FF:::/Kernel/MultiProc.ZC,dev.uncached_alias"$. +All of the regular page tables are marked, "cached". When accessing hardware, however, you need uncached page table. The lowest 4Gig addresses have an alias to access hardware located toward the top of mapped space, $FG,2$0x$TX,"0124000000",D="DD_UNCACHED_ALIAS"$$FG$. See $LK,"dev.uncached_alias",A="FF:::/Kernel/MultiProc.ZC,dev.uncached_alias"$. During an extended powered-on session of ZealOS, in theory, memory will become fragmented, requiring a reboot. @@ -17,7 +17,7 @@ See $LK,"MemRep",A="MN:MemRep"$() and $LK,"::/Demo/MemDemo.ZC"$. $FG,5$$TX+CX,"Single System-wide Memory Map"$ -$FG,2$ 0x00$TX,"00007C00",D="DD_KERNEL"$- 0x00$TX,"0003813F",D="DD_KERNEL_END"$$FG$ +$FG,2$ 0x00$TX,"0003F000",D="DD_KERNEL"$- 0x00$TX,"000712CF",D="DD_KERNEL_END"$$FG$ $ID,2$Kernel module, placed here by the boot-loader, $LK,"BOOT_RAM_BASE",A="MN:BOOT_RAM_BASE"$. $ID,-2$ $FG,2$ 0x00$TX,"00096600",D="DD_BOOT_HIGH_LOC_DVD"$- 0x00$TX,"00096FFF",D="DD_BOOT_HIGH_LOC_DVD_END"$$FG$ @@ -25,21 +25,20 @@ $ID,2$$FG$Boot block relocated here before loading the Kernel module, $LK,"BootD $ID,-2$ $FG,2$ 0x00$TX,"00097000",D="DD_MP_VECT"$- 0x00$TX,"0009703B",D="DD_MP_VECT_END"$$FG$ Multicore start-up vect code, $LK,"MPN_VECT",A="MN:MPN_VECT"$. $FG,2$~0x000009F000- 0x000009FFFF$FG$ Extended BIOS data area. -$FG,2$ 0x00000A0000- 0x00000BFFFF$FG$ VGA graphics mem with alias at $LK,"text",A="MN:text"$.vga_alias. $FG,2$ 0x00$TX,"00100000",D="DD_SYS_FIXED_AREA_BASE"$- 0x00$TX,"00102FFF",D="DD_SYS_FIXED_AREA_END"$$FG$ $LK,"CSysFixedArea",A="MN:CSysFixedArea"$ for misc. -$FG,2$ 0x00$TX,"0010D000",D="DD_MEM_HEAP_BASE"$- 0x00$TX,"33BFFFFF",D="DD_MEM_HEAP_LIMIT"$$FG$ Code Heap mem. +$FG,2$ 0x00$TX,"0010E000",D="DD_MEM_HEAP_BASE"$- 0x00$TX,"3FFE37FF",D="DD_MEM_HEAP_LIMIT"$$FG$ Code Heap mem. $FG,2$ 0x00E0000000- 0x00FFFFFFFF$FG$ $ID,2$32-bit devices could alloc memory at 0xF0000000 going up, but this is wrong, since some PCs already have devices at 0xF0000000. PCI devices are supported, so $LK,"Mem32DevAlloc",A="MN:Mem32DevAlloc"$() flaws could become an issue. $ID,-2$ $FG,2$ 0x0080000000-~0x00DFFFFFFF$FG$ -$FG,2$ 0x0100000000-~0x$TX,"00FFFFFFFF",D="DD_PHYSICAL_SPACE_END"$$FG$ +$FG,2$ 0x0100000000-~0x$TX,"0123FFFFFF",D="DD_PHYSICAL_SPACE_END"$$FG$ $ID,2$Data Heap mem. (The physical memory that exists in this range is data heap.) $ID,-2$ -$FG,2$ 0x$TX,"0100000000",D="DD_UNCACHED_ALIAS"$- 0x$TX,"01FFFFFFFF",D="DD_MAPPED_SPACE_END"$$FG$ +$FG,2$ 0x$TX,"0124000000",D="DD_UNCACHED_ALIAS"$- 0x$TX,"0223FFFFFF",D="DD_MAPPED_SPACE_END"$$FG$ $ID,2$Uncached alias of first 4Gig. (For 32-bit device access.) $ID,-2$ -$FG,2$ - 0x$TX,"01FFFFFFFF",D="DD_MAPPED_SPACE_END"$$FG$ +$FG,2$ - 0x$TX,"0223FFFFFF",D="DD_MAPPED_SPACE_END"$$FG$ $ID,2$64-bit devices are alloced with $LK,"Mem64DevAlloc",A="MN:Mem64DevAlloc"$() counting backward$WW,0$. $ID,-2$ @@ -55,7 +54,7 @@ In 2003, Terry Davis wanted to make a no-paging ring-0-only 64-bit operating sys Terry needed VGA A0000-BFFFF memory to be write-through and 0xE0000000-0xFFFFFFFF to be uncached for various devices. All 64-bit computers allow stopping address translation at 2Meg page size, not using 4K. He wanted to use 2Meg for everything because it's faster, with one less level of page tables. He had to make A0000-BFFFF write-through, though, so he could not use 2Meg size on the lowest page. He did the lowest 2Meg area as 4K pages. He also unmapped the first 4K to cause a fault when dereferencing NULL. -In 2016, Terry came-up with an alternate idea. He double mapped the lowest memory with an alias that was uncached. Accessing the lowest 2Meg area directly was cached but the alias he created up at the top of address space was uncached. See $LK,"UncachedAliasAlloc",A="MN:UncachedAliasAlloc"$(). Unfortunately, he could no longer boast of the simplicity of identity mapping everything. Since many of the users are familiar with A0000-BFFFF, it is actually pretty seriously unfortunate that they cannot use the easy-to-understand numbers of A0000-BFFFF, but must access the relocated alias location. See $LK,"text.vga_alias",A="FF:::/Kernel/KMain.ZC,text.vga_alias"$. We also no longer cause a fault when dereferencing NULL. +In 2016, Terry came-up with an alternate idea. He double mapped the lowest memory with an alias that was uncached. Accessing the lowest 2Meg area directly was cached but the alias he created up at the top of address space was uncached. See $LK,"UncachedAliasAlloc",A="MN:UncachedAliasAlloc"$(). Unfortunately, he could no longer boast of the simplicity of identity mapping everything. We also no longer cause a fault when dereferencing NULL. Then, Terry switched to 1Gig page sizes. For the lowest 4Gig, he set-up an alias up at the top of address space. See $LK,"UncachedAliasAlloc",A="MN:UncachedAliasAlloc"$(). Not all computers support 1Gig page tables, however, so he also supported 2Meg. diff --git a/src/Doc/Start.DD b/src/Doc/Start.DD index 701db648..0bbaaddd 100755 --- a/src/Doc/Start.DD +++ b/src/Doc/Start.DD @@ -1,5 +1,5 @@ -$WW+H,1$$FG,5$$TX+CX,"ZealOS V1.13",D="DD_OS_NAME_VERSION"$$FG$ +$WW+H,1$$FG,5$$TX+CX,"ZealOS V2.00",D="DD_OS_NAME_VERSION"$$FG$ $TX+CX,"Public Domain Operating System"$ diff --git a/src/Doc/Strategy.DD b/src/Doc/Strategy.DD index 8159ee95..0fc0ea1d 100755 --- a/src/Doc/Strategy.DD +++ b/src/Doc/Strategy.DD @@ -6,9 +6,9 @@ Windows is a car. ZealOS is a motorcycle -- if you lean-over too far, a motorcycle will crash. Don't do that! There are no side air bags on a motorcycle. DOS and C64 had no memory protections and ran in ring-0, with no security. This saves an order of magnitude complexity. -Linux and Windows are general purpose operating systems. They attempt to do any task you want. ZealOS cherry-picks tasks and is designed to do the same things a C64 did. This saves and order of magnitude complexity. For example, the $LK,"RedSea",A="FI:::/Doc/RedSea.DD"$ file system allocates just contiguous files -- you load and save whole files at once. Also, ZealOS does not do multimedia. In theory, memory will fragment with lots of big files. The system would fall to pieces with multimedia. +Linux and Windows are general purpose operating systems. They attempt to do any task you want. ZealOS cherry-picks tasks and is designed to do the same things a C64 did. This saves and order of magnitude complexity. For example, the $LK,"RedSea",A="FI:::/Doc/RedSea.DD"$ file system allocates just contiguous files -- you load and save whole files at once. In theory, memory will fragment with lots of big files. -A three button mouse is like a leg you cannot put weight on. ZealOS just does hardware everybody has, with no divergent code bases for each machine's custom hardware. There is one graphics driver instead of 50 for different GPUs. This saves an order of magnitude complexity and makes for a delightful API, so developer's code is not like a frayed rope end. +A three button mouse is like a leg you cannot put weight on. ZealOS primarily just does hardware everybody has, avoiding divergent code bases for each machine's custom hardware. There is one CPU-driven graphics driver, instead of 50 for different GPUs. This saves an order of magnitude complexity and makes for a delightful API, so developer's code is not like a frayed rope end. diff --git a/src/Doc/Tips.DD b/src/Doc/Tips.DD index 5b50c9f0..eedb39bd 100755 --- a/src/Doc/Tips.DD +++ b/src/Doc/Tips.DD @@ -67,7 +67,7 @@ $FG,2$Merge("C:/","D:/","+r+d");$FG$ to check your changes. * Use $FG,2$$FG$ to enter an extended ASCII char. -* Use $FG,2$$FG$ to toggle between the $LK,"VGA ROM Font",A="FF:::/Kernel/KMain.ZC,SYS_FONT_PTR:2"$ and $LK,"Std Font",A="FI:::/Kernel/FontStd.ZC"$. +* Use $FG,2$$FG$ to toggle between the $LK,"Aux Font",A="FI:::/Kernel/FontAux.ZC"$ and $LK,"Std Font",A="FI:::/Kernel/FontStd.ZC"$. * Use $FG,2$$FG$ will capture the screen as a sprite on the clip. You can save the cmd line doc as text with $FG,2$$FG$. diff --git a/src/Doc/Welcome.DD b/src/Doc/Welcome.DD index 8cf6b891..e66e961d 100755 --- a/src/Doc/Welcome.DD +++ b/src/Doc/Welcome.DD @@ -7,7 +7,7 @@ $ID,2$* Professionals doing hobby projects * Teenagers doing projects * Non-professional, older-persons projects $ID,-2$ -Simplicity is a goal to $LK,"keep the line count down",A="FI:::/Doc/Strategy.DD"$, so it's easy to tinker with. As it turns-out, simplicity makes it faster in some ways, too. It never switches privilege levels, never changes address maps, tends to load whole contiguous files and other, similar things which boost speed. It's only $TX,"95,255",D="DD_ZEALOS_LOC"$ lines of code including the kernel, the 64-bit compiler, the graphics library and all the tools. More importantly, it's designed to keep the user's line count down -- you can do a $LK,"Hello World",A="FI:::/Doc/HelloWorld.DD"$ application in one line of code and can put graphics on the screen with a three line program! +Simplicity is a goal to $LK,"keep the line count down",A="FI:::/Doc/Strategy.DD"$, so it's easy to tinker with. As it turns-out, simplicity makes it faster in some ways, too. It never switches privilege levels, never changes address maps, tends to load whole contiguous files and other, similar things which boost speed. It's only $TX,"98,658",D="DD_ZEALOS_LOC"$ lines of code including the kernel, the 64-bit compiler, the graphics library and all the tools. More importantly, it's designed to keep the user's line count down -- you can do a $LK,"Hello World",A="FI:::/Doc/HelloWorld.DD"$ application in one line of code and can put graphics on the screen with a three line program! It's a kayak, not a Titanic -- it will crash if you do something wrong. You quickly reboot, however. DOS and the 8-bit home computers of the 80's worked fine without memory protection and most computers in the world -- the embedded ones -- operate without protection. The resulting simplicity of no protections is why ZealOS has value. In facts, that's the point of ZealOS. See the $LK,"ZealOS Charter",A="FI:::/Doc/Charter.DD"$. @@ -118,7 +118,7 @@ Software is distributed as $LK,"RedSea",A="FI:::/Doc/RedSea.DD"$ ISO files. Bur Ideally, do not install applications such as games onto your hard drive because we wish to keep hard drive usage low, so the whole $FG,2$'C'$FG$ drive can be copied quickly to $FG,2$'D'$FG$. Also, the $LK,"FileMgr",A="MN:FileMgr"$() $FG,2$$FG$ starts too slowly when there are lots of hard drive files, but that is how we want it. -3rd party libraries are banned, since they circumvent the 100,000 line of code limit in the $LK,"ZealOS Charter",A="FI:::/Doc/Charter.DD"$. All applications must only depend on the core ZealOS files and whatever they bring along in the ISO. This is similar to how Commodore 64 applications only depended on the ROM. +3rd party libraries are banned from being required, since they circumvent the 100,000 line of code limit in the $LK,"ZealOS Charter",A="FI:::/Doc/Charter.DD"$. All applications must only depend on the core ZealOS files and whatever they bring along in the ISO. This is similar to how Commodore 64 applications only depended on the ROM. $MA-X+PU,"Take Tour",LM="User(\"Cd(\\\"::/Misc/Tour\\\");;InFile(\\\"Tour\\\");\n\");"$ diff --git a/src/Doc/WhyNotMore.DD b/src/Doc/WhyNotMore.DD index 2296d899..0b868cf1 100755 --- a/src/Doc/WhyNotMore.DD +++ b/src/Doc/WhyNotMore.DD @@ -10,9 +10,7 @@ In the CPU department, ZealOS has state of the art 64-bit $LK,"long mode",A="FI: Terry Davis made an incredible accomplishment by getting it to work on practically everyone's computer as long as it is 64-bit and they run inside VMware, QEMU or VirtualBox. -Adding a USB driver would be really ugly with UHCI, EHCI, OHCI, USB1, USB2, USB3, ICH6, ICH7, ICH8, ICH9, ICH10, ICH11, ICH12, boot mode and regular mode for keyboard/mouse and a diversity of HID reports. It's hopeless. It could never offer anything but crappy, limited support and it would just add a ton of crappy code that mostly didn't work. What would ZealOS gain? Nothing. A keyboard or mouse would not be improved. Solid State USB drives would be nice, but it's not going to happen. - -UEFI is pointless. If ZealOS is forced to run in VMware, QEMU or VirtualBox, they will always support non-UEFI mode. Without working, native hard drive and CD/DVD drivers, you can't get very far with UEFI on a native install, not to mention SecureBoot. UEFI is, first of all, redundant. If non-UEFI works in a virtual machine, supporting UEFI would only be redundant, ugly nasty code. The compiler does not create an ELF or PE format. We would have to ruin the beauty of the compiler. +The compiler does not create an ELF or PE format. We would have to ruin the beauty of the compiler. God talks. $FG,8$ diff --git a/src/Home/DoDistro.ZC b/src/Home/DoDistro.ZC index 6e286d93..62fe40a1 100755 --- a/src/Home/DoDistro.ZC +++ b/src/Home/DoDistro.ZC @@ -1,6 +1,6 @@ //Make Your own Distro by #include-ing this file. -#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n1024\n768\n\n\n" +#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n\n\n" U0 MakeMyISO(U8 *_out_iso_filename) {//Does everything with current drive. diff --git a/src/Home/K.ZC b/src/Home/K.ZC deleted file mode 100755 index 545a4185..00000000 --- a/src/Home/K.ZC +++ /dev/null @@ -1,39 +0,0 @@ -Ed("/Doc/ChangeLog.DD"); - -CAHCIPort *port; -I64 i, ata_drive = -1; - -// Find first-available ATA drive for BootHDIns. -for (i = 0; i < AHCI_MAX_PORTS; i++) -{ - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) - { - port = &blkdev.ahci_hba->ports[i]; - if (port->signature == AHCI_PxSIG_ATA) - { - ata_drive = i; - break; - } - } -} - -if (ata_drive < 0) - throw('No ATA'); - -In("CC\n%d\n\n1024\n768\n\n\n", ata_drive); -BootHDIns; - -"\n\nSuccessful? "; -if (YorN) -{ - Once( "CursorRemove(\"/*\");;;" - "PopUp(\"#include \\\"DoDistro\\\";;" - "if (DriveIsWritable)" - "{" - "Del(\\\"~/Registry.ZC\\\");" - "Del(\\\"~/MakeHome.ZC\\\");" - "OutU16(0x4004, 0x3400);" - "}\");"); - - BootRAM; -} diff --git a/src/Home/Net/Drivers/E1000.ZC b/src/Home/Net/Drivers/E1000.ZC index 0496d601..d39944e6 100755 --- a/src/Home/Net/Drivers/E1000.ZC +++ b/src/Home/Net/Drivers/E1000.ZC @@ -239,7 +239,7 @@ U16 E1000EEPROMRead(U8 word) E1000MMIOWrite(E1000_REG_EERD, 1 | word << 8); temp = E1000MMIORead(E1000_REG_EERD); - while (!Bt(&temp, E1000_EERDf_DONE)) + while (!PCIBt(&temp, E1000_EERDf_DONE)) { Sleep(1); temp = E1000MMIORead(E1000_REG_EERD); @@ -278,7 +278,7 @@ I64 E1000PacketReceive(U8 **packet_buffer_out, U16 *packet_length_out) drop = TRUE; } - if (Bt(&entry->status, E1000_RDESC_STATUSf_EOP)) + if (PCIBt(&entry->status, E1000_RDESC_STATUSf_EOP)) { NetErr("E1000 PACKET RECEIVE: No EOP Set"); drop = TRUE; @@ -316,7 +316,7 @@ U0 E1000ReceivePacketRelease(I64 de_index) Bool E1000DriverOwnsRX(CE1000DescriptorEntryRX *entry) { - return Bt(&entry->status, 0); // ?? TODO #define + return PCIBt(&entry->status, 0); // ?? TODO #define } I64 E1000TransmitPacketAllocate(U8 **packet_buffer_out, I64 length) @@ -330,9 +330,9 @@ I64 E1000TransmitPacketAllocate(U8 **packet_buffer_out, I64 length) entry->address = *packet_buffer_out; entry->length = length; - Bts(&entry->cmd, E1000_TDESC_CMDf_EOP); - Bts(&entry->cmd, E1000_TDESC_CMDf_IFCS); - Bts(&entry->cmd, E1000_TDESC_CMDf_RS); + PCIBts(&entry->cmd, E1000_TDESC_CMDf_EOP); + PCIBts(&entry->cmd, E1000_TDESC_CMDf_IFCS); + PCIBts(&entry->cmd, E1000_TDESC_CMDf_RS); NetLog("E1000 ALLOCATE TX PACKET: de_index: %X.", de_index); return de_index; @@ -370,23 +370,23 @@ interrupt U0 E1000IRQ() icr &= ~(E1000_ICRF_TXDW | E1000_ICRF_TXQE); - if (Bt(&icr, E1000_ICRf_LSC)) // 'link status change' ? + if (PCIBt(&icr, E1000_ICRf_LSC)) // 'link status change' ? { - Btr(&icr, E1000_ICRf_LSC); + PCIBtr(&icr, E1000_ICRf_LSC); E1000MMIOWrite(E1000_REG_CTRL, E1000MMIORead(E1000_REG_CTRL) | E1000_CTRLF_SLU); } - if (Bt(&icr, E1000_ICRf_RXO) || Bt(&icr, E1000_ICRf_RXDMT)) // 'rx underrun / min threshold' ? + if (PCIBt(&icr, E1000_ICRf_RXO) || PCIBt(&icr, E1000_ICRf_RXDMT)) // 'rx underrun / min threshold' ? { - Btr(&icr, E1000_ICRf_RXO); - Btr(&icr, E1000_ICRf_RXDMT); + PCIBtr(&icr, E1000_ICRf_RXO); + PCIBtr(&icr, E1000_ICRf_RXDMT); poll = TRUE; } - if (Bt(&icr, E1000_ICRf_RXT)) // 'packet pending' ? + if (PCIBt(&icr, E1000_ICRf_RXT)) // 'packet pending' ? { - Btr(&icr, E1000_ICRf_RXT); + PCIBtr(&icr, E1000_ICRf_RXT); poll = TRUE; } diff --git a/src/Home/Net/Drivers/PCNet.ZC b/src/Home/Net/Drivers/PCNet.ZC index 861a269a..963b0e3c 100755 --- a/src/Home/Net/Drivers/PCNet.ZC +++ b/src/Home/Net/Drivers/PCNet.ZC @@ -199,7 +199,7 @@ U0 PCNetSWStyleSet() csr &= ~0xFF; // clears first 8 bits: SWSTYLE 8-bit register. csr |= PCNET_SWSTYLE_SELECTION; // set SWSTYLE to PCNet-PCI mode. - Bts(&csr, PCNET_SWSTYLE_SSIZE32); // set SSIZE32 bit 1 + PCIBts(&csr, PCNET_SWSTYLE_SSIZE32); // set SSIZE32 bit 1 PCNetCSRWrite(PCNET_CSR_SOFTWARESTYLE, csr); } @@ -239,7 +239,7 @@ U0 PCNetDescriptorEntryInit(CPCNetDescriptorEntry *entry, U32 buffer_address, I6 //if this is a Receive DE, give ownership to the card so the PCNet can fill them. if (is_rx) - Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); + PCIBts(&entry->status1, PCNET_DESCRIPTORf_OWN); } U0 PCNetBuffersAllocate() @@ -397,11 +397,11 @@ U0 PCNetInterruptCSRSet() U32 csr = PCNetCSRRead(PCNET_CSR_INTERRUPTS); - Btr(&csr, PCNET_INT_BSWP); - Btr(&csr, PCNET_INT_RINTM); + PCIBtr(&csr, PCNET_INT_BSWP); + PCIBtr(&csr, PCNET_INT_RINTM); - Bts(&csr, PCNET_INT_IDONM); - Bts(&csr, PCNET_INT_TINTM); + PCIBts(&csr, PCNET_INT_IDONM); + PCIBts(&csr, PCNET_INT_TINTM); PCNetCSRWrite(PCNET_CSR_INTERRUPTS, csr); } @@ -414,7 +414,7 @@ U0 PCNetTXAutoPadEnable() U32 csr = PCNetCSRRead(PCNET_CSR_FEATURECTRL); - Bts(&csr, PCNET_FEATURE_APADXMT); + PCIBts(&csr, PCNET_FEATURE_APADXMT); PCNetCSRWrite(PCNET_CSR_FEATURECTRL, csr); } @@ -429,10 +429,10 @@ U0 PCNetConfigModeExit() U32 csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - Btr(&csr, PCNET_CTRL_INIT); - Btr(&csr, PCNET_CTRL_STOP); + PCIBtr(&csr, PCNET_CTRL_INIT); + PCIBtr(&csr, PCNET_CTRL_STOP); - Bts(&csr, PCNET_CTRL_STRT); + PCIBts(&csr, PCNET_CTRL_STRT); PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr); } @@ -442,7 +442,7 @@ I64 PCNetDriverOwns(CPCNetDescriptorEntry* entry) Descriptor Entry is zero. If 0, driver owns, if 1, PCNet card owns it. */ - return !Bt(&entry->status1, PCNET_DESCRIPTORf_OWN); + return !PCIBt(&entry->status1, PCNET_DESCRIPTORf_OWN); } I64 PCNetTransmitPacketAllocate(U8 **packet_buffer_out, I64 length) @@ -474,9 +474,9 @@ I64 PCNetTransmitPacketAllocate(U8 **packet_buffer_out, I64 length) NetLog("PCNET ALLOCATE TX PACKET: Driver owns TX DE at index %d.", de_index); } - Bts(&entry->status1, PCNET_DESCRIPTORf_STP); + PCIBts(&entry->status1, PCNET_DESCRIPTORf_STP); - Bts(&entry->status1, PCNET_DESCRIPTORf_ENP); + PCIBts(&entry->status1, PCNET_DESCRIPTORf_ENP); /* AMD PCNet datasheet p.1-991. BCNT is the usable buffer length, expressed as first @@ -512,9 +512,9 @@ U0 PCNetTransmitPacketFinish(I64 de_index) CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)]; - Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); + PCIBts(&entry->status1, PCNET_DESCRIPTORf_OWN); NetLog("PCNET FINISH TX PACKET: TX DE index: %X, OWN bit of entry at entry: %b.", - de_index, Bt(&entry->status1, PCNET_DESCRIPTORf_OWN)); + de_index, PCIBt(&entry->status1, PCNET_DESCRIPTORf_OWN)); } U0 NetDriverTransmitPacketFinish(I64 de_index) @@ -570,7 +570,7 @@ U0 PCNetReceivePacketRelease(I64 de_index) CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)]; - Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); + PCIBts(&entry->status1, PCNET_DESCRIPTORf_OWN); } interrupt U0 PCNetIRQ() @@ -603,7 +603,7 @@ interrupt U0 PCNetIRQ() PCNetReceivePacketRelease(de_index); } - Bts(&csr, PCNET_CTRL_RINT); + PCIBts(&csr, PCNET_CTRL_RINT); PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr); @@ -666,10 +666,10 @@ U0 PCNetInit() PCNet32BitModeEnable; U32 csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - NetLog("PCNET INIT START: what is INIT ?: %d", Bt(&csr, PCNET_CTRL_INIT)); - NetLog("PCNET INIT START: what is STRT ?: %d", Bt(&csr, PCNET_CTRL_STRT)); - NetLog("PCNET INIT START: what is STOP ?: %d", Bt(&csr, PCNET_CTRL_STOP)); - NetLog("PCNET INIT START: what is RINT ?: %d", Bt(&csr, PCNET_CTRL_RINT)); + NetLog("PCNET INIT START: what is INIT ?: %d", PCIBt(&csr, PCNET_CTRL_INIT)); + NetLog("PCNET INIT START: what is STRT ?: %d", PCIBt(&csr, PCNET_CTRL_STRT)); + NetLog("PCNET INIT START: what is STOP ?: %d", PCIBt(&csr, PCNET_CTRL_STOP)); + NetLog("PCNET INIT START: what is RINT ?: %d", PCIBt(&csr, PCNET_CTRL_RINT)); PCNetSWStyleSet; @@ -689,10 +689,10 @@ U0 PCNetInit() PCNetCSRWrite(0, PCNetCSRRead(0) | 1 | 1 << 6); // ? csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - NetLog("PCNET INIT UPLOAD: what is INIT ?: %d", Bt(&csr, PCNET_CTRL_INIT)); - NetLog("PCNET INIT UPLOAD: what is STRT ?: %d", Bt(&csr, PCNET_CTRL_STRT)); - NetLog("PCNET INIT UPLOAD: what is STOP ?: %d", Bt(&csr, PCNET_CTRL_STOP)); - NetLog("PCNET INIT UPLOAD: what is RINT ?: %d", Bt(&csr, PCNET_CTRL_RINT)); + NetLog("PCNET INIT UPLOAD: what is INIT ?: %d", PCIBt(&csr, PCNET_CTRL_INIT)); + NetLog("PCNET INIT UPLOAD: what is STRT ?: %d", PCIBt(&csr, PCNET_CTRL_STRT)); + NetLog("PCNET INIT UPLOAD: what is STOP ?: %d", PCIBt(&csr, PCNET_CTRL_STOP)); + NetLog("PCNET INIT UPLOAD: what is RINT ?: %d", PCIBt(&csr, PCNET_CTRL_RINT)); while (!(PCNetCSRRead(0) & 1 << 8)) // ? Yield; @@ -702,15 +702,15 @@ U0 PCNetInit() Sleep(100); //? necessary? csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - NetLog("PCNET INIT END: what is INIT ?: %d", Bt(&csr, PCNET_CTRL_INIT)); - NetLog("PCNET INIT END: what is STRT ?: %d", Bt(&csr, PCNET_CTRL_STRT)); - NetLog("PCNET INIT END: what is STOP ?: %d", Bt(&csr, PCNET_CTRL_STOP)); - NetLog("PCNET INIT END: what is RINT ?: %d", Bt(&csr, PCNET_CTRL_RINT)); - NetLog("PCNET INIT END: what is TXON ?: %d", Bt(&csr, 4)); - NetLog("PCNET INIT END: what is RXON ?: %d", Bt(&csr, 5)); + NetLog("PCNET INIT END: what is INIT ?: %d", PCIBt(&csr, PCNET_CTRL_INIT)); + NetLog("PCNET INIT END: what is STRT ?: %d", PCIBt(&csr, PCNET_CTRL_STRT)); + NetLog("PCNET INIT END: what is STOP ?: %d", PCIBt(&csr, PCNET_CTRL_STOP)); + NetLog("PCNET INIT END: what is RINT ?: %d", PCIBt(&csr, PCNET_CTRL_RINT)); + NetLog("PCNET INIT END: what is TXON ?: %d", PCIBt(&csr, 4)); + NetLog("PCNET INIT END: what is RXON ?: %d", PCIBt(&csr, 5)); csr = PCNetCSRRead(PCNET_CSR_POLLINT); - NetLog("PCNET INIT END: what is POLLINT ?: %d", Bt(&csr, PCNET_CTRL_RINT)); + NetLog("PCNET INIT END: what is POLLINT ?: %d", PCIBt(&csr, PCNET_CTRL_RINT)); NetLog("PCNET INIT END: Redirecting interrupts."); PCNetInterruptsSetup; @@ -763,7 +763,7 @@ U0 NetStop() { // Halt network activity by setting STOP bit on Status CSR. U32 csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - Bts(&csr, PCNET_CTRL_STOP); + PCIBts(&csr, PCNET_CTRL_STOP); PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr); @@ -773,7 +773,7 @@ U0 NetStart() { // Continue network activity. Setting START bit clears STOP/INIT. U32 csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS); - Bts(&csr, PCNET_CTRL_STRT); + PCIBts(&csr, PCNET_CTRL_STRT); PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr); } diff --git a/src/Home/PaletteEditor/Palettes/Amicus.ZC b/src/Home/PaletteEditor/Palettes/Amicus.ZC index 5496c49b..6c774b9e 100755 --- a/src/Home/PaletteEditor/Palettes/Amicus.ZC +++ b/src/Home/PaletteEditor/Palettes/Amicus.ZC @@ -1,5 +1,5 @@ public CBGR24 gr_palette_amicus[COLORS_NUM] = { -0x0, 0x1A4883, 0x8D2E75, 0xFFA995, 0xA10000, 0xFFC0FF, 0x8B5858, 0xB2B6AF, 0x555753, 0xC5A5, 0x82BC49, 0x8ABEE1, 0xDF2100, 0xD138D1, 0xFFFFFF, 0x969696 +0x0, 0x1A4883, 0x8D2E75, 0xFFA995, 0xA10000, 0xFFC0FF, 0x8B5858, 0xB2B6AF, 0x555753, 0xE4D2, 0x82BC49, 0x8AE0C0, 0xDF2100, 0xB800B2, 0xFFFFFF, 0x969696 }; public U0 PaletteSetAmicus(Bool persistent=TRUE) { @@ -7,4 +7,4 @@ public U0 PaletteSetAmicus(Bool persistent=TRUE) LFBFlush; if (persistent) fp_set_std_palette = &PaletteSetAmicus; -} \ No newline at end of file +} diff --git a/src/Home/PaletteEditor/Palettes/Commander.ZC b/src/Home/PaletteEditor/Palettes/Commander.ZC index c3cf8775..f6c36d65 100755 --- a/src/Home/PaletteEditor/Palettes/Commander.ZC +++ b/src/Home/PaletteEditor/Palettes/Commander.ZC @@ -1,5 +1,5 @@ public CBGR24 gr_palette_commander[COLORS_NUM] = { -0xFFFFFF, 0x867ADE, 0xCC55, 0x5A878B, 0xEE0000, 0xCC44CC, 0xDD8855, 0xBBBBBB, 0x777777, 0x9BFF, 0xAAFF66, 0xAAFFEE, 0xFF7777, 0xCA94E8, 0xEEEE77, 0x483AAA +0xFFFFFF, 0x867ADE, 0xCC55, 0x5A878B, 0xFF0000, 0xCC44CC, 0xDD8855, 0xE1E1E2, 0x777777, 0x9BFF, 0xAAFF66, 0xAAFFEE, 0xFF7777, 0xCA94E8, 0xEEEE77, 0x483AA7 }; public U0 PaletteSetCommander(Bool persistent=TRUE) { diff --git a/src/Home/Roadmap.DD b/src/Home/Roadmap.DD deleted file mode 100755 index 00c610fe..00000000 --- a/src/Home/Roadmap.DD +++ /dev/null @@ -1,25 +0,0 @@ -$WW$$FG,5$$TX+CX,"Project Roadmap"$$FG$ - -The goal is to be a fully-functional, self-reproducing x86_64 PC operating system running in $FG,2$ring-0 only$FG$, designed for modern machines with $FG,2$AHCI$FG$. - -Roadmap: - -- AHCI driver that is capable of reading and burning CD/DVD discs (ñR/W). - -- Write drivers for the 5 most common ethernet cards. - - PCNet-II (Virtualbox) - - 82545EM (VMWare; QEMU?) - - ... - - ... - - ... - -- Create a clean and robust networking stack that supports sockets, TCP, UDP, IP, ICMP, DHCP, and an HTTP library. - - Write applications using this networking stack. - - Write a JSON library, so REST APIs can be used. - - Whole system VCS, with root being top-level directory. Stored repo inside the OS, you can checkout any commit onto another partition and boot it to see what the OS was like in that commit. - - Pull updates directly onto root filesystem from network. (it's a repo source tree after all). - -- Code clean up and refactoring. - -- Perhaps support for USB keyboard and mice. - diff --git a/src/HomeLocalize.ZC b/src/HomeLocalize.ZC index e2ace27d..7e37bd1f 100755 --- a/src/HomeLocalize.ZC +++ b/src/HomeLocalize.ZC @@ -7,6 +7,9 @@ KbdTypeMatic(0); //Set Time Zone local_time_offset = 0 * 60 * 60 * CDATE_FREQ; //Do daylight savings by hand +//Set screen zoom behaviour +gr.continuous_scroll = TRUE; + //$AN,"",A="mouse_move_scale"$adjust these to set mouse move scale mouse_hard.scale.x = 0.7; mouse_hard.scale.y = 0.7; diff --git a/src/Kernel/BlkDev/DiskAHCI.ZC b/src/Kernel/BlkDev/DiskAHCI.ZC index fa9be7f1..7832501a 100755 --- a/src/Kernel/BlkDev/DiskAHCI.ZC +++ b/src/Kernel/BlkDev/DiskAHCI.ZC @@ -1,11 +1,18 @@ /* -- Perhaps make more references to spec in comments +- Make more references to spec in comments -- ATAPI RW +- ATAPI RW needs cleaning up / improving - Remove Buffer alignment check and just do it on every call -- AHCIATAPISetMaxSpeed? +- AHCIATAPISetMaxSpeed needs to be implemented + +- TODO FIXME: Variable casting into AHCI memory-mapped areas caused strange crashes + on a Ryzen with Gigabyte brand motherboard, all PCI devices AMD brand. + Compiler casting internal functionality needs to be researched to fix those bugs. + Example line that caused crashes with Page Faults and bad memory address on Ryzen: + cmd_header = &port->cmd_list_base(CPortCmdHeader *)[i]; + */ I64 AHCI_DEBUG = FALSE; @@ -25,24 +32,24 @@ U0 AHCIDebug(I64 port_num) "\nAHCI Port: %d", port_num; "\nPort Interrupt Status: %b", port->interrupt_status; - if (Bt(&port->interrupt_status, AHCI_PxIf_CPDS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_CPDS)) "\n\tCold Port Detect Status"; - if (Bt(&port->interrupt_status, AHCI_PxIf_TFE)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_TFE)) "\n\tTask File Error"; - if (Bt(&port->interrupt_status, AHCI_PxIf_HBFS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_HBFS)) "\n\tHost Bus Fatal Error"; - if (Bt(&port->interrupt_status, AHCI_PxIf_HBDS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_HBDS)) "\n\tHost Bus Data Error"; - if (Bt(&port->interrupt_status, AHCI_PxIf_IFS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_IFS)) "\n\tSATA Interface Fatal Error"; - if (Bt(&port->interrupt_status, AHCI_PxIf_INFS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_INFS)) "\n\tSATA Interface Non-Fatal Error"; - if (Bt(&port->interrupt_status, AHCI_PxIf_OFS)) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_OFS)) "\n\tOverflow Status (HBA RX bytes > PRDT bytes)"; "\nPort Command: %b", port->command; "\nPort Command Issue: %b", port->cmd_issue; "\nPort Task File Data: %b", port->task_file_data; - if (Bt(&port->task_file_data, AHCI_PxTFDf_STS_ERR)) + if (PCIBt(&port->task_file_data, AHCI_PxTFDf_STS_ERR)) { "\n\tTask File Data Error"; "\n\tTask File Data Error Register: %b", port->task_file_data.u8[1]; @@ -51,27 +58,27 @@ U0 AHCIDebug(I64 port_num) "\nPort SATA Status: %b", port->sata_status; "\nPort SATA Ctrl: %b", port->sata_ctrl; "\nPort SATA Error: %b", port->sata_error; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_I)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_I)) "\n\tRecovered Data Integrity Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_M)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_M)) "\n\tRecovered Communication Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_T)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_T)) "\n\tTransient Data Integrity Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_C)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_C)) "\n\tPersistent Communication Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_P)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_P)) "\n\tSATA Protocol Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_ERR_E)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_ERR_E)) "\n\tInternal Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_DIAG_I)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_DIAG_I)) "\n\tPHY Internal Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_DIAG_C)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_DIAG_C)) "\n\tLink Layer CRC Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_DIAG_H)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_DIAG_H)) "\n\tHandshake Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_DIAG_S)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_DIAG_S)) "\n\tLink Sequence Error"; - if (Bt(&port->sata_error, AHCI_PxSERR_DIAG_T)) + if (PCIBt(&port->sata_error, AHCI_PxSERR_DIAG_T)) "\n\tTransport State Transition Error"; "\nPort SATA Active: %b", port->sata_active; "\nPort SATA Notif: %b", port->sata_notif; @@ -85,14 +92,14 @@ U0 AHCIDebug(I64 port_num) "\nHBA Ports Implemented: %b", hba->ports_implemented; "\nHBA Version: 0x%0X", hba->version; "\nHBA Ext Capabilities: %b", hba->caps_ext; - if (Bt(&hba->caps_ext, AHCI_CAPSEXTf_BOH)) + if (PCIBt(&hba->caps_ext, AHCI_CAPSEXTf_BOH)) "\n\tBIOS/OS Handoff supported."; - if (Bt(&hba->caps_ext, AHCI_CAPSEXTf_NVMP)) + if (PCIBt(&hba->caps_ext, AHCI_CAPSEXTf_NVMP)) "\n\tNVMHCI Supported (Non-Volatile Memory Host Controller Interface)"; "\nHBA BIOS/OS Handoff: %b", hba->bohc; - if (Bt(&hba->bohc, AHCI_BOHCf_BOS)) + if (PCIBt(&hba->bohc, AHCI_BOHCf_BOS)) "\n\tBIOS owns AHCI Controller"; - if (Bt(&hba->bohc, AHCI_BOHCf_BB)) + if (PCIBt(&hba->bohc, AHCI_BOHCf_BB)) "\n\tBIOS Busy"; "\n"; @@ -144,20 +151,20 @@ U0 AHCIPortCmdStop(I64 port_num) {//Stop command engine on port. CAHCIPort *port = &blkdev.ahci_hba->ports[port_num]; - Btr(&port->command, AHCI_PxCMDf_ST); - Btr(&port->command, AHCI_PxCMDf_FRE); + PCIBtr(&port->command, AHCI_PxCMDf_ST); + PCIBtr(&port->command, AHCI_PxCMDf_FRE); - while (Bt(&port->command, AHCI_PxCMDf_CR) || Bt(&port->command, AHCI_PxCMDf_FR)); + while (PCIBt(&port->command, AHCI_PxCMDf_CR) || PCIBt(&port->command, AHCI_PxCMDf_FR)); } U0 AHCIPortCmdStart(I64 port_num) {//Start command engine on port. CAHCIPort *port = &blkdev.ahci_hba->ports[port_num]; - while (Bt(&port->command, AHCI_PxCMDf_CR)); + while (PCIBt(&port->command, AHCI_PxCMDf_CR)); - Bts(&port->command, AHCI_PxCMDf_FRE); - Bts(&port->command, AHCI_PxCMDf_ST); + PCIBts(&port->command, AHCI_PxCMDf_FRE); + PCIBts(&port->command, AHCI_PxCMDf_ST); } Bool AHCIPortWait(I64 port_num, F64 timeout, Bool throwing=TRUE) @@ -224,10 +231,10 @@ U0 AHCIPortCmdWait(I64 port_num, I64 cmd_slot) while (TRUE) { - if (!Bt(&port->cmd_issue, cmd_slot)) //When command has been processed + if (!PCIBt(&port->cmd_issue, cmd_slot)) //When command has been processed break; - if (Bt(&port->interrupt_status, AHCI_PxIf_TFE)) //Task File Error ($LK,"ATAS_ERR",A="MN:ATAS_ERR"$) + if (PCIBt(&port->interrupt_status, AHCI_PxIf_TFE)) //Task File Error ($LK,"ATAS_ERR",A="MN:ATAS_ERR"$) { error: if (AHCI_DEBUG) @@ -243,7 +250,7 @@ error: Yield; // don't hang OS } - if (Bt(&port->interrupt_status, AHCI_PxIf_TFE)) //Second safety check + if (PCIBt(&port->interrupt_status, AHCI_PxIf_TFE)) //Second safety check goto error; } @@ -264,7 +271,7 @@ I64 AHCIAtapiCapacityGet(CBlkDev *bd) buf = CAlloc(8, sys_task->code_heap); - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -277,12 +284,12 @@ I64 AHCIAtapiCapacityGet(CBlkDev *bd) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; cmd_table->acmd[0] = ATAPI_READ_CAPACITY >> 8; AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -309,7 +316,7 @@ Bool AHCIAtapiSync(CBlkDev *bd) throw('AHCI'); } - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -317,12 +324,12 @@ Bool AHCIAtapiSync(CBlkDev *bd) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; cmd_table->acmd[0] = ATAPI_SYNC_CACHE >> 8; AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -350,7 +357,7 @@ Bool AHCIAtapiClose(CBlkDev *bd, I64 close_field=0x200, I64 track=0) throw('AHCI'); } - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -358,7 +365,7 @@ Bool AHCIAtapiClose(CBlkDev *bd, I64 close_field=0x200, I64 track=0) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; MemSet(&close_cmd, 0, sizeof(CAtapiCloseCmd)); @@ -368,7 +375,7 @@ Bool AHCIAtapiClose(CBlkDev *bd, I64 close_field=0x200, I64 track=0) MemCopy(&cmd_table->acmd, &close_cmd, sizeof(CAtapiCloseCmd)); AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -395,7 +402,7 @@ Bool AHCIAtapiBlank(CBlkDev *bd, Bool minimal=TRUE) throw('AHCI'); } - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -403,13 +410,13 @@ Bool AHCIAtapiBlank(CBlkDev *bd, Bool minimal=TRUE) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; cmd_table->acmd[0] = ATAPI_BLANK >> 8; cmd_table->acmd[1] = minimal; AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -445,7 +452,7 @@ Bool AHCIAtapiModeWriteSelect(CBlkDev *bd) mode_list->page.block_type = 8; // Mode 1: 2048-size blocks of data mode_list->page.packet_size = EndianU32(16);// Number of User Data Blocks per Fixed Packet. DVD media default: 16. - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -458,12 +465,12 @@ Bool AHCIAtapiModeWriteSelect(CBlkDev *bd) cmd_fis->type = FISt_H2D; cmd_fis->feature_low= 0x01; // Core Feature, 'mandatory' - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; cmd_table->acmd[0] = ATAPI_MODE_SELECT >> 8; AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -490,7 +497,7 @@ Bool AHCIAtapiStartStop(CBlkDev *bd, Bool start) throw('AHCI'); } - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -498,13 +505,13 @@ Bool AHCIAtapiStartStop(CBlkDev *bd, Bool start) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. cmd_fis->command = ATA_PACKET; cmd_table->acmd[0] = ATAPI_START_STOP_UNIT >> 8; cmd_table->acmd[4] = start; AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. try AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -566,7 +573,7 @@ U0 AHCIPortIdentify(CBlkDev *bd) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS. if (port->signature == AHCI_PxSIG_ATAPI) cmd_fis->command = ATA_IDENTIFY_PACKET; @@ -578,7 +585,7 @@ U0 AHCIPortIdentify(CBlkDev *bd) //Wait on previous command to complete. AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); //Issue the command. + PCIBts(&port->cmd_issue, cmd_slot); //Issue the command. AHCIPortCmdWait(bd->port_num, cmd_slot); Free(bd->dev_id_record); @@ -608,14 +615,14 @@ U8 *AHCIBufferAlign(CBlkDev *bd, U8 *user_buf, I64 buf_size, Bool write) Free(bd->prd_buf); bd->prd_buf = MAlloc(buf_size, sys_task->code_heap); - Bts(&bd->flags, BDf_INTERNAL_BUF); + PCIBts(&bd->flags, BDf_INTERNAL_BUF); if (write) MemCopy(bd->prd_buf, user_buf, buf_size); return bd->prd_buf; } - Btr(&bd->flags, BDF_INTERNAL_BUF); + PCIBtr(&bd->flags, BDF_INTERNAL_BUF); return user_buf; } @@ -650,16 +657,11 @@ I64 AHCIAtaBlksRW(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool write) buf_size = buf_size_tmp = count * BLK_SIZE; prdt_len = (buf_size - 1) / AHCI_PRD_MAX_BYTES + 1; -// "PRDT Length:\t%d\n", prdt_len; -// "Count:\t\t\t%d\n", count; -// "Buffer size:\t%X\n", buf_size; - cmd_header->prdt_len = prdt_len; //Set PRD table length in cmd header. //Set 'write' bit depending on 'write' argument. BEqual(&cmd_header->desc, AHCI_CH_DESCf_W, write); internal_buf = internal_buf_tmp = AHCIBufferAlign(bd, buf, buf_size, write); -// "Buffer:\t\t\t0x%X\n", internal_buf; if (!internal_buf) throw('AHCI'); //Will probably never happen. @@ -675,9 +677,6 @@ I64 AHCIAtaBlksRW(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool write) else byte_count = buf_size_tmp; -// "prdt[%d].data_base_addr = 0x%X\n" , i, internal_buf_tmp; -// "prdt[%d].data_byte_count = 0x%X\n\n", i, byte_count; - cmd_table->prdt[i].data_base = internal_buf_tmp; cmd_table->prdt[i].data_byte_count = byte_count - 1; //Zero-based value buf_size_tmp -= byte_count; @@ -687,7 +686,7 @@ I64 AHCIAtaBlksRW(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool write) cmd_fis = cmd_table->cmd_fis; cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS if (write) //Assumed support for LBA48. cmd_fis->command = ATA_WRITE_DMA_EXT; @@ -707,7 +706,7 @@ I64 AHCIAtaBlksRW(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool write) //Wait on previous command to complete. AHCIPortWait(bd->port_num, tS + 2); //Issue the command. - Bts(&port->cmd_issue, cmd_slot); + PCIBts(&port->cmd_issue, cmd_slot); //Wait on command to finish. AHCIPortCmdWait(bd->port_num, cmd_slot); @@ -725,27 +724,23 @@ I64 AHCIAtaBlksRW(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool write) } I64 AHCIAtaBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count) -{//Read 'blk' amount of blocks from AHCI disk device. Returns num of bytes transferred between disk and memory. +{//Read 'count' amount of blocks from block 'blk' in AHCI disk device. Returns num of bytes transferred between disk and memory. I64 byte_count = 0; if (!count) return 0; if (count <= AHCI_PRDT_MAX_BLOCKS) { -// "$$GREEN$$READ less than MAX_BLOCKS$$FG$$\n"; return AHCIAtaBlksRW(bd, buf, blk, count, FALSE); } else { -// "$$GREEN$$READ greater than MAX_BLOCKS\n"; -// "read count: %d\n$$FG$$", count; while (count > AHCI_PRDT_MAX_BLOCKS) { byte_count += AHCIAtaBlksRW(bd, buf, blk, AHCI_PRDT_MAX_BLOCKS, FALSE); count -= AHCI_PRDT_MAX_BLOCKS; blk += AHCI_PRDT_MAX_BLOCKS; buf += AHCI_PRDT_MAX_BLOCKS * BLK_SIZE; -// "$$GREEN$$read count: %d\n$$FG$$", count; - }$ER$ + } byte_count += AHCIAtaBlksRW(bd, buf, blk, count, FALSE); } @@ -755,27 +750,23 @@ I64 AHCIAtaBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count) } I64 AHCIAtaBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count) -{//Write 'blk' amount of blocks to AHCI disk device. Returns num of bytes transferred between memory and disk. +{//Write 'count' amount of blocks from block 'blk' in AHCI disk device. Returns num of bytes transferred between memory and disk. I64 byte_count = 0; if (!count) return 0; if (count <= AHCI_PRDT_MAX_BLOCKS) { -// "$$GREEN$$WRITE less than MAX_BLOCKS$$FG$$\n"; return AHCIAtaBlksRW(bd, buf, blk, count, TRUE); } else { -// "$$GREEN$$WRITE greater than MAX_BLOCKS\n"; -// "write count: %d$$FG$$\n", count; while (count > AHCI_PRDT_MAX_BLOCKS) { byte_count += AHCIAtaBlksRW(bd, buf, blk, AHCI_PRDT_MAX_BLOCKS, TRUE); count -= AHCI_PRDT_MAX_BLOCKS; blk += AHCI_PRDT_MAX_BLOCKS; buf += AHCI_PRDT_MAX_BLOCKS * BLK_SIZE; -// "$$GREEN$$write count: %d\n$$FG$$\n", count; } byte_count += AHCIAtaBlksRW(bd, buf, blk, count, TRUE); } @@ -784,7 +775,7 @@ I64 AHCIAtaBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count) } I64 AHCIAtapiBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) -{//Read 'blk' amount of blocks from from AHCI ATAPI device. Returns num of bytes transferred. +{//Read 'count' amount of blocks from block 'blk' in AHCI ATAPI device. Returns num of bytes transferred. CPortCmdTable *cmd_table; CFisH2D *cmd_fis; CAHCIPort *port = bd->ahci_port; @@ -808,18 +799,13 @@ I64 AHCIAtapiBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) buf_size = buf_size_tmp = count * DVD_BLK_SIZE; prdt_len = (buf_size - 1) / AHCI_PRD_MAX_BYTES + 1; -// "PRDT Length:\t%d\n", prdt_len; -// "Count:\t\t\t%d\n", count; -// "Buffer size:\t%X\n", buf_size; - cmd_header->prdt_len = prdt_len; internal_buf = internal_buf_tmp = AHCIBufferAlign(bd, buf, buf_size, FALSE); -// "Buffer:\t\t\t0x%X\n", internal_buf; if (!internal_buf) throw('AHCI'); - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); //Set ATAPI flag in command header + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); //Set ATAPI flag in command header cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -831,8 +817,6 @@ I64 AHCIAtapiBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) else byte_count = buf_size_tmp; -// "prdt[%d].data_base_addr = 0x%X\n" , i, internal_buf_tmp; -// "prdt[%d].data_byte_count = 0x%X\n\n", i, byte_count; cmd_table->prdt[i].data_base = internal_buf_tmp; cmd_table->prdt[i].data_byte_count = byte_count - 1; //Zero-based value @@ -844,7 +828,7 @@ I64 AHCIAtapiBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) MemSet(cmd_fis, 0, sizeof(CFisH2D)); cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS cmd_fis->feature_low = 1; //Necessary? cmd_fis->command = ATA_PACKET; @@ -859,7 +843,7 @@ I64 AHCIAtapiBlksRead(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); + PCIBts(&port->cmd_issue, cmd_slot); AHCIPortCmdWait(bd->port_num, cmd_slot); if (bd->flags & BDF_INTERNAL_BUF) @@ -908,8 +892,8 @@ I64 AHCIAtapiBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) if (!internal_buf) throw('AHCI'); - Bts(&cmd_header->desc, AHCI_CH_DESCf_A); //Set ATAPI flag in command header - Bts(&cmd_header->desc, AHCI_CH_DESCf_W); //Set WRITE flag in command header + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_A); //Set ATAPI flag in command header + PCIBts(&cmd_header->desc, AHCI_CH_DESCf_W); //Set WRITE flag in command header cmd_table = cmd_header->cmd_table_base; MemSet(cmd_table, 0, sizeof(CPortCmdTable)); @@ -931,7 +915,7 @@ I64 AHCIAtapiBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) MemSet(cmd_fis, 0, sizeof(CFisH2D)); cmd_fis->type = FISt_H2D; - Bts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS + PCIBts(&cmd_fis->desc, AHCI_CF_DESCf_C); //Set Command bit in H2D FIS cmd_fis->command = ATA_PACKET; @@ -944,7 +928,7 @@ I64 AHCIAtapiBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) AHCIPortWait(bd->port_num, tS + 2); - Bts(&port->cmd_issue, cmd_slot); + PCIBts(&port->cmd_issue, cmd_slot); AHCIPortCmdWait(bd->port_num, cmd_slot); if (bd->flags & BDF_INTERNAL_BUF) @@ -961,8 +945,9 @@ I64 AHCIAtapiBlksWrite(CBlkDev *bd, U8 *buf, I64 blk, I64 count, Bool lock=TRUE) U0 AHCIPortInit(CBlkDev *bd, CAHCIPort *port, I64 port_num) {//Initialize base addresses for command list and FIS receive area and start command execution on port. - CPortCmdHeader *cmd_header; - I64 i; + CPortCmdHeader *cmd_header, + *cmd_header_base; + I64 i; if (!(port->signature == AHCI_PxSIG_ATAPI || port->signature == AHCI_PxSIG_ATA)) Debug("AHCI Port/BlkDev error: Invalid Port Signature"); @@ -992,9 +977,12 @@ U0 AHCIPortInit(CBlkDev *bd, CAHCIPort *port, I64 port_num) port->fis_base = CAllocAligned(sizeof(CFisReceived), 256, sys_task->code_heap); port->fis_base_upper = 0; + + cmd_header_base = port->cmd_list_base; for (i = 0; i < blkdev.cmd_slot_count; i++) { - cmd_header = &port->cmd_list_base(CPortCmdHeader *)[i]; +// cmd_header = &port->cmd_list_base(CPortCmdHeader *)[i]; + cmd_header = &cmd_header_base[i]; //Write Command FIS Length (CFL, a fixed size) in bits 4:0 of the desc. Takes size in U32s. cmd_header->desc = sizeof(CFisH2D) / sizeof(U32); @@ -1009,7 +997,7 @@ U0 AHCIPortInit(CBlkDev *bd, CAHCIPort *port, I64 port_num) Bool AHCIAtaInit(CBlkDev *bd) { Bool unlock, okay = FALSE; - CPortCmdHeader *cmd_header; + CPortCmdHeader *cmd_header, *cmd_header_base; I64 i; if (!bd->ahci_port) @@ -1022,7 +1010,9 @@ Bool AHCIAtaInit(CBlkDev *bd) { for (i = 0; i < blkdev.cmd_slot_count; i++) { - cmd_header = &bd->ahci_port->cmd_list_base(CPortCmdHeader *)[i]; + cmd_header_base = bd->ahci_port->cmd_list_base; +// cmd_header = &bd->ahci_port->cmd_list_base(CPortCmdHeader *)[i]; + cmd_header = &cmd_header_base[i]; Free(cmd_header->cmd_table_base); } Free(bd->ahci_port->cmd_list_base); @@ -1054,9 +1044,9 @@ Bool AHCIAtaInit(CBlkDev *bd) U0 AHCIHbaReset() { - Bts(&blkdev.ahci_hba->ghc, AHCI_GHCf_HBA_RESET); - while (Bt(&blkdev.ahci_hba->ghc, AHCI_GHCf_HBA_RESET)); - Bts(&blkdev.ahci_hba->ghc, AHCI_GHCf_AHCI_ENABLE); + PCIBts(&blkdev.ahci_hba->ghc, AHCI_GHCf_HBA_RESET); + while (PCIBt(&blkdev.ahci_hba->ghc, AHCI_GHCf_HBA_RESET)); + PCIBts(&blkdev.ahci_hba->ghc, AHCI_GHCf_AHCI_ENABLE); } U0 AHCIInit() @@ -1080,19 +1070,19 @@ U0 AHCIInit() blkdev.ahci_hba = hba; - Bts(&blkdev.ahci_hba->ghc, AHCI_GHCf_AHCI_ENABLE); + PCIBts(&blkdev.ahci_hba->ghc, AHCI_GHCf_AHCI_ENABLE); "AHCI: GHC.AE set\n"; //Transferring ownership from BIOS if supported. - if (Bt(&hba->caps_ext, AHCI_CAPSEXTf_BOH)) + if (PCIBt(&hba->caps_ext, AHCI_CAPSEXTf_BOH)) { - Bts(&hba->bohc, AHCI_BOHCf_OOS); + PCIBts(&hba->bohc, AHCI_BOHCf_OOS); "AHCI: Transferring ownership from BIOS\n"; - while (Bt(&hba->bohc, AHCI_BOHCf_BOS)); + while (PCIBt(&hba->bohc, AHCI_BOHCf_BOS)); Sleep(25); - if (Bt(&hba->bohc, AHCI_BOHCf_BB)) //if Bios Busy is still set after 25 mS, wait 2 seconds. + if (PCIBt(&hba->bohc, AHCI_BOHCf_BB)) //if Bios Busy is still set after 25 mS, wait 2 seconds. Sleep(2000); } @@ -1101,7 +1091,7 @@ U0 AHCIInit() for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&hba->ports_implemented, i)) + if (PCIBt(&hba->ports_implemented, i)) {//$BK,1$Make ports idle?$BK,0$ port = &hba->ports[i]; "AHCI: Port %2d signature 0x%08X ", i, port->signature; @@ -1109,7 +1099,7 @@ U0 AHCIInit() { if (port->signature == AHCI_PxSIG_ATAPI) { - Bts(&port->command, AHCI_PxCMDf_ATAPI); + PCIBts(&port->command, AHCI_PxCMDf_ATAPI); "ATAPI drive\n"; } else if (port->signature == AHCI_PxSIG_ATA) @@ -1139,7 +1129,7 @@ Bool AHCIBootDVDProbeAll(CBlkDev *bd) for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; "AHCI: BootDVDProbeAll: Saw port at %2d with signature 0x%0X\n", i, port->signature; @@ -1163,7 +1153,17 @@ Bool AHCIBootDVDProbeAll(CBlkDev *bd) return TRUE; } else - "AHCI: Did not find matching sys_compile_time on Port %d\n", i; + "AHCI: Did not find matching sys_compile_time at BLK %d on Port %d\n", sys_boot_blk, i; + + AHCIAtapiBlksRead(bd, buf, 0, 1, FALSE); + + if (!MemCompare(buf + 568, sys_disk_uuid, 16)) + { + "AHCI: Found sys_disk_uuid at BLK 0 byte 568 on Port %d\n", i; + "______________________\n"; + return TRUE; + } + } catch { diff --git a/src/Kernel/BlkDev/DiskATAId.ZC b/src/Kernel/BlkDev/DiskATAId.ZC index 27b86762..84044438 100755 --- a/src/Kernel/BlkDev/DiskATAId.ZC +++ b/src/Kernel/BlkDev/DiskATAId.ZC @@ -29,7 +29,7 @@ I64 MountAHCIAuto() // if boot-drive blkdev exists, do a SATA port iteration to mount it first "( ':' BlkDev at 0x%0X )\n", bd; for (i = 0; i < AHCI_MAX_PORTS; i++) - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; @@ -55,7 +55,7 @@ I64 MountAHCIAuto() // do a 2nd iteration to mount remaining drives // (we will end up trying to boot off whichever drive/partition ends up at chosen letter) for (i = 0; i < AHCI_MAX_PORTS; i++) - if (i != ata_port && i != atapi_port && Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (i != ata_port && i != atapi_port && PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; diff --git a/src/Kernel/BlkDev/DiskCDDVD.ZC b/src/Kernel/BlkDev/DiskCDDVD.ZC index 27f10939..5cc1020c 100755 --- a/src/Kernel/BlkDev/DiskCDDVD.ZC +++ b/src/Kernel/BlkDev/DiskCDDVD.ZC @@ -27,7 +27,8 @@ Bool ISOInit(CDrive *drive, I64 blk) case ISOT_BOOT_RECORD: drv_offset += (2 * DVD_BLK_SIZE + DVD_BLK_SIZE) / BLK_SIZE; break; - +// TODO FIXME: ISOT_PRI_VOL_DESC isn't currently implemented, meaning only ISO9660 ISOs with Joliet filesystem are supported ! +// case ISOT_PRI_VOL_DESC: case ISOT_SUPPLEMENTARY_DESC: de = &iso->root_dir_record; drive->size = iso->vol_space_size.little * bd->blk_size >> BLK_SIZE_BITS; diff --git a/src/Kernel/BlkDev/DiskClus.ZC b/src/Kernel/BlkDev/DiskClus.ZC index d24b9c9f..48cc4d64 100755 --- a/src/Kernel/BlkDev/DiskClus.ZC +++ b/src/Kernel/BlkDev/DiskClus.ZC @@ -106,7 +106,7 @@ I64 ClusBlkRead(CDrive *drive, U8 *buf, I64 c, I64 blks) I64 ClusRead(CDrive *drive, U8 *buf, I64 c, I64 count) {//Read cluster count from drive to buf. - return ClusBlkRead(drive, buf, c, count*drive->spc); + return ClusBlkRead(drive, buf, c, count * drive->spc); } I64 ClusBlkWrite(CDrive *drive, U8 *buf, I64 c, I64 blks) diff --git a/src/Kernel/BlkDev/DiskCopy.ZC b/src/Kernel/BlkDev/DiskCopy.ZC index 87ce38f6..fb029da5 100755 --- a/src/Kernel/BlkDev/DiskCopy.ZC +++ b/src/Kernel/BlkDev/DiskCopy.ZC @@ -29,7 +29,7 @@ Bool CopySingleZ(U8 *f1, U8 *f2) //Just one file Bool CopySingle(U8 *f1, U8 *f2) //Just one file { U8 *absf1 = FileNameAbs(f1), *absf2 = FileNameAbs(f2), *buf; - I64 count, n, size, attr1 = FileAttr(f1), attr2 = FileAttr(f2), i, j; + I64 count, n, size, attr1 = FileAttr(f1), attr2 = FileAttr(f2), i, j, time = counts.jiffies; CFile *in_file = NULL, *out_file = NULL; if (!StrCompare(absf1, absf2)) @@ -57,7 +57,7 @@ Bool CopySingle(U8 *f1, U8 *f2) //Just one file out_file = FOpen(f2, "w", count); if (out_file) { - "Copying %s to %s\n", f1, f2; + "Copying %s to %s", f1, f2; j = size; while (count > 0) { @@ -65,6 +65,11 @@ Bool CopySingle(U8 *f1, U8 *f2) //Just one file { n = COPY_BUF_BLKS; i = n << BLK_SIZE_BITS; + if (counts.jiffies > time + 2000) + { + "\n [ %0.2f%% ]", 100 * ToF64(size - j) / size; + time = counts.jiffies; + } } else { @@ -76,6 +81,7 @@ Bool CopySingle(U8 *f1, U8 *f2) //Just one file count -= n; j -= n << BLK_SIZE_BITS; } + "\n"; out_file->flags |= FF_USE_OLD_DATETIME; out_file->de.datetime = in_file->de.datetime; out_file->de.size = size; diff --git a/src/Kernel/BlkDev/FileSysFAT.ZC b/src/Kernel/BlkDev/FileSysFAT.ZC index 07258f1b..0036c265 100755 --- a/src/Kernel/BlkDev/FileSysFAT.ZC +++ b/src/Kernel/BlkDev/FileSysFAT.ZC @@ -1045,8 +1045,7 @@ Bool FAT32MkDir(CDrive *drive, U8 *cur_dir, U8 *name, I64 entry_count) { I64 c, cur_dir_clus = Name2DirClus(drive, cur_dir), //Rough estimate of size - size = CeilU64((entry_count + 2) << FAT32_ENTRIES_BITS, - drive->spc << BLK_SIZE_BITS); + size = CeilU64((entry_count + 2) << FAT32_ENTRIES_BITS, drive->spc << BLK_SIZE_BITS); U8 *buf = CAlloc(size); CDirEntry d_native; CFAT32DirEntry *dFAT = buf; diff --git a/src/Kernel/BlkDev/FileSysISO.ZC b/src/Kernel/BlkDev/FileSysISO.ZC index c69b0cbd..ba0996f5 100755 --- a/src/Kernel/BlkDev/FileSysISO.ZC +++ b/src/Kernel/BlkDev/FileSysISO.ZC @@ -176,7 +176,8 @@ U8 *ISOFileRead(CDrive *drive, U8 *cur_dir, U8 *filename, I64 *_size, I64 *_attr buf = MAlloc(blk_cnt << BLK_SIZE_BITS + 1); c = de.clus; c = ClusBlkRead(drive, buf, c, blk_cnt); - buf[de.size] = 0; //Terminate *_size = de.size; + buf[de.size] = 0; //Terminate + *_size = de.size; *_attr = FileAttr(de.name, de.attr); } DriveUnlock(drive); diff --git a/src/Kernel/Display.ZC b/src/Kernel/Display.ZC index 0d41dc83..f8cadcb9 100755 --- a/src/Kernel/Display.ZC +++ b/src/Kernel/Display.ZC @@ -60,17 +60,17 @@ See also $LK,"GrUpdateScreen",A="MN:GrUpdateScreen"$(). {//Scroll screen down MemCopy(text.fb_alias, - text.fb_alias + sys_vbe_mode.width * FONT_HEIGHT, - (text.screen_size - sys_vbe_mode.width * FONT_HEIGHT) * sizeof(U32)); + text.fb_alias + sys_framebuffer_width * FONT_HEIGHT, + (text.screen_size - sys_framebuffer_width * FONT_HEIGHT) * sizeof(U32)); - MemSetU32(text.fb_alias + text.screen_size - sys_vbe_mode.width * FONT_HEIGHT, BLACK32, sys_vbe_mode.width * FONT_HEIGHT); + MemSetU32(text.fb_alias + text.screen_size - sys_framebuffer_width * FONT_HEIGHT, BLACK32, sys_framebuffer_width * FONT_HEIGHT); text.raw_col -= text.cols ; row = text.rows - 1; } x = col * FONT_WIDTH; y = row * FONT_HEIGHT; ch_bitmap = text.font[ch & 0xFF]; - framebuffer = text.fb_alias + sys_vbe_mode.width * y + x; + framebuffer = text.fb_alias + sys_framebuffer_width * y + x; PUSHFD CLI @@ -81,7 +81,7 @@ See also $LK,"GrUpdateScreen",A="MN:GrUpdateScreen"$(). else *framebuffer++ = BLACK32; if (i & (FONT_WIDTH - 1) == FONT_WIDTH - 1) - framebuffer += sys_vbe_mode.width - FONT_WIDTH; + framebuffer += sys_framebuffer_width - FONT_WIDTH; ch_bitmap >>= 1; } POPFD diff --git a/src/Kernel/FontAux.ZC b/src/Kernel/FontAux.ZC new file mode 100755 index 00000000..5f947cc6 --- /dev/null +++ b/src/Kernel/FontAux.ZC @@ -0,0 +1,258 @@ +public U64 sys_font_aux[256] = { +0x0000000000000000, +0x0000000000000000, +0x000000FF00000000, +0x000000FF00FF0000, +0x1818181818181818, +0x6C6C6C6C6C6C6C6C, +0x181818F800000000, +0x6C6C6CEC0CFC0000, +0x1818181F00000000, +0x6C6C6C6F607F0000, +0x000000F818181818, +0x000000FC0CEC6C6C, +0x0000001F18181818, +0x0000007F606F6C6C, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0000000000000000, +0x0008000000000000,// +0x0000000000000000,// +0x000C000C0C1E1E0C,//! +0x0000000012243636,//" +0x0036367F367F3636,//# +0x00083F683E0B7E08,//$$ +0x0023562C18326542,//% +0x006E333B6E1C361C,//& +0x0000000004080C0C,//' +0x00180C0606060C18,//( +0x00060C1818180C06,//) +0x0000361C7F1C3600,//* +0x000008083E080800,//+ +0x04080C0C00000000,//, +0x000000007E000000,//- +0x000C0C0000000000,//. +0x000103060C183020,/// +0x003E67636363733E,//0 +0x007E18181818181C,//1 +0x007F03061C30633E,//2 +0x003E63603C60633E,//3 +0x0060607F63666C78,//4 +0x003E6360603F037F,//5 +0x003E63633F03633E,//6 +0x0003060C1830637F,//7 +0x003E63633E63633E,//8 +0x003E63607E63633E,//9 +0x000C0C00000C0C00,//: +0x0004080C000C0C00,//; +0x0030180C060C1830,//< +0x0000003E003E0000,//= +0x00060C1830180C06,//> +0x000C000C3C60633E,//? +0x007E037B6B7B633E,//@ +0x0063637F6363361C,//A +0x003F63633F63633F,//B +0x003E63030303633E,//C +0x001F33636363331F,//D +0x007F03031F03037F,//E +0x000303031F03037F,//F +0x007E63637B03037E,//G +0x006363637F636363,//H +0x007E18181818187E,//I +0x003E636360606078,//J +0x0063331B0F1B3363,//K +0x007F030303030303,//L +0x006363636B7F7763,//M +0x006363737B6F6763,//N +0x003E63636363633E,//O +0x000303033F63633F,//P +0x005E337B6B63633E,//Q +0x0063331B3F63633F,//R +0x003E63603E03633E,//S +0x001818181818187E,//T +0x003E636363636363,//U +0x00081C3663636363,//V +0x006363777F6B6363,//W +0x0063773E1C3E7763,//X +0x001818183C666666,//Y +0x007F070E1C38707F,//Z +0x001E06060606061E,//[ +0x00406030180C0602,//\ +0x001E18181818181E,//] +0x0000000063361C08,//^ +0x00FF000000000000,//_ +0x000000000030180C,//` +0x007E637E603E0000,//a +0x003F6363633F0303,//b +0x003E6303633E0000,//c +0x007E6363637E6060,//d +0x003E037F633E0000,//e +0x000C0C0C7F0C0C78,//f +0x3E607E63637E0000,//g +0x00636363633F0303,//h +0x007E18181C001818,//i +0x003E636060600060,//j +0x0063331F33630303,//k +0x0030181818181818,//l +0x006B6B6B6B3F0000,//m +0x00636363633F0000,//n +0x003E6363633E0000,//o +0x03033F63633F0000,//p +0x60607E63637E0000,//q +0x00030303673B0000,//r +0x003F607F037E0000,//s +0x00181818187E1818,//t +0x003E636363630000,//u +0x00081C3663630000,//v +0x00367F6B6B630000,//w +0x00773E1C3E770000,//x +0x070C1C3663630000,//y +0x007F0E1C387F0000,//z +0x007018180C181870,//{ +0x0018181818181818,//| +0x00070C0C180C0C07,//} +0x0000003B6B6E0000,//~ +0xFFFFFFFFFFFFFFFF, +0x0004083E6303633E,//€ +0x003E636363003600,// +0x003E037F633E0810,//‚ +0x007E637E603E1408,//ƒ +0x007E637E603E0036,//„ +0x007E637E603E0804,//… +0x007E637E603E0C0C,//† +0x0004083E03033E00,//‡ +0x003E037F633E1408,//ˆ +0x003E037F633E0036,//‰ +0x003E037F633E0804,//Š +0x007E18181C003636,//‹ +0x007E18181C001408,//Œ +0x007E18181C000804,// +0x00637F63361C0036,//Ž +0x00637F63361C141C,// +0x007F031F037F0810,// +0x007E197E583E0000,//‘ +0x007B1B1F7B1B1E7C,//’ +0x003E63633E001408,//“ +0x003E63633E000036,//” +0x003E63633E000804,//• +0x003E636363001408,//– +0x003E636363000804,//— +0x0F0C1C3663630063,//˜ +0x003E6363633E0036,//™ +0x003E636363630036,//š +0x00083E6B0B6B3E08,//› +0x007F06061F46663C,//œ +0x00083E083E1C3663,// +0x70337B332F1B1B0F,//ž +0x0E1B18187E18D870,//Ÿ +0x007E637E603E0810,//  +0x007E18181C000810,//¡ +0x003E63633E000810,//¢ +0x003E636363000810,//£ +0x00636363633F1428,//¤ +0x0063736B67631428,//¥ +0x007E007E637E603E,//¦ +0x00007E003C66663C,//§ +0x003E63031E180018,//¨ +0x00000C06FF060C00,//© +0x000030303F000000,//ª +0x0070117244750911,//« +0x0040417A54654911,//¬ +0x00183C3C18180018,//­ +0x00006C361B366C00,//® +0x00001B366C361B00,//¯ +0x1144114411441144,//° +0x55AA55AA55AA55AA,//± +0xEEBBEEBBEEBBEEBB,//² +0x0808080808080808,//³ +0x080808080F080808,//´ +0x0808080F0F0F0808,//µ +0x3C3C3C3C3F3C3C3C,//¶ +0x3C3C3C3C3F000000,//· +0x0808080F0F0F0000,//¸ +0x3C3C3C3F3F3F3C3C,//¹ +0x3C3C3C3C3C3C3C3C,//º +0x3C3C3E3F1F0F0000,//» +0x0000000F1F3F3E3C,//¼ +0x000000003F3C3C3C,//½ +0x0000000F0F0F0808,//¾ +0x0808080807000000,//¿ +0x00000000F0080808,//À +0x00000000FF080808,//Á +0x08080808FF000000,// +0x08080808F8080808,//à +0x00000000FF000000,//Ä +0x08080808FF080808,//Å +0x080808F8F8F80808,//Æ +0x3C3C3C3CFC3C3C3C,//Ç +0x000000F0F8FC7C3C,//È +0x3C3C7CFCF8F00000,//É +0x000000FFFFFF3C3C,//Ê +0x3C3C3CFFFFFF0000,//Ë +0x3C3C3CFCFCFC3C3C,//Ì +0x000000FFFFFF0000,//Í +0x3C3C3CFFFFFF3C3C,//Î +0x000000FFFFFF0808,//Ï +0x00000000FF3C3C3C,//Ð +0x080808FFFFFF0000,//Ñ +0x3C3C3C3CFF000000,//Ò +0x00000000FC3C3C3C,//Ó +0x000000F8F8F80808,//Ô +0x080808F8F8F80000,//Õ +0x3C3C3C3CFC000000,//Ö +0x3C3C3C3CFF3C3C3C,//× +0x080808FFFFFF0808,//Ø +0x0000000007080808,//Ù +0x08080808F0000000,//Ú +0xFFFFFFFFFFFFFFFF,//Û +0xFFFFFFFF00000000,//Ü +0x0F0F0F0F0F0F0F0F,//Ý +0xF0F0F0F0F0F0F0F0,//Þ +0x00000000FFFFFFFF,//ß +0x005E6363635E0000,//à +0x00037F63633B633E,//á +0x000303030303037F,//â +0x00363636367F0000,//ã +0x007F060C180C067F,//ä +0x001E3333337E0000,//å +0x00031F3333330000,//æ +0x001818181A7C0000,//ç +0x00083E6B6B6B3E08,//è +0x00003E637F633E00,//é +0x007736636363633E,//ê +0x003E63633E0C067F,//ë +0x0000364949360000,//ì +0x0002043E493E1020,//í +0x003E630E633E0000,//î +0x006363636363361C,//ï +0x00003E003E003E00,//ð +0x003E0008083E0808,//ñ +0x003E000C1830180C,//ò +0x003E00180C060C18,//ó +0x1818181818D8D870,//ô +0x0E1B1B1818181818,//õ +0x0008003E00080000,//ö +0x003B6B6E003B6B6E,//÷ +0x000000001C36361C,//ø +0x0000001818000000,//ù +0x0000001800000000,//ú +0x001C1E1B18181878,//û +0x000000001B1B1B0F,//ü +0x0000003F061C331E,//ý +0x00003C3C3C3C0000,//þ +0xFFFFFFFFFFFFFFFF,//ÿ +}; \ No newline at end of file diff --git a/src/Kernel/KConfig.ZC b/src/Kernel/KConfig.ZC index 1623536a..1aae05b3 100755 --- a/src/Kernel/KConfig.ZC +++ b/src/Kernel/KConfig.ZC @@ -26,7 +26,6 @@ class CKConfig CDoc *add_dev; U8 *debug_distro_file, *debug_distro_start; U8 *home_dir; - U16 screen_width, screen_height; Bool opts[CONFIG_OPTIONS_NUM]; U8 mem_init_val, heap_init_val, var_init_val, boot_drive_let, mount_ide_auto_hd_let, mount_ide_auto_cd_let; }; @@ -168,27 +167,11 @@ U0 KConfigOptions(CKConfig *c) CKConfig *KConfigNew() { - I64 resolution_num; CKConfig *c = CAlloc(sizeof(CKConfig)); c->add_dev = KConfigAddDev(c); c->home_dir = StrNew("::/Home"); - - VideoRep(FALSE); - resolution_num = I64Get("Enter list number of desired resolution, " - "or desired width. ($$PURPLE$$$$FG$$ for auto maximum): ",, 1); - if (resolution_num <= VBE_MODES_NUM) - { - c->screen_width = sys_vbe_modes[resolution_num - 1].width; - c->screen_height = sys_vbe_modes[resolution_num - 1].height; - } - else - { - c->screen_width = resolution_num; - c->screen_height = I64Get("Enter Height: ",, 0); - } - c->disk_cache_size_exp = StrGet("\nDisk Cache Size in Bytes, gets rounded-up funny, " "($$PURPLE$$$$FG$$ will use default.):", "Scale2Mem(0x80000,0x8000000)"); diff --git a/src/Kernel/KDebug.ZC b/src/Kernel/KDebug.ZC index 7b5734b9..4f08387c 100755 --- a/src/Kernel/KDebug.ZC +++ b/src/Kernel/KDebug.ZC @@ -1,17 +1,21 @@ Bool CheckPtr(U8 *ptr) {//Check if address is valid pointer. + CZXE *zxe = mem_boot_base - sizeof(CZXE); + if (mem_heap_base <= ptr <= mem_mapped_space) return *MemPageTable(ptr) & 1; else - return mem_boot_base < ptr < VGAM_GRAPHICS; + return mem_boot_base < ptr < mem_boot_base + zxe->file_size - 1 - sizeof(CZXE); } Bool CheckCodePtr(U8 *ptr) {//Check if address is valid code address. + CZXE *zxe = mem_boot_base - sizeof(CZXE); + if (mem_heap_base <= ptr <= mem_heap_limit) return *MemPageTable(ptr) & 1; else - return mem_boot_base < ptr < VGAM_GRAPHICS; + return mem_boot_base < ptr < mem_boot_base + zxe->file_size - 1 - sizeof(CZXE); } Bool CheckOnStack(U8 *ptr, CTask *task=NULL) diff --git a/src/Kernel/KGlobals.ZC b/src/Kernel/KGlobals.ZC index c2c1a950..17c3558d 100755 --- a/src/Kernel/KGlobals.ZC +++ b/src/Kernel/KGlobals.ZC @@ -13,7 +13,7 @@ CTask *sys_winmgr_task, U8 *rev_bits_table; //Table with U8 bits reversed CDate local_time_offset; F64 *pow10_I64, - sys_os_version = 1.13; + sys_os_version = 2.00; CAutoCompleteDictGlobals acd; CAutoCompleteGlobals ac; diff --git a/src/Kernel/KMain.ZC b/src/Kernel/KMain.ZC index b08a70a0..771ae09c 100755 --- a/src/Kernel/KMain.ZC +++ b/src/Kernel/KMain.ZC @@ -64,33 +64,18 @@ U0 SysGlobalsInit() QueueInit(&dev.pci_head); dev.mem64_ptr = mem_mapped_space; - if (sys_boot_src.u8[0] != BOOT_SRC_RAM) - {//framebuffer pointer is already linear - Seg2Linear(&sys_vbe_info.video_modes); - Seg2Linear(&sys_vbe_info.oem); - Seg2Linear(&sys_vbe_info.vendor); - Seg2Linear(&sys_vbe_info.product_name); - Seg2Linear(&sys_vbe_info.product_revision); - Seg2Linear(SYS_FONT_PTR); - sys_vbe_info.software_revision = Bcd2Binary(sys_vbe_info.software_revision); - } - debug.fun_seg_cache = CAlloc(FUN_SEG_CACHE_SIZE * sizeof(CFunSegCache)); debug.int_fault_code = IntFaultHandlersNew; } U0 SysGrInit() { - I64 i, j; - text.aux_font = MAlloc(256 * 8); //256 U64s - MemCopy(text.aux_font, *SYS_FONT_PTR(U32), 256 * 8); - - for (i = 0; i < 256; i++) - for (j = 0; j < 8; j++) - text.aux_font[i].u8[j] = rev_bits_table[text.aux_font[i].u8[j]]; + I64 i; text.font = sys_font_std; + text.aux_font = sys_font_aux; + //patch some chars text.aux_font[10] = text.font[10]; //"Return" symbol text.aux_font[255] = text.font[255]; //Block symbol ÿ @@ -103,16 +88,15 @@ U0 SysGrInit() text.border_chars[2] (I64) = 'ÄͳºÚÉ¿»'; text.border_chars[10](U32) = 'ÀÈÙ¼'; - text.cols = sys_vbe_mode.width / FONT_WIDTH; - text.rows = sys_vbe_mode.height / FONT_HEIGHT; + text.cols = sys_framebuffer_width / FONT_WIDTH; + text.rows = sys_framebuffer_height / FONT_HEIGHT; - text.screen_size = sys_vbe_mode.width * sys_vbe_mode.height; + text.screen_size = sys_framebuffer_width * sys_framebuffer_height; text.buffer_size = text.screen_size * 4; //buffer for 32-bit, but only 16 colors now. text.raw_screen = CAlloc(text.buffer_size); - text.fb_alias = sys_vbe_mode.framebuffer; + text.fb_alias = sys_framebuffer_addr; MemSetU32(text.fb_alias, BLACK32, text.screen_size); - text.vga_alias = CAlloc(text.rows * text.cols * 8); } U0 TimerInit() diff --git a/src/Kernel/KStart16.ZC b/src/Kernel/KStart16.ZC index 32b47e61..5729bd18 100755 --- a/src/Kernel/KStart16.ZC +++ b/src/Kernel/KStart16.ZC @@ -50,23 +50,31 @@ GDT_TR: DU8 MP_PROCESSORS_NUM * 16 DUP(0); GDT_TR_RING3: DU8 MP_PROCESSORS_NUM * 16 DUP(0); #assert $$ - SYS_GDT == sizeof(CGDT) -SYS_FONT_PTR:: DU32 0; +SYS_FRAMEBUFFER_ADDR:: DU64 0; +SYS_FRAMEBUFFER_WIDTH:: DU64 0; +SYS_FRAMEBUFFER_HEIGHT:: DU64 0; +SYS_FRAMEBUFFER_PITCH:: DU64 0; +SYS_FRAMEBUFFER_BPP:: DU8 0; + +SYS_SMBIOS_ENTRY:: DU64 0; + +SYS_DISK_UUID:: DU64 0, 0; + +SYS_BOOT_STACK:: DU32 BOOT_RAM_LIMIT; + +SYS_IS_UEFI_BOOTED:: DU8 0; + +SYS_FRAMEBUFFER_LIST:: DU8 sizeof(CVideoInfo) * VBE_MODES_NUM DUP(0); -SYS_VBE_INFO:: DU8 sizeof(CVBEInfo) DUP(0); -SYS_VBE_MODES:: DU8 sizeof(CVBEModeShort) * VBE_MODES_NUM DUP(0); -SYS_VBE_FINAL_MODE:: DU8 sizeof(CVBEMode) DUP(0); -SYS_VBE_FINAL_MODE_NUM::DU16 0; //mode number of final mode set #assert $$ - SYS_KERNEL == sizeof(CKernel) - sizeof(CZXE) -TEMP_VBE_MODE: DU8 sizeof(CVBEMode) DUP(0); -MAX_VBE_MODE: DU8 sizeof(CVBEModeShort) DUP(0); -MAX_SCREEN_HEIGHT: DU16 0; +REQUESTED_SCREEN_WIDTH: DU16 1024; +REQUESTED_SCREEN_HEIGHT: DU16 768; -#exe -{ - StreamPrint("SCREEN_WIDTH: DU16 %d;" - "SCREEN_HEIGHT: DU16 %d;", kernel_config->screen_width, kernel_config->screen_height); -}; +VBE_TEMP_MODE: DU8 sizeof(CVBEMode) DUP(0); +VBE_INFO: DU8 sizeof(CVBEInfo) DUP(0); +VBE_FINAL_MODE_NUM: DU16 0; // gets set to final result mode number +VBE_STD_MODE_NUM: DU16 0; // gets set to mode number for standard 1024x768 //************************************ CORE0_16BIT_INIT:: @@ -84,10 +92,10 @@ GET_IP: POP BX MOV AX, CS ADD AX, BX PUSH AX - PUSH U16 @@04 + PUSH U16 @@05 RETF -@@04: STI +@@05: STI MOV AX, CS MOV DS, AX MOV U32 [SYS_RUN_LEVEL], RLF_16BIT @@ -100,34 +108,34 @@ GET_IP: POP BX //Get VBE implementation information MOV AX, 0x4F00 - MOV DI, SYS_VBE_INFO + MOV DI, VBE_INFO MOV CVBEInfo.signature[DI], 'VBE2' //set to 'VBE2' to use VBE 2.0 functionality INT 0x10 POP ES CMP AX, 0x004F - JE @@05 + JE @@10 JMP $$ //Freeze system if VBE not supported -@@05: +@@10: /*Loop variables: DI <- Temporary storage for mode information CX <- Mode number - DX <- mode array + DX <- 'mode' array GS <- Segment for video modes list SI <- Offset for video modes list */ //Obtain segment:offset of list of potential video modes - MOV AX, SYS_VBE_INFO + MOV AX, VBE_INFO MOV SI, CVBEInfo.video_modes[AX] MOV GS, CVBEInfo.video_modes+2[AX] - MOV DI, TEMP_VBE_MODE - MOV DX, SYS_VBE_MODES + MOV DX, SYS_FRAMEBUFFER_LIST + MOV DI, VBE_TEMP_MODE -@@06: //Loop through all the mode numbers +@@15: //Loop through all the mode numbers MOV AX, GS:[SI] CMP AX, 0xFFFF //FFFF signifies the end of the list - JE @@08 + JE @@25 ADD SI, 2 //Increment pointer to read next U16 mode @@ -141,90 +149,98 @@ GET_IP: POP BX INT 0x10 POP ES CMP AX, 0x004F - JNE @@06 //if call to get mode information failed + JNE @@15 //if call to get mode information failed -//filter everything but 32-bit color +//Filter everything but 32-bit color MOV AL, CVBEMode.bpp[DI] CMP AL, 32 - JNE @@06 + JNE @@15 //Check if the mode is actually supported MOV AX, CVBEMode.attributes[DI] AND AX, 0x91 //bit 0 = supported, bit 4 = graphics mode, bit 7 = linear framebuffer CMP AX, 0x91 - JNE @@06 + JNE @@15 //Only want memory model of packed pixel or direct color (RGB) -// MOV AX, CVBEMode.memory_model[DI] -// CMP AX, 4 -// JNE @@06 -// CMP AX, 6 -// JNE @@06 -//Copy information about this mode into an element of the mode array - MOV BX, CVBEMode.height[DI] - MOV CVBEModeShort.height[DX], BX - CMP BX, [MAX_SCREEN_HEIGHT] - JL @@07 + MOV AX, CVBEMode.memory_model[DI] + CMP AX, 4 + JE @@18 + CMP AX, 6 + JNE @@15 - MOV [MAX_SCREEN_HEIGHT], BX - MOV [MAX_VBE_MODE], CX +//Copy information about this mode into AX and BX +@@18: MOV BX, CVBEMode.height[DI] +@@20: MOV AX, CVBEMode.width[DI] -@@07: MOV AX, CVBEMode.width[DI] - MOV CVBEModeShort.width[DX], AX -// MOV EAX, CVBEMode.max_pixel_clock[DI] -// MOV CVBEModeShort.max_pixel_clock[DX], EAX +// Copy info into DX SYS_FRAMEBUFFER_LIST - MOV CVBEModeShort.mode_num[DX], CX - ADD DX, sizeof(CVBEModeShort) //next array element + MOV CVideoInfo.height[DX], BX + MOV CVideoInfo.width[DX], AX + ADD DX, sizeof(CVideoInfo) // next array element -//Check if width and height match - CMP AX, [SCREEN_WIDTH] - JNE @@06 - CMP BX, [SCREEN_HEIGHT] - JNE @@06 +//Check if width and height match standard 1024x768 +//If they match, set VBE_STD_MODE_NUM to this mode num + CMP AX, 1024 + JNE @@23 + CMP BX, 768 + JNE @@23 + MOV [VBE_STD_MODE_NUM], CX + +//Check if width and height match requested resolution +@@23: CMP AX, [REQUESTED_SCREEN_WIDTH] + JNE @@15 + CMP BX, [REQUESTED_SCREEN_HEIGHT] + JNE @@15 //If we've made it here we have our mode - MOV [SYS_VBE_FINAL_MODE_NUM], CX - JMP @@06 + MOV [VBE_FINAL_MODE_NUM], CX + JMP @@15 -@@08: //End of loop -//If there isn't a valid mode set by user through kernel config, set the mode with the biggest height. - MOV AX, [SYS_VBE_FINAL_MODE_NUM] +@@25: //End of loop + +//If requested resolution wasn't found in VBE mode list, +//use the standard 1024x768 mode as fallback + MOV AX, [VBE_FINAL_MODE_NUM] CMP AX, 0 - JNE @@09 - MOV CX, [MAX_VBE_MODE] - MOV [SYS_VBE_FINAL_MODE_NUM], CX + JNE @@30 -@@09: PUSH ES + MOV CX, [VBE_STD_MODE_NUM] + MOV [VBE_FINAL_MODE_NUM], CX + +@@30: PUSH ES PUSH DS POP ES -//Get mode infomration for the mode we want - MOV DI, SYS_VBE_FINAL_MODE - MOV CX, [SYS_VBE_FINAL_MODE_NUM] +//Get mode information for the mode we want + MOV DI, VBE_TEMP_MODE + MOV CX, [VBE_FINAL_MODE_NUM] MOV AX, 0x4F01 INT 0x10 POP ES CMP AX, 0x004F - JNE @@10 //if called failed + JNE @@35 //if called failed //Set the mode; call takes mode number in BX MOV AX, 0x4F02 MOV BX, CX INT 0x10 CMP AX, 0x004F - JNE @@10 + JNE @@35 + +//Give mode information to kernel + MOV EAX, CVBEMode.framebuffer[DI] + MOV U32 [SYS_FRAMEBUFFER_ADDR], EAX + MOV AX, CVBEMode.height[DI] + MOV U16 [SYS_FRAMEBUFFER_HEIGHT], AX + MOV AX, CVBEMode.width[DI] + MOV U16 [SYS_FRAMEBUFFER_WIDTH], AX + MOV AX, CVBEMode.pitch[DI] + MOV U16 [SYS_FRAMEBUFFER_PITCH], AX + MOV AL, CVBEMode.bpp[DI] + MOV U8 [SYS_FRAMEBUFFER_BPP], AL BTS U32 [SYS_RUN_LEVEL], RLf_VESA -@@10: - -//Get pointer to 8x8 VGA ROM font. - MOV AX, 0x1130 - MOV BH, 3 - INT 0x10 - MOV AX, ES - SHL EAX, 16 - MOV AX, BP - MOV U32 [SYS_FONT_PTR], EAX +@@35: //Get E801 memory map. //Output: AX = Memory between 1MiB and 16MiB in KiB (max 0x3C00 == 15 MiB) @@ -233,10 +249,10 @@ GET_IP: POP BX XOR DX, DX MOV AX, 0xE801 INT 0x15 - JCXZ @@12 //if CX and DX are zero, use AX and BX instead. + JCXZ @@40 //if CX and DX are zero, use AX and BX instead. MOV AX, CX MOV BX, DX -@@12: MOV U16 [MEM_E801], AX +@@40: MOV U16 [MEM_E801], AX MOV U16 [MEM_E801+2], BX //Get E820 memory map. @@ -245,21 +261,21 @@ GET_IP: POP BX PUSH DS POP ES MOV DI, MEM_E820 -@@15: PUSH CX +@@45: PUSH CX MOV EAX, 0xE820 MOV ECX, sizeof(CMemE820) MOV EDX, 'PAMS' INT 0x15 - JC @@20 + JC @@50 CMP EAX, 'PAMS' - JNE @@20 + JNE @@50 TEST EBX, EBX - JZ @@20 + JZ @@50 ADD DI, sizeof(CMemE820) POP CX - LOOP @@15 + LOOP @@45 SUB SP, 2 -@@20: ADD SP, 2 //if called failed we want to nullify the PUSHed CX value. +@@50: ADD SP, 2 //if called failed we want to nullify the PUSHed CX value. //Find how much space to map, start with E801 limit. XOR EAX, EAX @@ -270,24 +286,24 @@ GET_IP: POP BX //Find max of E820 to set mapped space. MOV SI, MEM_E820 -@@25: MOV CL, CMemE820.type[SI] +@@55: MOV CL, CMemE820.type[SI] TEST CL, CL - JZ @@35 + JZ @@65 MOV EBX, CMemE820.base [SI] MOV ECX, CMemE820.base+4[SI] ADD EBX, CMemE820.len [SI] ADC ECX, CMemE820.len+4 [SI] SUB EBX, EAX SBB ECX, EDX - JC @@30 + JC @@60 MOV EAX, CMemE820.base [SI] MOV EDX, CMemE820.base+4[SI] ADD EAX, CMemE820.len [SI] ADC EDX, CMemE820.len+4 [SI] -@@30: ADD SI, sizeof(CMemE820) - JMP @@25 +@@60: ADD SI, sizeof(CMemE820) + JMP @@55 -@@35: MOV [MEM_PHYSICAL_SPACE], EAX +@@65: MOV [MEM_PHYSICAL_SPACE], EAX MOV [MEM_PHYSICAL_SPACE+4], EDX //Get PCI Bus Info @@ -296,11 +312,11 @@ GET_IP: POP BX MOV AX, 0xB101 INT 0x1A CMP DX, 'PC' - JNE @@40 + JNE @@70 MOV CH, 0 INC CX MOV U16 [SYS_PCI_BUSES], CX -@@40: +@@70: CLI //Enable A20 IN AL, 0x92 diff --git a/src/Kernel/KStart32.ZC b/src/Kernel/KStart32.ZC index 53451831..4f296a0d 100755 --- a/src/Kernel/KStart32.ZC +++ b/src/Kernel/KStart32.ZC @@ -88,6 +88,7 @@ CORE0_32BIT_INIT:: //Entry point for $LK,"BootRAM",A="MN:BootRAM"$. BTS U32 [SYS_RUN_LEVEL], RLf_32BIT MOV ESI, U32 [SYS_BOOT_PATCH_TABLE_BASE] MOV EDI, U32 [MEM_BOOT_BASE] + MOV ESP, U32 [SYS_BOOT_STACK] MOV AX, CGDT.ds MOV DS, AX @@ -95,8 +96,15 @@ CORE0_32BIT_INIT:: //Entry point for $LK,"BootRAM",A="MN:BootRAM"$. MOV FS, AX MOV GS, AX MOV SS, AX - MOV ESP, BOOT_RAM_LIMIT //Tmp Stack + JMP @@02 + + ALIGN 16, OC_NOP + // Signature to find CORE0_32BIT_INIT + DU64 ZEALBOOTER_LIMINE_SIGNATURE_1; + DU64 ZEALBOOTER_LIMINE_SIGNATURE_2; + +@@02: //Patch abs addresses MOV ECX, U32 CPatchTableAbsAddr.abs_address_count[ESI] LEA ESI, U32 CPatchTableAbsAddr.abs_address[ESI] diff --git a/src/Kernel/KStart64.ZC b/src/Kernel/KStart64.ZC index e4317bf0..f814e440 100755 --- a/src/Kernel/KStart64.ZC +++ b/src/Kernel/KStart64.ZC @@ -83,7 +83,7 @@ USE64 //************************************ SYS_RAM_REBOOT:: //This gets copied high. $LK,"SYS_RAM_REBOOT",A="FF:::/System/Boot/BootRAM.ZC,SYS_RAM_REBOOT:2"$ PUSH U32 CGDT.ds //stack seg - PUSH U32 BOOT_RAM_LIMIT //stack + PUSH U32 [SYS_BOOT_STACK]//stack PUSH U32 0 //flags PUSH U32 CGDT.cs32 LEA RAX, [@@10] diff --git a/src/Kernel/Kernel.PRJ b/src/Kernel/Kernel.PRJ index 02d00a32..9487a413 100755 --- a/src/Kernel/Kernel.PRJ +++ b/src/Kernel/Kernel.PRJ @@ -30,6 +30,7 @@ #include "Sched" #include "Memory/MakeMemory" #include "FontStd" +#include "FontAux" #include "StrB" #include "KHashA" #include "KInterrupts" diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index 2729c8f3..2f22b54f 100755 --- a/src/Kernel/KernelA.HH +++ b/src/Kernel/KernelA.HH @@ -427,7 +427,7 @@ class CSysLimitBase }; #help_index "Memory/Info" -#define MEM_E820_ENTRIES_NUM 48 +#define MEM_E820_ENTRIES_NUM 256 #define MEM_E820t_USABLE 1 #define MEM_E820t_RESERVED 2 #define MEM_E820t_ACPI 3 @@ -536,14 +536,15 @@ class CVBEMode }; #assert sizeof(CVBEMode) == 256 -class CVBEModeShort +class CVideoInfo { - U16 width, - height, - mode_num; - U32 max_pixel_clock; //TODO refresh rates. + U16 width; + U16 height; }; +#define ZEALBOOTER_LIMINE_SIGNATURE_1 0xaa23c08ed10bd4d7; // See $LK+PU,"CORE0_32BIT_INIT",A="FF:::/Kernel/KStart32.ZC,JMP @@"$ +#define ZEALBOOTER_LIMINE_SIGNATURE_2 0xf6ceba7d4b74179a; // + #help_index "Boot" class CKernel {//Must match $LK,"OSStartUp",A="FF:::/Kernel/KStart16.ZC,MEM_BOOT_BASE"$ @@ -564,11 +565,16 @@ class CKernel U16 sys_pci_buses; ;$$ = ($$ + 15) & -16; CGDT sys_gdt; - U32 sys_font_ptr; - CVBEInfo sys_vbe_info; - CVBEModeShort sys_vbe_modes[VBE_MODES_NUM]; - CVBEMode sys_vbe_mode; - U16 sys_vbe_mode_num; + U64 sys_framebuffer_addr; + U64 sys_framebuffer_width; + U64 sys_framebuffer_height; + U64 sys_framebuffer_pitch; + U8 sys_framebuffer_bpp; + U64 sys_smbios_entry; + U64 sys_disk_uuid[2]; + U32 sys_boot_stack; + Bool sys_is_uefi_booted; + CVideoInfo sys_framebuffer_list[VBE_MODES_NUM]; }; //Run-Levels @@ -907,7 +913,7 @@ public class CHashImport:CHashSrcSym }; #help_index "Compiler/Internal" -#define PTR_STARS_NUM 4 +#define PTR_STARS_NUM 3 //Member List Flags #define MLF_DEFAULT_AVAILABLE 1 @@ -2722,7 +2728,7 @@ class CPCIDev //Command FIS flags #define AHCI_CF_DESCf_C 7 //'Command' bit. Set when FIS is an ATA command. -#define AHCI_CF_DESCF_C (1 << AHCI_CF_DESCF_C) +#define AHCI_CF_DESCF_C (1 << AHCI_CF_DESCf_C) //Port register flags //Command and Status register flags @@ -3015,7 +3021,7 @@ class CAtapiModeWriteList #define FILEMASK_AOT "*.ZC*;*.HH*;*.PRJ*" #define FILEMASK_SRC "*.ZC*;*.HH*;*.IN*;*.PRJ*" #define FILEMASK_DD FILEMASK_SRC ";*.DD*" -#define FILEMASK_TXT FILEMASK_DD ";*.TXT*" +#define FILEMASK_TXT FILEMASK_DD ";*.TXT*;*.CFG*" #define FILEMASK_GR "*.GR*" #help_index "File/Low Level" @@ -4278,7 +4284,6 @@ public class CTextGlobals U32 *raw_screen, *fb_alias; I64 rows, cols; //Use TEXT_ROWS,TEXT_COLS U64 *font, *aux_font, screen_size, buffer_size; - U8 *vga_alias; U8 border_chars[16]; Bool is_fb_busy; }; @@ -4387,10 +4392,6 @@ public class CDC #assert !($$ & 7) }; -#help_index "Devices" -//VGA Memory -#define VGAM_GRAPHICS 0xA0000 - #define "Char/Input;StdIn" //StrGet flags #define SGF_SHIFT_ESC_EXIT 1 //This kills task on @@ -4515,7 +4516,7 @@ public class CDebugGlobals #define BOOT_SRC_DVD 4 // $LK,"In",A="MN:In"$("") StdIn for call to $LK,"BootHDIns",A="MN:BootHDIns"$(). -#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT \n\n\n\n" +#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n\n\n" #help_index "Registry" //Registry sys_message_flags. $LK,"RegOneTimePopUp",A="MN:RegOneTimePopUp"$() @@ -4551,4 +4552,4 @@ class CProgress #define PRINTF_NEG_E 0x400 #define PRINTF_NEG_AUX_FORMAT_NUM 0x800 -#help_index "" \ No newline at end of file +#help_index "" diff --git a/src/Kernel/KernelB.HH b/src/Kernel/KernelB.HH index f207c52d..94865553 100755 --- a/src/Kernel/KernelB.HH +++ b/src/Kernel/KernelB.HH @@ -243,10 +243,20 @@ public _intern IC_FS CTask *Fs(); //FS segment register points to the current $L #help_file "::/Doc/TimeCycles" public _intern IC_RDTSC I64 TSCGet(); //Get time stamp counter. -#help_index "Graphics/VBE" -public _extern SYS_VBE_INFO CVBEInfo sys_vbe_info; -public _extern SYS_VBE_FINAL_MODE CVBEMode sys_vbe_mode; -_extern SYS_VBE_FINAL_MODE_NUM U16 sys_vbe_mode_num; -_extern SYS_VBE_MODES CVBEModeShort sys_vbe_modes[VBE_MODES_NUM]; +#help_index "Graphics/Framebuffer" +public _extern SYS_FRAMEBUFFER_ADDR U8 *sys_framebuffer_addr; +public _extern SYS_FRAMEBUFFER_WIDTH U64 sys_framebuffer_width; +public _extern SYS_FRAMEBUFFER_HEIGHT U64 sys_framebuffer_height; +public _extern SYS_FRAMEBUFFER_PITCH U64 sys_framebuffer_pitch; +public _extern SYS_FRAMEBUFFER_BPP U8 sys_framebuffer_bpp; + +_extern SYS_FRAMEBUFFER_LIST CVideoInfo sys_framebuffer_list[VBE_MODES_NUM]; + +#help_index "Processor/SMBIOS" +public _extern SYS_SMBIOS_ENTRY U8 *sys_smbios_entry; + +#help_index "" +public _extern SYS_DISK_UUID U64 sys_disk_uuid[2]; +public _extern SYS_IS_UEFI_BOOTED Bool sys_is_uefi_booted; #help_index "" diff --git a/src/Kernel/KernelC.HH b/src/Kernel/KernelC.HH index 87a6d99e..9bd4886a 100755 --- a/src/Kernel/KernelC.HH +++ b/src/Kernel/KernelC.HH @@ -622,6 +622,9 @@ public extern U0 PCIWriteU32(I64 bus, I64 dev, I64 fun, I64 rg, I64 val); public extern U0 PCIWriteU8( I64 bus, I64 dev, I64 fun, I64 rg, I64 val); public _extern SYS_PCIBIOS_SERVICE_DIR U32 sys_PCIBIOS_service_dir;//Far call routine in the BIOS public _extern SYS_PCI_SERVICES U32 sys_pci_services;//Far call routine in the BIOS +public extern Bool PCIBt( U8 *bit_field, I64 bit); // MOV-based Bt for use in PCI device memory-mapped IO areas. See $LK+PU,"Bt()",A="FF:::/Kernel/KernelB.HH,Bt("$. +public extern Bool PCIBtr( U8 *bit_field, I64 bit); // MOV-based Btr for use in PCI device memory-mapped IO areas. See $LK+PU,"Btr()",A="FF:::/Kernel/KernelB.HH,Btr("$. +public extern Bool PCIBts( U8 *bit_field, I64 bit); // MOV-based Bts for use in PCI device memory-mapped IO areas. See $LK+PU,"Bts()",A="FF:::/Kernel/KernelB.HH,Bts("$. #help_index "Processor" public extern U8 *IntEntryGet(I64 irq); diff --git a/src/Kernel/KeyDev.ZC b/src/Kernel/KeyDev.ZC index 2caad425..a897da1f 100755 --- a/src/Kernel/KeyDev.ZC +++ b/src/Kernel/KeyDev.ZC @@ -237,6 +237,6 @@ U0 KeyDevInit() CtrlAltCBSet('M', &CtrlAltM, "Cmd /Toggle Mute"); CtrlAltCBSet('N', &CtrlAltN, "Cmd /Next Focus Task",, TRUE); CtrlAltCBSet('T', &CtrlAltT, "Cmd /Terminal Window"); - CtrlAltCBSet('V', &CtrlAltV, "Cmd /VGA Flush",, TRUE); + CtrlAltCBSet('V', &CtrlAltV, "Cmd /Video Framebuffer Flush",, TRUE); CtrlAltCBSet('X', &CtrlAltX, "Cmd /Kill Focused Task",, TRUE); } diff --git a/src/Kernel/PCI.ZC b/src/Kernel/PCI.ZC index bc02daea..8d7c5d87 100755 --- a/src/Kernel/PCI.ZC +++ b/src/Kernel/PCI.ZC @@ -126,3 +126,32 @@ else bus, dev, fun. pci_end: return res; } + +Bool PCIBt(U8 reg RBX *bit_field, I64 reg RDX bit) +{ // MOV-based Bt for use in PCI device memory-mapped IO areas. See $LK+PU,"Bt()",A="FF:::/Kernel/KernelB.HH,Bt("$. + bit_field += bit / 8; + bit &= 7; + return (*bit_field & 1 << bit) >> bit; +} + +Bool PCIBtr(U8 reg RDX *bit_field, I64 reg RBX bit) +{ // MOV-based Btr for use in PCI device memory-mapped IO areas. See $LK+PU,"Btr()",A="FF:::/Kernel/KernelB.HH,Btr("$. + U64 reg R9 chunk_mod = bit & 31, chunk_bit = 1 << chunk_mod; + bit_field(U32 *) += bit / 32; + Bool reg R8 result = (*bit_field(U32 *) & chunk_bit) >> chunk_mod; + + *bit_field(U32 *) &= ~chunk_bit; + + return result; +} + +Bool PCIBts(U8 reg RDX *bit_field, I64 reg RBX bit) +{ // MOV-based Bts for use in PCI device memory-mapped IO areas. See $LK+PU,"Bts()",A="FF:::/Kernel/KernelB.HH,Bts("$. + U64 reg R9 chunk_mod = bit & 31, chunk_bit = 1 << chunk_mod; + bit_field(U32 *) += bit / 32; + Bool reg R8 result = (*bit_field(U32 *) & chunk_bit) >> chunk_mod; + + *bit_field(U32 *) |= chunk_bit; + + return result; +} diff --git a/src/Kernel/SerialDev/Mouse.ZC b/src/Kernel/SerialDev/Mouse.ZC index f81cc9a5..756aaedf 100755 --- a/src/Kernel/SerialDev/Mouse.ZC +++ b/src/Kernel/SerialDev/Mouse.ZC @@ -24,8 +24,8 @@ U0 MouseUpdate(I64 x, I64 y, I64 z, Bool l, Bool r) mouse.pos.z = mouse.presnap.z; } - mouse.pos.x = ClampI64(mouse.pos.x, 0, sys_vbe_mode.width - 1); - mouse.pos.y = ClampI64(mouse.pos.y, 0, sys_vbe_mode.height - 1); + mouse.pos.x = ClampI64(mouse.pos.x, 0, sys_framebuffer_width - 1); + mouse.pos.y = ClampI64(mouse.pos.y, 0, sys_framebuffer_height - 1); mouse.pos_text.x = mouse.pos.x / FONT_WIDTH; if (mouse.pos_text.x >= text.cols) { @@ -46,9 +46,9 @@ U0 MouseUpdate(I64 x, I64 y, I64 z, Bool l, Bool r) U0 MouseSet(I64 x=I64_MAX, I64 y=I64_MAX, I64 z=I64_MAX, I64 l=I64_MAX, I64 r=I64_MAX) {//Note: Generates a message. See $LK,"MouseSet",A="FF:::/Demo/Games/Zing.ZC,MouseSet"$(). - if (!(0 <= x < sys_vbe_mode.width)) + if (!(0 <= x < sys_framebuffer_width)) x = mouse.pos.x; - if (!(0 <= y < sys_vbe_mode.height)) + if (!(0 <= y < sys_framebuffer_height)) y = mouse.pos.y; if (z == I64_MAX) z = mouse.pos.z; @@ -227,14 +227,14 @@ U0 MouseHardSetPost() //TODO mouse_grid.x_offset? if (i < 0) mouse.offset.x -= i; - else if (i >= sys_vbe_mode.width) - mouse.offset.x += sys_vbe_mode.width - 1 - i; + else if (i >= sys_framebuffer_width) + mouse.offset.x += sys_framebuffer_width - 1 - i; i = Trunc(mouse.scale.y * mouse_hard.pos.y / mouse_grid.y) * mouse_grid.y + mouse.offset.y; if (i < 0) mouse.offset.y -= i; - else if (i >= sys_vbe_mode.height) - mouse.offset.y += sys_vbe_mode.height - 1 - i; + else if (i >= sys_framebuffer_height) + mouse.offset.y += sys_framebuffer_height - 1 - i; if (mouse_hard.pos.x != mouse_hard_last.pos.x || mouse_hard.pos.y != mouse_hard_last.pos.y || mouse_hard.pos.z != mouse_hard_last.pos.z) @@ -400,10 +400,10 @@ U0 KbdMouseInit() mouse_hard.scale.x = 0.5; mouse_hard.scale.y = 0.5; mouse_hard.scale.z = 1.0; - mouse_hard.prescale.x = sys_vbe_mode.width / mouse_hard.scale.x / 2.0; - mouse_hard.prescale.y = sys_vbe_mode.height / mouse_hard.scale.y / 2.0; + mouse_hard.prescale.x = sys_framebuffer_width / mouse_hard.scale.x / 2.0; + mouse_hard.prescale.y = sys_framebuffer_height / mouse_hard.scale.y / 2.0; mouse_hard.prescale.z = 0 / mouse_hard.scale.z; - mouse_hard.pos.x = sys_vbe_mode.width >> 1; - mouse_hard.pos.y = sys_vbe_mode.height >> 1; + mouse_hard.pos.x = sys_framebuffer_width >> 1; + mouse_hard.pos.y = sys_framebuffer_height >> 1; MemCopy(&mouse_hard_last, &mouse_hard, sizeof(CMouseHardStateGlobals)); } diff --git a/src/Misc/Auto/AutoDistro.ZC b/src/Misc/Auto/AutoDistro.ZC index 5c311e47..e2a2fbf5 100755 --- a/src/Misc/Auto/AutoDistro.ZC +++ b/src/Misc/Auto/AutoDistro.ZC @@ -2,7 +2,7 @@ // Custom DoDistro file that generates an AUTO.ISO. // Used by host OS to create a full Distro ISO synced with GitHub repo. -#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n1024\n768\n\n\n" +#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n\n\n" U0 MakeMyISO(U8 *_out_iso_filename) {//Does everything with current drive. diff --git a/src/Misc/Auto/AutoFullDistro0.ZC b/src/Misc/Auto/AutoFullDistro0.ZC index b456e991..21e8914c 100755 --- a/src/Misc/Auto/AutoFullDistro0.ZC +++ b/src/Misc/Auto/AutoFullDistro0.ZC @@ -7,7 +7,7 @@ U0 Auto() for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATA) @@ -18,12 +18,16 @@ U0 Auto() } } + WinMax; BootMHDIns('C'); - in_str = MStrPrint("Sleep(700);In(\"CC\\n%d\\n\\n1024\\n768\\n\\n\\n\");", ata_port); + in_str = MStrPrint("Sleep(700);In(\"CC\\n%d\\n\\n\\n\\n\");", ata_port); OnceDrive('C', in_str); Free(in_str); - in_str = MStrPrint("BootHDIns;OnceFlush;Once(\"#include \\\"/Misc/Auto/AutoFullDistro1\\\";;Auto;\");Reboot;"); + in_str = MStrPrint( "BootHDIns;" + "OnceFlush;" + "Once(\"#include \\\"/Misc/Auto/AutoFullDistro1\\\";;Auto;\");" + "Reboot;"); OnceDrive('C', in_str); OutU8(0x501,0x31); } -Auto; \ No newline at end of file +Auto; diff --git a/src/Misc/Auto/AutoFullDistro1.ZC b/src/Misc/Auto/AutoFullDistro1.ZC index 6018209f..df207faf 100755 --- a/src/Misc/Auto/AutoFullDistro1.ZC +++ b/src/Misc/Auto/AutoFullDistro1.ZC @@ -1,4 +1,37 @@ U0 Auto() { - PopUp("#include \"/Misc/Auto/AutoFullDistro2\""); -} \ No newline at end of file + I64 i, ata_port = -1; + CAHCIPort *port; + U8 *in_str; + + for (i = 0; i < AHCI_MAX_PORTS; i++) + + { + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) + { + port = &blkdev.ahci_hba->ports[i]; + if (port->signature == AHCI_PxSIG_ATA) + { + ata_port = i; + break; + } + } + } + + WinMax; + BootMHDIns('C'); + Copy("C:/Tmp/OSBuild/Kernel/KStart16.ZC", "C:/Kernel/"); + Copy("C:/Tmp/OSBuild/Kernel/KernelA.HH", "C:/Kernel/"); + in_str = MStrPrint("CC\n%d\n\n\n\n", ata_port); + Sleep(700); + In(in_str); + BootHDIns; + OnceFlush; + Free(in_str); + in_str = MStrPrint( "OnceFlush;" + "Once(\"#include \\\"/Misc/Auto/AutoFullDistro2\\\";;Auto;\");" + "Reboot;"); + OnceDrive('C', in_str); + Reboot; +} +Auto; diff --git a/src/Misc/Auto/AutoFullDistro2.ZC b/src/Misc/Auto/AutoFullDistro2.ZC index 82f4fd6c..4f0bd44f 100755 --- a/src/Misc/Auto/AutoFullDistro2.ZC +++ b/src/Misc/Auto/AutoFullDistro2.ZC @@ -1,72 +1,36 @@ -#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n1024\n768\n\n\n" - -U0 MakeMyISO() +U0 Auto() { - U8 *_out_iso_filename = "/Tmp/MyDistro.ISO.C"; - U8 *out_iso_filename = FileNameAbs(_out_iso_filename); - I64 line_count = LineRep("/*", "-r") + LineRep("/System/*") + LineRep("/Compiler/*", "-S+$$") + LineRep("/Kernel/*"); + I64 i, ata_port = -1; + CAHCIPort *port; + U8 *in_str; + + for (i = 0; i < AHCI_MAX_PORTS; i++) - if (!DriveIsWritable) { - "Drive must be writable. Install on Hard drive, first.\n"; - return; + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) + { + port = &blkdev.ahci_hba->ports[i]; + if (port->signature == AHCI_PxSIG_ATA) + { + ata_port = i; + break; + } + } } - DocTreeFWrite("/System/Define.ZC", "LineRep", "DefinePrint(\"DD_ZEALOS_LOC\",\"%,d\");\n", line_count); - DefinePrint("DD_ZEALOS_LOC", "%,d", line_count); - - "Total LOC:%12,d\n\n", line_count; - - DelTree("/Distro"); - Del(out_iso_filename); - - ProgressBarsReset; - progress1_max = 14; - StrCopy(progress1_desc, "Copying files to /Distro"); - - DirMake("/Distro"); - In(STD_DISTRO_DVD_CONFIG); - BootDVDIns; - progress1++; - - Copy("/*", "/Distro"); - progress1++; - DirMake("/Distro" BOOT_DIR); - Move(BOOT_DIR_DVD_KERNEL_ZXE, "/Distro" BOOT_DIR_KERNEL_ZXE); - progress1++; - CopyTree("/Home", "/Distro/Home"); - progress1++; - Del("/Distro/Home/Registry.ZC"); - CopyTree("/System", "/Distro/System"); - progress1++; - CopyTree("/Apps", "/Distro/Apps"); - progress1++; - CopyTree("/Compiler", "/Distro/Compiler"); - progress1++; - CopyTree("/Demo", "/Distro/Demo"); - progress1++; - CopyTree("/Doc", "/Distro/Doc"); - progress1++; - CopyTree("/Kernel", "/Distro/Kernel"); - progress1++; - CopyTree("/Misc", "/Distro/Misc"); - progress1++; - - CopyTree("/Downloads", "/Distro/Downloads"); - progress1++; - DirMake("/Distro/Tmp"); - DirMake("/Distro/Tmp/ScreenShots"); - progress1++; - StrCopy(progress1_desc, "Building ISO"); - RedSeaISO(out_iso_filename, "/Distro", "/Distro" BOOT_DIR_KERNEL_ZXE); - progress1++; - - //If CD-ROM use MT_CD instead of MT_DVD. - //DVDImageWrite('T',out_iso_filename,MT_DVD); //Uncomment to burn. - - DelTree("/Distro"); - ProgressBarsReset; - Free(out_iso_filename); + WinMax; + BootMHDIns('C'); + CopyTree("C:/Tmp/OSBuild/Kernel/", "C:/Kernel/"); + in_str = MStrPrint("CC\n%d\n\n\n\n", ata_port); + Sleep(700); + In(in_str); + BootHDIns; + OnceFlush; + Free(in_str); + in_str = MStrPrint( "OnceFlush;" + "Once(\"#include \\\"/Misc/Auto/AutoFullDistro3\\\";;Auto;\");" + "Reboot;"); + OnceDrive('C', in_str); + Reboot; } -MakeMyISO; -OutU8(0x501,0x31); +Auto; diff --git a/src/Misc/Auto/AutoFullDistro3.ZC b/src/Misc/Auto/AutoFullDistro3.ZC new file mode 100755 index 00000000..e7ec0760 --- /dev/null +++ b/src/Misc/Auto/AutoFullDistro3.ZC @@ -0,0 +1,33 @@ +U0 Auto() +{ + I64 i, ata_port = -1; + CAHCIPort *port; + U8 *in_str; + + for (i = 0; i < AHCI_MAX_PORTS; i++) + + { + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) + { + port = &blkdev.ahci_hba->ports[i]; + if (port->signature == AHCI_PxSIG_ATA) + { + ata_port = i; + break; + } + } + } + + WinMax; + CopyTree("C:/Tmp/OSBuild/", "C:/"); + in_str = MStrPrint("CC\n%d\n\n\n\n", ata_port); + Sleep(700); + In(in_str); + BootHDIns; + OnceFlush; + in_str = MStrPrint("#include \"/Misc/Auto/AutoFullDistro4\";;Auto;;"); + OnceDrive('C', in_str); + DelTree("C:/Tmp/OSBuild"); + Reboot; +} +Auto; diff --git a/src/Misc/Auto/AutoFullDistro4.ZC b/src/Misc/Auto/AutoFullDistro4.ZC new file mode 100755 index 00000000..bfd5ad96 --- /dev/null +++ b/src/Misc/Auto/AutoFullDistro4.ZC @@ -0,0 +1,4 @@ +U0 Auto() +{ + PopUp("#include \"/Misc/Auto/AutoFullDistro5\""); +} \ No newline at end of file diff --git a/src/Misc/Auto/AutoFullDistro5.ZC b/src/Misc/Auto/AutoFullDistro5.ZC new file mode 100755 index 00000000..962128f6 --- /dev/null +++ b/src/Misc/Auto/AutoFullDistro5.ZC @@ -0,0 +1,74 @@ +#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n\n\n" + +U0 MakeMyISO() +{ + U8 *_out_iso_filename = "/Tmp/MyDistro.ISO.C"; + U8 *out_iso_filename = FileNameAbs(_out_iso_filename); + I64 line_count = LineRep("/*", "-r") + LineRep("/System/*") + LineRep("/Compiler/*", "-S+$$") + LineRep("/Kernel/*"); + + if (!DriveIsWritable) + { + "Drive must be writable. Install on Hard drive, first.\n"; + return; + } + + DocTreeFWrite("/System/Define.ZC", "LineRep", "DefinePrint(\"DD_ZEALOS_LOC\",\"%,d\");\n", line_count); + DefinePrint("DD_ZEALOS_LOC", "%,d", line_count); + + "Total LOC:%12,d\n\n", line_count; + + DelTree("/Distro"); + Del(out_iso_filename); + + ProgressBarsReset; + progress1_max = 14; + StrCopy(progress1_desc, "Copying files to /Distro"); + + DirMake("/Distro"); + In(STD_DISTRO_DVD_CONFIG); + BootDVDIns; + progress1++; + + Copy("/*", "/Distro"); + progress1++; + DirMake("/Distro" BOOT_DIR); + Move(BOOT_DIR_DVD_KERNEL_ZXE, "/Distro" BOOT_DIR_KERNEL_ZXE); + progress1++; + CopyTree("/Home", "/Distro/Home"); + progress1++; + Del("/Distro/Home/Registry.ZC"); + CopyTree("/System", "/Distro/System"); + progress1++; + CopyTree("/Apps", "/Distro/Apps"); + progress1++; + CopyTree("/Compiler", "/Distro/Compiler"); + progress1++; + CopyTree("/Demo", "/Distro/Demo"); + progress1++; + CopyTree("/Doc", "/Distro/Doc"); + progress1++; + CopyTree("/Kernel", "/Distro/Kernel"); + progress1++; + CopyTree("/Misc", "/Distro/Misc"); + progress1++; + + CopyTree("/Downloads", "/Distro/Downloads"); + progress1++; + DirMake("/Distro/Tmp"); + DirMake("/Distro/Tmp/ScreenShots"); + progress1++; + StrCopy(progress1_desc, "Building ISO"); + RedSeaISO(out_iso_filename, "/Distro", "/Distro" BOOT_DIR_KERNEL_ZXE); + progress1++; + + //If CD-ROM use MT_CD instead of MT_DVD. + //DVDImageWrite('T',out_iso_filename,MT_DVD); //Uncomment to burn. + + Copy("/Distro" BOOT_DIR_KERNEL_ZXE, "/Tmp/DVD" KERNEL_ZXE); + + DelTree("/Distro"); + ProgressBarsReset; + Free(out_iso_filename); +} +MakeMyISO; +OutU8(0x501,0x31); diff --git a/src/Misc/Auto/AutoInstall.ZC b/src/Misc/Auto/AutoInstall.ZC index 41f63ccf..d3f5f4ec 100755 --- a/src/Misc/Auto/AutoInstall.ZC +++ b/src/Misc/Auto/AutoInstall.ZC @@ -41,7 +41,7 @@ U0 VMInstallDrive(CTask *task, U8 drv_let, I64 ata_port, I64 atapi_port) XTalkWait(task, "C\n%d\n", ata_port); if (atapi_port > -1) XTalkWait(task, "T%d\n", atapi_port); - XTalkWait(task, "\n1024\n768\n\n\n"); //Exit Drives, set Screen Resolution, skip Disk Cache and Options + XTalkWait(task, "\n\n\n"); //Exit Drives, skip Disk Cache and Options } U0 VMInstallWiz() @@ -66,7 +66,7 @@ U0 VMInstallWiz() SATARep; for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATA) @@ -78,7 +78,7 @@ U0 VMInstallWiz() } for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATAPI) diff --git a/src/Misc/DoDistro.ZC b/src/Misc/DoDistro.ZC index 761f5dd3..1baf3459 100755 --- a/src/Misc/DoDistro.ZC +++ b/src/Misc/DoDistro.ZC @@ -1,6 +1,6 @@ //Make Your own Distro by #include-ing this file. -#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n1024\n768\n\n\n" +#define STD_DISTRO_DVD_CONFIG "TB\nScale2Mem(2048,0x40000)\nT\n\n\n\n" U0 MakeMyISO(U8 *_out_iso_filename) {//Does everything with current drive. diff --git a/src/Misc/OSInstall.ZC b/src/Misc/OSInstall.ZC index 44148db5..ad876287 100755 --- a/src/Misc/OSInstall.ZC +++ b/src/Misc/OSInstall.ZC @@ -1,3 +1,17 @@ + +#define LIMINE_HDD_FILE "/Boot/Limine-HDD.HH" +#define LIMINE_HDD_INSTALLER "/System/Boot/LimineMHDIns.ZC" +#include LIMINE_HDD_FILE +#include LIMINE_HDD_INSTALLER + +#define LIMINE_INSTALL_PROMPT \ +"Install $$GREEN$$Public Domain$$FG$$ ZealOS Boot Loader,\n" \ +"or $$RED$$BSD-2 licensed$$FG$$ Limine Boot Loader?\n\n" \ +"$$DKGRAY$$ZealOS Boot Loader is written in public-domain ZealC, but only supports BIOS mode.\n\n" \ +"Limine supports UEFI and BIOS mode and multiple boot protocols, but is written in BSD-2 licensed C code, and cannot be modified within ZealOS.$$FG$$\n\n\n" + +// TODO FIXME: refactor OSUpgrade code into optional Diff prompt to compare ISO<->HDD before Install. + CDirEntry OSFilesMGFind(CDirEntry *needle_entry, CDirEntry *haystack_list) { while (haystack_list) @@ -10,7 +24,7 @@ CDirEntry OSFilesMGFind(CDirEntry *needle_entry, CDirEntry *haystack_list) return NULL; } -U0 OSFilesMergeInner(CDirEntry *tmpde1, CDirEntry *tmpde2, I64 *_fuf_flags, I64 *_df_flags, Bool auto) +U0 OSFilesMergeInner(CDirEntry *tmpde1, CDirEntry *tmpde2, I64 *_df_flags) { CDirEntry *tmpde; U8 *new; @@ -23,28 +37,27 @@ U0 OSFilesMergeInner(CDirEntry *tmpde1, CDirEntry *tmpde2, I64 *_fuf_flags, I64 "$$BROWN$$Does Not Exist:%s$$FG$$\n", tmpde1->full_name; new = StrNew(tmpde1->full_name); new[0] = tmpde2->full_name[0]; // shortcut to quickly get drive letter - Copy(tmpde1->full_name, new); + + if (tmpde1->attr & RS_ATTR_DIR) + CopyTree(tmpde1->full_name, new); + else + { + Copy(tmpde1->full_name, new); + } + Free(new); } else { if (tmpde1->attr & RS_ATTR_DIR) - OSFilesMergeInner(tmpde1->sub, tmpde->sub, _fuf_flags, _df_flags, auto); + OSFilesMergeInner(tmpde1->sub, tmpde->sub, _df_flags); else { - if (AbsI64(tmpde1->datetime - tmpde->datetime) > CDATE_FREQ * 2) {//slop + if (FilesFindMatch(tmpde1->full_name, FILEMASK_TXT)) + { "\n$$LTRED$$%s$$FG$$\n", tmpde->full_name; "$$LTGREEN$$%s$$FG$$\n", tmpde1->full_name; - if (Bt(_fuf_flags, FUf_DIFF)) - { - if (FilesFindMatch(tmpde1->full_name, FILEMASK_TXT)) - { - if (!auto) - Diff(tmpde->full_name, tmpde1->full_name, _df_flags); - else - Copy(tmpde1->full_name, tmpde->full_name); - } - } + Diff(tmpde->full_name, tmpde1->full_name, _df_flags); } } } @@ -54,7 +67,7 @@ U0 OSFilesMergeInner(CDirEntry *tmpde1, CDirEntry *tmpde2, I64 *_fuf_flags, I64 U0 OSFilesMerge(U8 *dst_files_find_mask="/*", U8 *src_files_find_mask="/*", U8 *fu_flags=NULL) { // See $LK+PU,"Merge",A="FF:::/System/Utils/Merge.ZC,public U0 Merge"$. - I64 df_flags = 0, fuf_flags = 0, ch; + I64 df_flags, fuf_flags = 0, ch; CDirEntry *tmpde1 = NULL, *tmpde2 = NULL; FlagsScan(&fuf_flags, Define("ST_FILE_UTIL_FLAGS"), "+r"); @@ -64,20 +77,26 @@ U0 OSFilesMerge(U8 *dst_files_find_mask="/*", U8 *src_files_find_mask="/*", U8 * PrintWarn("This is based strictly on file dates.\n"); tmpde1 = FilesFind(src_files_find_mask, fuf_flags & FUG_FILES_FIND); tmpde2 = FilesFind(dst_files_find_mask, fuf_flags & FUG_FILES_FIND); - fuf_flags &= FUF_DIFF; "\n\nManual or Automatic Upgrade? (M/A): "; do ch = ToUpper(CharGet(, FALSE)); while (ch != 'M' && ch != 'A'); + + "%c\n", ch; + if (ch == 'M') { PopUpOk("\n$$LTGREEN$$FILE2$$FG$$ is new changes.\n" "$$LTRED$$FILE1$$FG$$ is from existing install."); - OSFilesMergeInner(tmpde1, tmpde2, &fuf_flags, &df_flags, FALSE); + df_flags = 0; + OSFilesMergeInner(tmpde1, tmpde2, &df_flags); } else - OSFilesMergeInner(tmpde1, tmpde2, &fuf_flags, &df_flags, TRUE); + { + df_flags = DF_REMAINDER_ALL_FILE2 | DF_NO_MORE_PROMPTS_THIS_FILE | DF_KEEP_FLAGS; + OSFilesMergeInner(tmpde1, tmpde2, &df_flags); + } DirTreeDel(tmpde1); DirTreeDel(tmpde2); @@ -89,17 +108,36 @@ U0 OSMerge(U8 dst_drv, U8 src_drv=':') U8 *src = MStrPrint("%C:/", src_drv); CopyTree(dst, "B:/"); - Copy(MStrPrint("%C:/Misc/Bible.TXT", src_drv), "B:/Misc/Bible.TXT"); - Copy(MStrPrint("%C:/Misc/Clementine.TXT", src_drv), "B:/Misc/Clementine.TXT"); + Del("B:/Misc/Bible.TXT"); // Deleting from B:/ prevents causing hang when merging large .TXT files, + Del("B:/Misc/Clementine.TXT"); // they will instead be copied over from boot drive in OSMergeInner + + Del("B:/Boot/Limine.CFG"); // Delete to make merge output ignore (copy) this, since it gets regenerated later + + DocMax; + + "$$PB$$$$PB$$$$LTCYAN$$Beginning Upgrade (running OSFilesMerge) ...$$FG$$\n\n"; + OSFilesMerge("B:/", src, "+d"); + + "\n\n$$LTCYAN$$Upgrade merge completed." + "\nChanges listed above, scroll up to see all." + "\n\nPress ESC when you are ready to finish Upgrade (write merged files to disk).$$FG$$\n\n"; + View; + DocBottom; + CopyTree("B:/", dst); + + ExePrint("Del(\"%C:/Boot/Limine-CD.BIN\");", dst_drv); + ExePrint("Del(\"%C:/Boot/Limine-CD-EFI.BIN\");", dst_drv); + ExePrint("Del(\"%C:/Boot/Limine.CFG\");", dst_drv); + ExePrint("Del(\"%C:/boot.catalog\");", dst_drv); + } U0 OSUpgrade() { - I64 drv_let; + I64 drv_let, ch; U8 *st, *port_st; - I64 res_num; CTask *task; task = User; @@ -147,17 +185,44 @@ U0 OSUpgrade() OSMerge(drv_let); // src_drv needed? - XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\n%C\n%s\n\n", drv_let, drv_let, port_st); - VideoRep; - res_num = I64Get("Enter desired list num ($$PURPLE$$$$FG$$ for max res): ",, 1); - XTalkWait(task, "%d\n\n\n", res_num); //skip through Disk Cache, Options + XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\nC\n%s\n\n", drv_let, port_st); + XTalkWait(task, "\n\n"); //skip through Disk Cache, Options - "$$RED$$Install Master Boot Loader?$$FG$$"; - if (YorN) + if (!sys_is_uefi_booted) { - '\n'; - BootMHDIns(drv_let); + "$$RED$$Install Master Boot Loader?$$FG$$"; + if (YorN) + { + "\n\n"; + if (FileFind(LIMINE_HDD_FILE)) + { + "" LIMINE_INSTALL_PROMPT; + "(Z/L): "; + + do + ch = ToUpper(CharGet(, FALSE)); + while (ch != 'Z' && ch != 'L'); + + "%c\n", ch; + + if (ch == 'Z') + { + BootMHDIns(drv_let); + "\n(Generating optional UEFI-mode Limine.CFG...)\n"; + LimineCFGMake(drv_let); + } + else + { + LimineMHDIns(drv_let); + } + "\n\n"; + } + else + BootMHDIns(drv_let); + } } + else + LimineCFGMake(drv_let); WinVert(task->win_top, Fs->win_bottom); Kill(task); @@ -169,9 +234,22 @@ U0 InstallDrive(U8 drv_let) while (!DriveCheck(blkdev.let_to_drive[drv_let - 'A'], FALSE)) Sleep(1); + + Sleep(1000); + '.'; + Sleep(1000); + '.'; + Sleep(1000); + '.'; Sleep(1000); ExePrint("CopyTree(\"::/\",\"%C:/\");", drv_let); + + ExePrint("Del(\"%C:/Boot/Limine-CD.BIN\");", drv_let); + ExePrint("Del(\"%C:/Boot/Limine-CD-EFI.BIN\");", drv_let); + ExePrint("Del(\"%C:/Boot/Limine.CFG\");", drv_let); + ExePrint("Del(\"%C:/boot.catalog\");", drv_let); + ExePrint("DirMake(\"%C:/Tmp\");", drv_let); ExePrint("DirMake(\"%C:/Tmp/ScreenShots\");", drv_let); ExePrint("DirMake(\"%C:/Home\");", drv_let); @@ -206,13 +284,13 @@ U0 VMInstallDrive(CTask *task, U8 drv_let, I64 ata_port, I64 atapi_port) XTalkWait(task, "C\n%d\n", ata_port); if (atapi_port > -1) XTalkWait(task, "T%d\n", atapi_port); - XTalkWait(task, "\n1024\n768\n\n\n"); //Exit Drives, set Screen Resolution, skip Disk Cache and Options + XTalkWait(task, "\n\n\n\n"); //Exit Drives, skip Disk Cache and Options } U0 VMInstallWiz() { CTask *task; - I64 i, atapi_port = -1, ata_port = -1; + I64 i, atapi_port = -1, ata_port = -1, ch; CAHCIPort *port; task = User; @@ -229,7 +307,7 @@ U0 VMInstallWiz() SATARep; for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATA) @@ -241,7 +319,7 @@ U0 VMInstallWiz() } for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; if (port->signature == AHCI_PxSIG_ATAPI) @@ -256,7 +334,38 @@ U0 VMInstallWiz() { VMInstallDrive(task, 'C', ata_port, atapi_port); VMInstallDrive(task, 'D', ata_port, atapi_port); - BootMHDIns('C'); + if (!sys_is_uefi_booted) + { + if (FileFind(LIMINE_HDD_FILE)) + { + "\n\n" + "" LIMINE_INSTALL_PROMPT; + "(Z/L): "; + + do + ch = ToUpper(CharGet(, FALSE)); + while (ch != 'Z' && ch != 'L'); + + "%c\n", ch; + + if (ch == 'Z') + { + BootMHDIns('C'); + "\n(Generating optional UEFI-mode Limine.CFG...)\n"; + LimineCFGMake('C'); + } + else + { + LimineMHDIns('C'); + } + "\n\n"; + } + else + BootMHDIns('C'); + } + else + LimineCFGMake('C'); + } WinVert(task->win_top, Fs->win_bottom); @@ -267,7 +376,7 @@ U0 RegularInstallWiz() { I64 drv_let; U8 *st, *port_st; - I64 ch, res_num; + I64 ch; CTask *task; task = User; @@ -336,15 +445,43 @@ U0 RegularInstallWiz() XTalkWait(task, "BootHDIns('%C');\n\nB\n0x20000\nC\n%s\n\n", drv_let, port_st); - VideoRep; - res_num = I64Get("Enter desired list num ($$PURPLE$$$$FG$$ for max res): ",, 1); - XTalkWait(task, "%d\n\n\n", res_num); //skip through Disk Cache, Options - "$$RED$$Install Master Boot loader?$$FG$$"; - if (YorN) + XTalkWait(task, "\n\n"); //skip through Disk Cache, Options + if (!sys_is_uefi_booted) { - '\n'; - BootMHDIns(drv_let); + "$$RED$$Install Master Boot loader?$$FG$$"; + if (YorN) + { + "\n\n"; + if (FileFind(LIMINE_HDD_FILE)) + { + "" LIMINE_INSTALL_PROMPT; + "(Z/L): "; + + do + ch = ToUpper(CharGet(, FALSE)); + while (ch != 'Z' && ch != 'L'); + + + "%c\n", ch; + + if (ch == 'Z') + { + BootMHDIns(drv_let); + "\n(Generating optional UEFI-mode Limine.CFG...)\n"; + LimineCFGMake(drv_let); // ensures we don't leave the LiveCD's Limine.CFG on the HDD + } + else + { + LimineMHDIns(drv_let); + } + "\n\n"; + } + else + BootMHDIns(drv_let); + } } + else + LimineCFGMake(drv_let); WinVert(task->win_top, Fs->win_bottom); Kill(task); @@ -380,6 +517,8 @@ Bool DoInstall(Bool prompt_reboot) ch = ToUpper(CharGet(, FALSE)); while (ch != 'U' && ch != 'I'); + "%c\n", ch; + if (ch == 'U') OSUpgrade; else @@ -400,6 +539,8 @@ Bool DoInstall(Bool prompt_reboot) ch = ToUpper(CharGet(, FALSE)); while (ch != 'U' && ch != 'I'); + "%c\n", ch; + if (ch == 'I') { RegularInstallWiz(); diff --git a/src/System/BlkDev/Mount.ZC b/src/System/BlkDev/Mount.ZC index 9f1c5e02..e66d18cb 100755 --- a/src/System/BlkDev/Mount.ZC +++ b/src/System/BlkDev/Mount.ZC @@ -60,7 +60,7 @@ public I64 SATARep(I64 bd_type=BDT_NULL) for (i = 0; i < AHCI_MAX_PORTS; i++) { - if (Bt(&blkdev.ahci_hba->ports_implemented, i)) + if (PCIBt(&blkdev.ahci_hba->ports_implemented, i)) { port = &blkdev.ahci_hba->ports[i]; diff --git a/src/System/Boot/BootMHDIns.ZC b/src/System/Boot/BootMHDIns.ZC index d23cd40b..8a259514 100755 --- a/src/System/Boot/BootMHDIns.ZC +++ b/src/System/Boot/BootMHDIns.ZC @@ -12,12 +12,13 @@ //Old master boot record #define BOOT_DIR_OLDMBR_BIN BOOT_DIR "/OldMBR.BIN" -public U0 BootMHDOldRead(U8 src_drive, U8 dst_drive) +public U0 BootMHDOldRead(U8 src_drive, U8 dst_drive, I64 size=1) {//Reads MBR from disk drive containing src partition. -//Writes a single block file to dst BOOT_DIR. +//Writes MBR file to dst BOOT_DIR. +// Takes optional arg 'size': count of 512-byte blocks. CBlkDev *bd = Letter2BlkDev(src_drive); CDrive *drive; - CMasterBoot mbr; + U8 *mbr = MAlloc(BLK_SIZE * size); Drive(dst_drive); drive = Fs->cur_dv; @@ -28,28 +29,30 @@ public U0 BootMHDOldRead(U8 src_drive, U8 dst_drive) { //Bypass partition bounds-checking BlkDevLock(bd); - AHCIAtaBlksRead(bd, &mbr, 0, 1); + AHCIAtaBlksRead(bd, mbr, 0, size); BlkDevUnlock(bd); Drive(dst_drive); DirMake(BOOT_DIR); - FileWrite(BOOT_DIR_OLDMBR_BIN, &mbr, BLK_SIZE); + FileWrite(BOOT_DIR_OLDMBR_BIN, mbr, size * BLK_SIZE); } } public U0 BootMHDOldWrite(U8 src_drive, U8 dst_drive) {//Reads OldMBR from src drive BOOT_DIR. //writes it to the MBR of the drive with dst partition. +// If OldMBR.BIN size > BLK_SIZE, writes to post-MBR gap. CBlkDev *bd = Letter2BlkDev(dst_drive); CMasterBoot *mbr; + I64 size; Drive(src_drive); - if (mbr = FileRead(BOOT_DIR_OLDMBR_BIN)) + if (mbr = FileRead(BOOT_DIR_OLDMBR_BIN, &size)) { //Bypass partition bounds-checking BlkDevLock(bd); - AHCIAtaBlksWrite(bd, mbr, 0, 1); + AHCIAtaBlksWrite(bd, mbr, 0, size / BLK_SIZE); BlkDevUnlock(bd); } Free(mbr); @@ -117,10 +120,13 @@ public Bool BootMHDIns(U8 drv_let, U8 *drv_list=NULL) StrPrint(menu_ptr, "\n\r\n\rZealOS Boot Loader\n\r\n\r"); j = 0; + "\nDetected boot drives:\n"; + "(Choice %16s)\n", "drv_offset"; if (FileFind(BOOT_DIR_OLDMBR_BIN, &de, FUF_JUST_FILES)) { Free(de.full_name); *_q++ = Clus2Blk(drive, de.clus); + "Old Boot Record\n"; CatPrint(menu_ptr, "0. Old Boot Record\n\r"); j++; } @@ -173,6 +179,7 @@ public Bool BootMHDIns(U8 drv_let, U8 *drv_list=NULL) res = TRUE; } } + "\nZealOS Public Domain HDD MBR Boot Loader installed.\n\n"; } catch PutExcept; diff --git a/src/System/Boot/LimineMHDIns.ZC b/src/System/Boot/LimineMHDIns.ZC new file mode 100755 index 00000000..714cafe4 --- /dev/null +++ b/src/System/Boot/LimineMHDIns.ZC @@ -0,0 +1,118 @@ + +class CLimineStage2Header +{ + U16 size_a; + U16 size_b; + U64 location_a; + U64 location_b; +}; + +#ifndef binary_limine_hdd_bin_data +U8 binary_limine_hdd_bin_data[0]; +#endif + +Bool LimineCFGMake(U8 drv_let) +{ + U8 *filename_cfg = MStrPrint("%C:/Boot/Limine.CFG", drv_let); + CDoc *doc = DocNew(filename_cfg); + CDrive *drive; + CBlkDev *bd; + I64 i; + U8 *filename_sys, *filename_elf, *filename_zxe, *st; + + "\nGenerating Limine.CFG ...\n"; + + DocPrint(doc, + "TIMEOUT=2\n" + "INTERFACE_RESOLUTION=1024x768\n\n"); + + "Searching drives for Limine bootloader files ...\n"; + for (i = 0, drive = blkdev.drvs; i < DRIVES_NUM; i++, drive++) + { + if (drive->drive_signature == DRIVE_SIGNATURE_VAL && drive->fs_type == FSt_FAT32 && DriveIsWritable(drive->drv_let)) + { + bd = drive->bd; + drv_let = Drive2Letter(drive); + + filename_sys = MStrPrint("%C:/Boot/Limine.SYS", drv_let); + filename_elf = MStrPrint("%C:/Boot/ZealBooter.ELF", drv_let); + filename_zxe = MStrPrint("%C:/Boot/Kernel.ZXE", drv_let); + if (FileFind(filename_sys) && FileFind(filename_elf) && FileFind(filename_zxe)) + { + st = MStrPrint(":ZealOS %C:/\n" + "PROTOCOL=limine\n" + "RESOLUTION=1024x768\n" + "KERNEL_PATH=boot://%d/Boot/ZealBooter.ELF\n" + "MODULE_PATH=boot://%d/Boot/Kernel.ZXE\n" + "\n", drv_let, drive->prt_num + 1, drive->prt_num + 1); + + DocPrint(doc, st); + "%C:/ drive added as a Limine.CFG menu entry.\n", drv_let; + } + else + "%C:/ drive is missing Limine bootloader files.\n", drv_let; + } + } + DocWrite(doc); + DocDel(doc); + + "/Boot/Limine.CFG generated.\n"; + + "Copying Limine.CFG to all other drives ...\n"; + for (i = 0, drive = blkdev.drvs; i < DRIVES_NUM; i++, drive++) + { + if (drive->drive_signature == DRIVE_SIGNATURE_VAL && drive->fs_type == FSt_FAT32 && DriveIsWritable(drive->drv_let)) + { + drv_let = Drive2Letter(drive); + if (FileFind(filename_sys) && FileFind(filename_elf) && FileFind(filename_zxe)) + { + st = MStrPrint("%C:/Boot/Limine.CFG", drv_let); + Copy(filename_cfg, st); + } + } + } + + return TRUE; +} + +Bool LimineMHDIns(U8 drv_let) +{ + U8 *limine = binary_limine_hdd_bin_data; + U16 limine_size = sizeof(binary_limine_hdd_bin_data); + CLimineStage2Header *limine_stage2 = limine + 0x1A4; + U16 limine_stage2_size = limine_size - BLK_SIZE; + U16 limine_stage2_size_aligned = limine_stage2_size + ((BLK_SIZE * 2) - limine_stage2_size % (BLK_SIZE * 2)); + CBlkDev *bd = Letter2BlkDev(drv_let); + CMasterBoot old_mbr, *new_mbr = limine; + + if (limine_size == 0) + { + "\n" ST_ERR_ST "Limine HDD MBR binary bytes not found. Must first #include it, then recompile this file.\n"; + return FALSE; + } + + '\n'; + + limine_stage2->size_a = limine_stage2->size_b = limine_stage2_size_aligned / 2; + limine_stage2->location_a = BLK_SIZE; + limine_stage2->location_b = BLK_SIZE + limine_stage2->size_a; + + BlkDevLock(bd); + + AHCIAtaBlksRead(bd, &old_mbr, 0, 1); // read old MBR currently on disk + MemCopy(new_mbr->p, old_mbr.p, sizeof(CMasterBoot.p)); // copy old MBR partition table to new Limine MBR + + // read the whole MBR + post-MBR-gap that Limine wants to overwrite, save all of that as an OldMBR.BIN + BootMHDOldRead(drv_let, drv_let, 1 + (limine_stage2_size_aligned / BLK_SIZE)); + + AHCIAtaBlksWrite(bd, limine, 0, 1 + (limine_stage2_size_aligned / BLK_SIZE)); // write Limine to MBR and post-MBR gap + + BlkDevUnlock(bd); + + LimineCFGMake(drv_let); + + "\nLimine BSD2-licensed HDD MBR Boot Loader installed.\n\n"; + + return TRUE; + +} diff --git a/src/System/Define.ZC b/src/System/Define.ZC index 7a4e1022..3130a724 100755 --- a/src/System/Define.ZC +++ b/src/System/Define.ZC @@ -15,8 +15,8 @@ U0 LoadDocDefines() //$LK,"DD_BOOT_HIGH_LOC_DVD",A="FF:::/System/Boot/BootDVD.ZC,DD_BOOT_HIGH_LOC_DVD"$ $TR,"LineRep"$ -$ID,2$DefinePrint("DD_ZEALOS_LOC","98,216"); -$ID,-2$ +$ID,2$DefinePrint("DD_ZEALOS_LOC","98,675"); +$ID,-2$ DefinePrint("DD_MP_VECT", "%08X", MP_VECT_ADDR); DefinePrint("DD_MP_VECT_END", "%08X", MP_VECT_ADDR + COREAP_16BIT_INIT_END - COREAP_16BIT_INIT - 1); diff --git a/src/System/DevInfo.ZC b/src/System/DevInfo.ZC index 0f322e50..b401be15 100755 --- a/src/System/DevInfo.ZC +++ b/src/System/DevInfo.ZC @@ -1,136 +1,5 @@ #help_index "PCI;Processor;Devices;Info" -//The file was downloaded from -//http://www.pcidatabase.com/reports.php?type=tab-delimeted - -#define PCI_DEV_FILE "::/Misc/PCIDevices.DD" - -/**** -//1) Download http://www.pcidatabase.com/reports.php?type=tab-delimeted -//2) Rename to ::/Misc/PCIDevices.DD -//3) ToDolDoc("::/Misc/PCIDevices.DD"); -//4) Edit and remove file header and tail -//5) Text find-and-replace "=0A=" with "". (Doesn't seem necessary anmore.) -//6) Run PCIDevFileGen(). (Doesn't seem necessary anmore.) - -public U0 PCIDevFileGen() -{ - Bool first=TRUE,del=FALSE,del2=FALSE,cont=FALSE; - CDoc *doc=DocRead(PCI_DEV_FILE, - DOCF_PLAIN_TEXT|DOCF_DBL_DOLLARS|DOCF_NO_CURSOR); - CDocEntry *doc_e=doc->head.next,*doc_e2; - while (doc_e!=doc) { - doc_e2=doc_e->next; - if (first) { - if (doc_e->type_u8==DOCT_TEXT) { - if (doc_e->tag[0]==';') - del=TRUE; - } - first=FALSE; - } - if (doc_e->type_u8==DOCT_TEXT && doc_e->tag[StrLen(doc_e->tag)-1]=='=' && - doc_e2->type_u8==DOCT_NEW_LINE) { - doc_e->tag[StrLen(doc_e->tag)-1]=CH_SPACE; - cont=TRUE; - } - del2=del; - if (doc_e->type_u8==DOCT_NEW_LINE) { - first=TRUE; - del2=FALSE; - if (cont) { - del=TRUE; - cont=FALSE; - } - } - if (del) - DocEntryDel(doc,doc_e); - del=del2; - doc_e=doc_e2; - } - DocWrite(doc); -} -****/ - -//$LK,"::/Misc/PCIDevices.DD",A="PI:::/Misc/PCIDevices.DD"$ -U0 PCILookUpSingle(CDoc *doc, I64 m, I64 d, U8 **_vendor, U8 **_dev) -{ - Bool first = TRUE; - U8 buf[8], *vendor = NULL, *dev = NULL; - CDocEntry *doc_e = doc->head.next; - - while (doc_e != doc) - { - if (first) - { - if (doc_e->type_u8 == DOCT_TEXT && doc_e->tag[0] != ';' && StrLen(doc_e->tag) >= 4) - { - buf[0](U16) = '0x'; - buf[2](U32) = doc_e->tag(U32 *)[0]; - buf[6] = '\0'; - if (Str2I64(buf) == m) - { - doc_e = doc_e->next->next->next; - if (doc_e->type_u8 == DOCT_TEXT) - { - vendor = SysStrNew(doc_e->tag); - first = FALSE; - break; - } - } - } - first=FALSE; - } - if (doc_e->type_u8 == DOCT_NEW_LINE) - first = TRUE; - doc_e = doc_e->next; - } - - if (vendor) - { - while (doc_e != doc) - { - if (first) - { - if (doc_e->type_u8 == DOCT_TAB) - { - doc_e = doc_e->next->next->next->next; - if (doc_e->type_u8 == DOCT_TEXT && StrLen(doc_e->tag) >= 4) - { - buf[0](U16) = '0x'; - buf[2](U32) = doc_e->tag(U32 *)[0]; - buf[6] = '\0'; - if (Str2I64(buf) == d) - { - doc_e = doc_e->next->next->next; - if (doc_e->type_u8 == DOCT_TEXT) - { - dev = SysStrNew(doc_e->tag); - break; - } - } - } - } - else - break; - first = FALSE; - } - if (doc_e->type_u8 == DOCT_NEW_LINE) - first = TRUE; - doc_e = doc_e->next; - } - } - - if (vendor) - *_vendor = vendor; - else - *_vendor = SysStrNew("Unknown"); - - if (dev) - *_dev = dev; - else - *_dev = SysStrNew("Unknown"); -} - U0 PCILookUpDevs() { CPCIDev *tmppci; @@ -253,11 +122,11 @@ public U0 MemBIOSRep() "FEE00000-FEE00FFF See $LK,"APIC",A="MN:LAPIC_BASE"$\n\n"; if (!IsRaw) - "$$PURPLE$$VBE Linear Framebuffer$$FG$$\n"; + "$$PURPLE$$Linear Framebuffer$$FG$$\n"; else - "VBE Linear Framebuffer\n"; + "Linear Framebuffer\n"; - "%08X-%08X See $LK,"VBE Mode",A="FF:::/Kernel/KernelA.HH,framebuffer"$\n", text.fb_alias, text.fb_alias(U8 *) + text.buffer_size - 1; + "%08X-%08X \n", text.fb_alias, text.fb_alias(U8 *) + text.buffer_size - 1; if (!IsRaw) "\n$$PURPLE$$32 Bit Device Mem$$FG$$\n"; diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index 07dc2bc3..ed308a54 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -47,9 +47,9 @@ public CBGR24 gr_palette[COLORS_NUM]; //See $LK,"SysGrInit",A="MN:SysGrInit"$() //Allows consts to be used instead of variables. HashPublic("GR_WIDTH", HTT_DEFINE_STR);; -DefinePrint("GR_WIDTH", "%d", sys_vbe_mode.width); +DefinePrint("GR_WIDTH", "%d", sys_framebuffer_width); HashPublic("GR_HEIGHT", HTT_DEFINE_STR);; -DefinePrint("GR_HEIGHT", "%d", sys_vbe_mode.height); +DefinePrint("GR_HEIGHT", "%d", sys_framebuffer_height); #help_index "Char;TextBase Layer/Char" DefinePrint("TEXT_ROWS", "%d", text.rows);; diff --git a/src/System/Gr/GrInitB.ZC b/src/System/Gr/GrInitB.ZC index 58e9cd29..484101e8 100755 --- a/src/System/Gr/GrInitB.ZC +++ b/src/System/Gr/GrInitB.ZC @@ -187,7 +187,7 @@ U0 GrInit2() gr.to_8_bits = MAlloc(256 * sizeof(I64)); gr.to_8_colors = MAlloc(256 * sizeof(I64)); - gr.screen_cache = MAlloc(sys_vbe_mode.width * sys_vbe_mode.height); + gr.screen_cache = MAlloc(sys_framebuffer_width * sys_framebuffer_height); gr.text_base = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.win_uncovered_bitmap = CAlloc(65536 / 8); diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index 84310bdb..75ea2c50 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -20,7 +20,7 @@ public CBGR24 gr32_palette_std[COLORS_NUM] = { }; public U0 PaletteSetStd(Bool persistent=TRUE) -{//Activate std palette. +{//Activate standard palette. GrPaletteSet(gr32_palette_std); LFBFlush; if (persistent) @@ -80,11 +80,11 @@ public U0 PaletteSetSlate(Bool persistent=TRUE) } //******************************************************************************** public CBGR24 gr_palette_commander[COLORS_NUM] = { - 0xFFFFFF, 0x867ADE, 0x00CC55, 0x5A878B, 0xEE0000, 0xCC44CC, 0xDD8855, 0xBBBBBB, - 0x777777, 0x009BFF, 0xAAFF66, 0xAAFFEE, 0xFF7777, 0xCA94E8, 0xEEEE77, 0x483AAA + 0xFFFFFF, 0x867ADE, 0x00CC55, 0x5A878B, 0xFF0000, 0xCC44CC, 0xDD8855, 0xE1E1E2, + 0x777777, 0x009BFF, 0xAAFF66, 0xAAFFEE, 0xFF7777, 0xCA94E8, 0xEEEE77, 0x483AA7 }; public U0 PaletteSetCommander(Bool persistent=TRUE) -{//Activate Slate palette. +{//Activate Commander palette. GrPaletteSet(gr_palette_commander); LFBFlush; if (persistent) diff --git a/src/System/MakeSystem.ZC b/src/System/MakeSystem.ZC index 343a072a..c62ccd7d 100755 --- a/src/System/MakeSystem.ZC +++ b/src/System/MakeSystem.ZC @@ -20,6 +20,7 @@ LBts(&sys_run_level, RLf_DOC); #include "God/MakeGod" #include "Hash" #include "TaskSettings" +#include "PCILookUpSingle" #include "DevInfo" #include "Define" #include "WallPaper" diff --git a/src/System/PCILookUpSingle.ZC b/src/System/PCILookUpSingle.ZC new file mode 100755 index 00000000..44787838 --- /dev/null +++ b/src/System/PCILookUpSingle.ZC @@ -0,0 +1,136 @@ +#help_index "PCI;Processor;Devices;Info" + +// PCILookUpSingle has been moved to its own file +// to make it simpler to update for modern PCI device lists. +// https://www.github.com/Zeal-Operating-System/PCIDeviceList + +//The file was downloaded from +//http://www.pcidatabase.com/reports.php?type=tab-delimeted + +#define PCI_DEV_FILE "::/Misc/PCIDevices.DD" + +/**** +//1) Download http://www.pcidatabase.com/reports.php?type=tab-delimeted +//2) Rename to ::/Misc/PCIDevices.DD +//3) ToDolDoc("::/Misc/PCIDevices.DD"); +//4) Edit and remove file header and tail +//5) Text find-and-replace "=0A=" with "". (Doesn't seem necessary anmore.) +//6) Run PCIDevFileGen(). (Doesn't seem necessary anmore.) + +public U0 PCIDevFileGen() +{ + Bool first=TRUE,del=FALSE,del2=FALSE,cont=FALSE; + CDoc *doc=DocRead(PCI_DEV_FILE, + DOCF_PLAIN_TEXT|DOCF_DBL_DOLLARS|DOCF_NO_CURSOR); + CDocEntry *doc_e=doc->head.next,*doc_e2; + while (doc_e!=doc) { + doc_e2=doc_e->next; + if (first) { + if (doc_e->type_u8==DOCT_TEXT) { + if (doc_e->tag[0]==';') + del=TRUE; + } + first=FALSE; + } + if (doc_e->type_u8==DOCT_TEXT && doc_e->tag[StrLen(doc_e->tag)-1]=='=' && + doc_e2->type_u8==DOCT_NEW_LINE) { + doc_e->tag[StrLen(doc_e->tag)-1]=CH_SPACE; + cont=TRUE; + } + del2=del; + if (doc_e->type_u8==DOCT_NEW_LINE) { + first=TRUE; + del2=FALSE; + if (cont) { + del=TRUE; + cont=FALSE; + } + } + if (del) + DocEntryDel(doc,doc_e); + del=del2; + doc_e=doc_e2; + } + DocWrite(doc); +} +****/ + +//$LK,"::/Misc/PCIDevices.DD",A="PI:::/Misc/PCIDevices.DD"$ +U0 PCILookUpSingle(CDoc *doc, I64 m, I64 d, U8 **_vendor, U8 **_dev) +{ + Bool first = TRUE; + U8 buf[8], *vendor = NULL, *dev = NULL; + CDocEntry *doc_e = doc->head.next; + + while (doc_e != doc) + { + if (first) + { + if (doc_e->type_u8 == DOCT_TEXT && doc_e->tag[0] != ';' && StrLen(doc_e->tag) >= 4) + { + buf[0](U16) = '0x'; + buf[2](U32) = doc_e->tag(U32 *)[0]; + buf[6] = '\0'; + if (Str2I64(buf) == m) + { + doc_e = doc_e->next->next->next; + if (doc_e->type_u8 == DOCT_TEXT) + { + vendor = SysStrNew(doc_e->tag); + first = FALSE; + break; + } + } + } + first=FALSE; + } + if (doc_e->type_u8 == DOCT_NEW_LINE) + first = TRUE; + doc_e = doc_e->next; + } + + if (vendor) + { + while (doc_e != doc) + { + if (first) + { + if (doc_e->type_u8 == DOCT_TAB) + { + doc_e = doc_e->next->next->next->next; + if (doc_e->type_u8 == DOCT_TEXT && StrLen(doc_e->tag) >= 4) + { + buf[0](U16) = '0x'; + buf[2](U32) = doc_e->tag(U32 *)[0]; + buf[6] = '\0'; + if (Str2I64(buf) == d) + { + doc_e = doc_e->next->next->next; + if (doc_e->type_u8 == DOCT_TEXT) + { + dev = SysStrNew(doc_e->tag); + break; + } + } + } + } + else + break; + first = FALSE; + } + if (doc_e->type_u8 == DOCT_NEW_LINE) + first = TRUE; + doc_e = doc_e->next; + } + } + + if (vendor) + *_vendor = vendor; + else + *_vendor = SysStrNew("Unknown"); + + if (dev) + *_dev = dev; + else + *_dev = SysStrNew("Unknown"); +} diff --git a/src/System/Utils/Diff.ZC b/src/System/Utils/Diff.ZC index 75f751d4..3b096f1d 100755 --- a/src/System/Utils/Diff.ZC +++ b/src/System/Utils/Diff.ZC @@ -36,6 +36,7 @@ I64 DiffEntriesCompare(CDocEntry *doc_e1, CDocEntry *doc_e2) #define DF_ABORT_FILE 0x10 #define DF_ABORT_ALL_FILES 0x20 #define DF_NO_MORE_PROMPTS_THIS_FILE 0x40 +#define DF_KEEP_FLAGS 0x80 // tells Diff NOT to &= with abort-all flag at call start U0 DiffSel(CDoc *doc, I64 *_df_flags, I64 j1_lo, I64 j1_hi, I64 j2_lo, I64 j2_hi, I64 count1, I64 count2, CDocEntry **doc_unsorted1, CDocEntry **doc_unsorted2) @@ -181,7 +182,13 @@ Bool DiffSub(CDoc *doc, I64 *_df_flags, I64 j1_lo, I64 j1_hi, I64 j2_lo, I64 j2_ i2++; else { - i = StrCompare(doc_sorted1[i1]->tag, doc_sorted2[i2]->tag); + if (!CheckPtr(doc_sorted1[i1]) || !CheckPtr(doc_sorted2[i2]) || !CheckPtr(doc_sorted1[i1]->tag) || !CheckPtr(doc_sorted2[i2]->tag)) + { + RawPrint(200, "DiffSub PANIC DEBUG FIXME: %X %X %X %X\n", doc_sorted1[i1], doc_sorted2[i2], doc_sorted1[i1]->tag, doc_sorted2[i2]->tag); + i = 1; // ??? + } + else + i = StrCompare(doc_sorted1[i1]->tag, doc_sorted2[i2]->tag); if (i > 0) i2++; else if (i < 0) @@ -270,7 +277,9 @@ public Bool Diff(U8 *dst_file, U8 *src_file, I64 *_df_flags=NULL) df_flags = *_df_flags; else df_flags = 0; - df_flags &= DF_ABORT_ALL_FILES; + + if (!(df_flags & DF_KEEP_FLAGS)) + df_flags &= DF_ABORT_ALL_FILES; doc_e = doc1->head.next; while (doc_e != doc1) diff --git a/src/System/Utils/SysRep.ZC b/src/System/Utils/SysRep.ZC index 09f70026..d6bf571e 100755 --- a/src/System/Utils/SysRep.ZC +++ b/src/System/Utils/SysRep.ZC @@ -660,6 +660,12 @@ Bool SMBIOSEntryScan(CSMBIOSEntryPoint **entry) I64 i; U8 noreg checksum = 0, *mem = 0xF0000; + if (sys_smbios_entry) + { + *entry = sys_smbios_entry; + return TRUE; + } + do { if (!MemCompare(mem, "_SM_", 4)) diff --git a/src/System/Utils/VideoRep.ZC b/src/System/Utils/VideoRep.ZC index 94d417a9..dff3b699 100755 --- a/src/System/Utils/VideoRep.ZC +++ b/src/System/Utils/VideoRep.ZC @@ -1,66 +1,68 @@ -public I64 VideoRep(Bool full=TRUE) -{//List available VBE modes as indicated by the BIOS. Show current mode; - I64 i, mode_count = 0; - CVBEModeShort *mode; - if (full) - { - "\nVBE Version %X.%X\n\n", sys_vbe_info.version.u8[1], sys_vbe_info.version.u8[0]; - if (!IsRaw) - { - "$$PURPLE$$Manufacturer $$FG$$: $$BLACK$$%s$$FG$$\n", sys_vbe_info.oem; - "$$PURPLE$$Vendor name $$FG$$: $$BLACK$$%s$$FG$$\n", sys_vbe_info.vendor; - "$$PURPLE$$Product name $$FG$$: $$BLACK$$%s$$FG$$\n", sys_vbe_info.product_name; - "$$PURPLE$$Product revision $$FG$$: $$BLACK$$%s$$FG$$\n", sys_vbe_info.product_revision; - "$$PURPLE$$Software revision $$FG$$: $$BLACK$$%X.%X$$FG$$\n", sys_vbe_info.software_revision.u8[1], sys_vbe_info.software_revision.u8[0]; - "$$PURPLE$$Hardware memory $$FG$$: $$BLACK$$%d MiB$$FG$$\n", sys_vbe_info.total_memory * 64 / 1024; - } - else - { - "Manufacturer : %s\n", sys_vbe_info.oem; - "Vendor name : %s\n", sys_vbe_info.vendor; - "Product name : %s\n", sys_vbe_info.product_name; - "Product revision : %s\n", sys_vbe_info.product_revision; - "Software revision : %X.%X\n", sys_vbe_info.software_revision.u8[1], sys_vbe_info.software_revision.u8[0]; - "Hardware memory : %d MiB\n", sys_vbe_info.total_memory * 64 / 1024; - } - "\n\nAll modes shown are 32-bit color.\n\n"; - } +public I64 VideoRep() +{ // List available screen resolutions, show current resolution. + I64 i, count = 0, div, aspect_w, aspect_h; + CVideoInfo *info; + + "\n"; + if (!IsRaw) + "$$PURPLE$$Framebuffer pointer: $$BLACK$$0x%8X$$FG$$ \n", sys_framebuffer_addr; + else + "Framebuffer pointer: 0x%8X \n", sys_framebuffer_addr; + + "\nAll modes shown are 32-bit color.\n\n"; if (!IsRaw) - "$$LTCYAN$$ # W x H\t\t Mode$$FG$$\n\n"; + "$$LTCYAN$$ # W x H Aspect Ratio$$FG$$\n\n"; else - " #\t\t W x H\t\t Mode\n\n"; + " #\t\t W x H Aspect Ratio\n\n"; for (i = 0; i < VBE_MODES_NUM; i++) { - mode = &sys_vbe_modes[i]; - if (mode->height) + info = &sys_framebuffer_list[i]; + if (info->height) { + // Determine aspect ratio + aspect_w = info->width; + aspect_h = info->height; + div = 2; + while (TRUE) + { + while (aspect_w % div == 0 && aspect_h % div == 0) + { + aspect_w /= div; + aspect_h /= div; + div = 2; + } + div++; + if (div >= aspect_h || div >= aspect_w) + break; + } + if (!IsRaw) "$$PURPLE$$ $$BT+X,\"%d\",LM=\"%d\\n\"$$$$FG$$$$LM,4$$", i+1, i+1; else " [%d]\t", i+1; - if (sys_vbe_mode_num == mode->mode_num) + if (info->width == sys_framebuffer_width && info->height == sys_framebuffer_height) { if (!IsRaw) - "$$RED$$%4d x %4d 0x%X (Current mode)$$FG$$$$LM,0$$", mode->width, mode->height, mode->mode_num; + "$$RED$$%4d x %4d %0.3f =%4d:%d (Current resolution)$$FG$$$$LM,0$$", info->width, info->height, aspect_w / ToF64(aspect_h), aspect_w, aspect_h; else - "%4d x %4d 0x%X (Current mode)", mode->width, mode->height, mode->mode_num; + "%4d x %4d %0.3f =%4d:%d (Current resolution)", info->width, info->height, aspect_w / ToF64(aspect_h), aspect_w, aspect_h; } else { if (!IsRaw) - "$$BLACK$$%4d x %4d $$FG$$0x%X$$LM,0$$", mode->width, mode->height, mode->mode_num; + "$$BLACK$$%4d x %4d$$FG$$ %0.3f =%4d:%d $$LM,0$$", info->width, info->height, aspect_w / ToF64(aspect_h), aspect_w, aspect_h; else - "%4d x %4d 0x%X", mode->width, mode->height, mode->mode_num; + "%4d x %4d %0.3f =%4d:%d ", info->width, info->height, aspect_w / ToF64(aspect_h), aspect_w, aspect_h; } "\n\n\n"; - mode_count++; + count++; } } - return mode_count; -} + return count; +} diff --git a/src/System/ZSplash.ZC b/src/System/ZSplash.ZC index 7cf5a5cb..8d13f3e7 100755 Binary files a/src/System/ZSplash.ZC and b/src/System/ZSplash.ZC differ diff --git a/zealbooter/GNUmakefile b/zealbooter/GNUmakefile new file mode 100644 index 00000000..ff39eaf3 --- /dev/null +++ b/zealbooter/GNUmakefile @@ -0,0 +1,114 @@ +# This is the name that our final kernel executable will have. +# Change as needed. +override KERNEL := zealbooter.elf + +# Convenience macro to reliably declare overridable command variables. +define DEFAULT_VAR = + ifeq ($(origin $1),default) + override $(1) := $(2) + endif + ifeq ($(origin $1),undefined) + override $(1) := $(2) + endif +endef + +# It is highly recommended to use a custom built cross toolchain to build a kernel. +# We are only using "cc" as a placeholder here. It may work by using +# the host system's toolchain, but this is not guaranteed. +$(eval $(call DEFAULT_VAR,CC,cc)) + +# Same thing for "ld" (the linker). +$(eval $(call DEFAULT_VAR,LD,ld)) + +# User controllable CFLAGS. +CFLAGS ?= -g -O2 -pipe -Wall -Wextra + +# User controllable preprocessor flags. We set none by default. +CPPFLAGS ?= + +# User controllable nasm flags. +NASMFLAGS ?= -F dwarf -g + +# User controllable linker flags. We set none by default. +LDFLAGS ?= + +# Internal C flags that should not be changed by the user. +override CFLAGS += \ + -std=gnu11 \ + -ffreestanding \ + -fno-stack-protector \ + -fno-stack-check \ + -fno-lto \ + -fno-pie \ + -fno-pic \ + -m64 \ + -march=x86-64 \ + -mabi=sysv \ + -mno-80387 \ + -mno-mmx \ + -mno-sse \ + -mno-sse2 \ + -mno-red-zone \ + -mcmodel=kernel \ + -MMD \ + -I. \ + -I./lib + +# Internal linker flags that should not be changed by the user. +override LDFLAGS += \ + -nostdlib \ + -static \ + -m elf_x86_64 \ + -z max-page-size=0x1000 \ + -T linker.ld + +# Check if the linker supports -no-pie and enable it if it does +ifeq ($(shell $(LD) --help 2>&1 | grep 'no-pie' >/dev/null 2>&1; echo $$?),0) + override LDFLAGS += -no-pie +endif + +# Internal nasm flags that should not be changed by the user. +override NASMFLAGS += \ + -f elf64 + +# Use find to glob all *.c, *.S, and *.asm files in the directory and extract the object names. +override CFILES := $(shell find . -type f -name '*.c') +override ASFILES := $(shell find . -type f -name '*.S') +override NASMFILES := $(shell find . -type f -name '*.asm') +override OBJ := $(CFILES:.c=.o) $(ASFILES:.S=.o) $(NASMFILES:.asm=.o) +override HEADER_DEPS := $(CFILES:.c=.d) $(ASFILES:.S=.d) + +# Default target. +.PHONY: all +all: $(KERNEL) + +limine.h: + curl https://raw.githubusercontent.com/limine-bootloader/limine/trunk/limine.h -o $@ || cp ../build/limine/limine.h limine.h || echo "ERROR" + +# Link rules for the final kernel executable. +$(KERNEL): $(OBJ) + $(LD) $(OBJ) $(LDFLAGS) -o $@ + +# Include header dependencies. +-include $(HEADER_DEPS) + +# Compilation rules for *.c files. +%.o: %.c limine.h + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +# Compilation rules for *.S files. +%.o: %.S limine.h + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +# Compilation rules for *.asm (nasm) files. +%.o: %.asm + nasm $(NASMFLAGS) $< -o $@ + +# Remove object files and the final executable. +.PHONY: clean +clean: + rm -rf $(KERNEL) $(OBJ) $(HEADER_DEPS) + +.PHONY: distclean +distclean: clean + rm -f limine.h diff --git a/zealbooter/Limine.CFG b/zealbooter/Limine.CFG new file mode 100755 index 00000000..f0da0dca --- /dev/null +++ b/zealbooter/Limine.CFG @@ -0,0 +1,8 @@ +TIMEOUT=2 +INTERFACE_RESOLUTION=1024x768 + +:ZealOS LiveCD +PROTOCOL=limine +RESOLUTION=1024x768 +KERNEL_PATH=boot:///Boot/ZealBooter.ELF +MODULE_PATH=boot:///Boot/Kernel.ZXE diff --git a/zealbooter/lib.c b/zealbooter/lib.c new file mode 100644 index 00000000..5ec0a60b --- /dev/null +++ b/zealbooter/lib.c @@ -0,0 +1,13 @@ +#include +#include + +uint64_t div_roundup_u64(uint64_t a, uint64_t b) +{ + return (a + (b - 1)) / b; +} + +uint64_t align_up_u64(uint64_t a, uint64_t b) +{ + return div_roundup_u64(a, b) * b; +} + diff --git a/zealbooter/lib.h b/zealbooter/lib.h new file mode 100644 index 00000000..b8b407fb --- /dev/null +++ b/zealbooter/lib.h @@ -0,0 +1,21 @@ +#ifndef __LIB_H__ +#define __LIB_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint64_t div_roundup_u64(uint64_t a, uint64_t b); +uint64_t align_up_u64(uint64_t a, uint64_t b); + +typedef char symbol[]; + +#endif // __LIB_H__ diff --git a/zealbooter/lib/memcmp.c b/zealbooter/lib/memcmp.c new file mode 100644 index 00000000..dd406ae2 --- /dev/null +++ b/zealbooter/lib/memcmp.c @@ -0,0 +1,26 @@ +/* memcmp( const void *, const void *, size_t ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + + while (n--) + { + if (*p1 != *p2) + { + return *p1 - *p2; + } + + ++p1; + ++p2; + } + + return 0; +} + diff --git a/zealbooter/lib/memcmp.h b/zealbooter/lib/memcmp.h new file mode 100644 index 00000000..3bbc4ca7 --- /dev/null +++ b/zealbooter/lib/memcmp.h @@ -0,0 +1,6 @@ +#ifndef __MEMCMP_H__ +#define __MEMCMP_H__ + +int memcmp(const void *s1, const void *s2, size_t n); + +#endif // __MEMCMP_H__ diff --git a/zealbooter/lib/memcpy.c b/zealbooter/lib/memcpy.c new file mode 100644 index 00000000..6584eb0a --- /dev/null +++ b/zealbooter/lib/memcpy.c @@ -0,0 +1,21 @@ +/* memcpy( void *, const void *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +void *memcpy(void *s1, const void *s2, size_t n) +{ + char *dest = (char *)s1; + const char *src = (const char *)s2; + + while (n--) + { + *dest++ = *src++; + } + + return s1; +} + diff --git a/zealbooter/lib/memcpy.h b/zealbooter/lib/memcpy.h new file mode 100644 index 00000000..c0600149 --- /dev/null +++ b/zealbooter/lib/memcpy.h @@ -0,0 +1,8 @@ +#ifndef __MEMCPY_H__ +#define __MEMCPY_H__ + +#include + +void *memcpy(void *s1, const void *s2, size_t n); + +#endif // __MEMCPY_H__ diff --git a/zealbooter/lib/memmove.c b/zealbooter/lib/memmove.c new file mode 100644 index 00000000..040402b4 --- /dev/null +++ b/zealbooter/lib/memmove.c @@ -0,0 +1,33 @@ +/* memmove( void *, const void *, size_t ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +void *memmove(void *s1, const void *s2, size_t n) +{ + char *dest = (char *)s1; + const char *src = (const char *)s2; + + if (dest <= src) + { + while (n--) + { + *dest++ = *src++; + } + } + else + { + src += n; + dest += n; + + while (n--) + { + *--dest = *--src; + } + } + + return s1; +} + diff --git a/zealbooter/lib/memmove.h b/zealbooter/lib/memmove.h new file mode 100644 index 00000000..80d5cba6 --- /dev/null +++ b/zealbooter/lib/memmove.h @@ -0,0 +1,6 @@ +#ifndef __MEMMOVE_H__ +#define __MEMMOVE_H__ + +void *memmove(void *s1, const void *s2, size_t n); + +#endif // __MEMMOVE_H__ diff --git a/zealbooter/lib/memset.c b/zealbooter/lib/memset.c new file mode 100644 index 00000000..cf951f09 --- /dev/null +++ b/zealbooter/lib/memset.c @@ -0,0 +1,20 @@ +/* memset( void *, int, size_t ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = (unsigned char *)s; + + while (n--) + { + *p++ = (unsigned char)c; + } + + return s; +} + + diff --git a/zealbooter/lib/memset.h b/zealbooter/lib/memset.h new file mode 100644 index 00000000..78fcb588 --- /dev/null +++ b/zealbooter/lib/memset.h @@ -0,0 +1,6 @@ +#ifndef __MEMSET_H__ +#define __MEMSET_H__ + +void *memset(void *s, int c, size_t n); + +#endif // __MEMSET_H__ diff --git a/zealbooter/lib/print.c b/zealbooter/lib/print.c new file mode 100644 index 00000000..2fbc98d6 --- /dev/null +++ b/zealbooter/lib/print.c @@ -0,0 +1,31 @@ +#define STB_SPRINTF_DECORATE(name) name +#define STB_SPRINTF_IMPLEMENTATION 1 +#define STB_SPRINTF_NOFLOAT 1 +#include +#include + +static volatile struct limine_terminal_request terminal_request = { + .id = LIMINE_TERMINAL_REQUEST, + .revision = 0 +}; + +#define PRINT_BUFFER_SIZE 8192 + +int printf(const char *format, ...) +{ + va_list args; + char buffer[PRINT_BUFFER_SIZE]; + struct limine_terminal *terminal; + size_t length; + + va_start(args, format); + + length = vsnprintf(buffer, PRINT_BUFFER_SIZE, format, args); + terminal = terminal_request.response->terminals[0]; + terminal_request.response->write(terminal, buffer, length); + + va_end(args); + + return length; +} + diff --git a/zealbooter/lib/print.h b/zealbooter/lib/print.h new file mode 100644 index 00000000..e659b694 --- /dev/null +++ b/zealbooter/lib/print.h @@ -0,0 +1,6 @@ +#ifndef __PRINT_H__ +#define __PRINT_H__ + +int printf(const char *format, ...); + +#endif // __PRINT_H__ diff --git a/zealbooter/lib/stb_sprintf.h b/zealbooter/lib/stb_sprintf.h new file mode 100644 index 00000000..f085a598 --- /dev/null +++ b/zealbooter/lib/stb_sprintf.h @@ -0,0 +1,1907 @@ +// stb_sprintf - v1.10 - public domain snprintf() implementation +// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 +// http://github.com/nothings/stb +// +// allowed types: sc uidBboXx p AaGgEef n +// lengths : hh h ll j z t I64 I32 I +// +// Contributors: +// Fabian "ryg" Giesen (reformatting) +// github:aganm (attribute format) +// +// Contributors (bugfixes): +// github:d26435 +// github:trex78 +// github:account-login +// Jari Komppa (SI suffixes) +// Rohit Nirmal +// Marcin Wojdyr +// Leonard Ritter +// Stefano Zanotti +// Adam Allison +// Arvid Gerstmann +// Markus Kolb +// +// LICENSE: +// +// See end of file for license information. + +#ifndef STB_SPRINTF_H_INCLUDE +#define STB_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int stbsp_sprintf( char * buf, char const * fmt, ... ) +int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. stbsp_snprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) +int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every STB_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least STB_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void stbsp_set_separators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#if defined(__clang__) + #if defined(__has_feature) && defined(__has_attribute) + #if __has_feature(address_sanitizer) + #if __has_attribute(__no_sanitize__) + #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) + #elif __has_attribute(__no_sanitize_address__) + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #elif __has_attribute(__no_address_safety_analysis__) + #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) + #endif + #endif + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) + #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #endif +#endif + +#ifndef STBSP__ASAN +#define STBSP__ASAN +#endif + +#ifdef STB_SPRINTF_STATIC +#define STBSP__PUBLICDEC static +#define STBSP__PUBLICDEF static STBSP__ASAN +#else +#ifdef __cplusplus +#define STBSP__PUBLICDEC extern "C" +#define STBSP__PUBLICDEF extern "C" STBSP__ASAN +#else +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF STBSP__ASAN +#endif +#endif + +#if defined(__has_attribute) + #if __has_attribute(format) + #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) + #endif +#endif + +#ifndef STBSP__ATTRIBUTE_FORMAT +#define STBSP__ATTRIBUTE_FORMAT(fmt,va) +#endif + +#ifdef _MSC_VER +#define STBSP__NOTUSED(v) (void)(v) +#else +#define STBSP__NOTUSED(v) (void)sizeof(v) +#endif + +#include // for va_arg(), va_list() +#include // size_t, ptrdiff_t + +#ifndef STB_SPRINTF_MIN +#define STB_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); + +#ifndef STB_SPRINTF_DECORATE +#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names +#endif + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); + +#endif // STB_SPRINTF_H_INCLUDE + +#ifdef STB_SPRINTF_IMPLEMENTATION + +#define stbsp__uint32 unsigned int +#define stbsp__int32 signed int + +#ifdef _MSC_VER +#define stbsp__uint64 unsigned __int64 +#define stbsp__int64 signed __int64 +#else +#define stbsp__uint64 unsigned long long +#define stbsp__int64 signed long long +#endif +#define stbsp__uint16 unsigned short + +#ifndef stbsp__uintptr +#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) +#define stbsp__uintptr stbsp__uint64 +#else +#define stbsp__uintptr stbsp__uint32 +#endif +#endif + +#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define STB_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses +#define STBSP__UNALIGNED(code) +#else +#define STBSP__UNALIGNED(code) code +#endif + +#ifndef STB_SPRINTF_NOFLOAT +// internal float utility functions +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); +#define STBSP__SPECIAL 0x7000 +#endif + +static char stbsp__period = '.'; +static char stbsp__comma = ','; +static struct +{ + short temp; // force next field to be 2-byte aligned + char pair[201]; +} stbsp__digitpair = +{ + 0, + "00010203040506070809101112131415161718192021222324" + "25262728293031323334353637383940414243444546474849" + "50515253545556575859606162636465666768697071727374" + "75767778798081828384858687888990919293949596979899" +}; + +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) +{ + stbsp__period = pperiod; + stbsp__comma = pcomma; +} + +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl & STBSP__NEGATIVE) { + sign[0] = 1; + sign[1] = '-'; + } else if (fl & STBSP__LEADINGSPACE) { + sign[0] = 1; + sign[1] = ' '; + } else if (fl & STBSP__LEADINGPLUS) { + sign[0] = 1; + sign[1] = '+'; + } +} + +static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) +{ + char const * sn = s; + + // get up to 4-byte alignment + for (;;) { + if (((stbsp__uintptr)sn & 3) == 0) + break; + + if (!limit || *sn == 0) + return (stbsp__uint32)(sn - s); + + ++sn; + --limit; + } + + // scan over 4 bytes at a time to find terminating 0 + // this will intentionally scan up to 3 bytes past the end of buffers, + // but becase it works 4B aligned, it will never cross page boundaries + // (hence the STBSP__ASAN markup; the over-read here is intentional + // and harmless) + while (limit >= 4) { + stbsp__uint32 v = *(stbsp__uint32 *)sn; + // bit hack to find if there's a 0 byte in there + if ((v - 0x01010101) & (~v) & 0x80808080UL) + break; + + sn += 4; + limit -= 4; + } + + // handle the last few characters to find actual size + while (limit && *sn) { + ++sn; + --limit; + } + + return (stbsp__uint32)(sn - s); +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) +{ + static char hex[] = "0123456789abcdefxp"; + static char hexu[] = "0123456789ABCDEFXP"; + char *bf; + char const *f; + int tlen = 0; + + bf = buf; + f = fmt; + for (;;) { + stbsp__int32 fw, pr, tz; + stbsp__uint32 fl; + + // macros for the callback buffer stuff + #define stbsp__chk_cb_bufL(bytes) \ + { \ + int len = (int)(bf - buf); \ + if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ + tlen += len; \ + if (0 == (bf = buf = callback(buf, user, len))) \ + goto done; \ + } \ + } + #define stbsp__chk_cb_buf(bytes) \ + { \ + if (callback) { \ + stbsp__chk_cb_bufL(bytes); \ + } \ + } + #define stbsp__flush_cb() \ + { \ + stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ + } // flush if there is even one byte in the buffer + #define stbsp__cb_buf_clamp(cl, v) \ + cl = v; \ + if (callback) { \ + int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ + if (cl > lg) \ + cl = lg; \ + } + + // fast copy everything up to the next % (or end of string) + for (;;) { + while (((stbsp__uintptr)f) & 3) { + schk1: + if (f[0] == '%') + goto scandd; + schk2: + if (f[0] == 0) + goto endfmt; + stbsp__chk_cb_buf(1); + *bf++ = f[0]; + ++f; + } + for (;;) { + // Check if the next 4 bytes contain %(0x25) or end of string. + // Using the 'hasless' trick: + // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord + stbsp__uint32 v, c; + v = *(stbsp__uint32 *)f; + c = (~v) & 0x80808080; + if (((v ^ 0x25252525) - 0x01010101) & c) + goto schk1; + if ((v - 0x01010101) & c) + goto schk2; + if (callback) + if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) + goto schk1; + #ifdef STB_SPRINTF_NOUNALIGNED + if(((stbsp__uintptr)bf) & 3) { + bf[0] = f[0]; + bf[1] = f[1]; + bf[2] = f[2]; + bf[3] = f[3]; + } else + #endif + { + *(stbsp__uint32 *)bf = v; + } + bf += 4; + f += 4; + } + } + scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; + pr = -1; + fl = 0; + tz = 0; + + // flags + for (;;) { + switch (f[0]) { + // if we have left justify + case '-': + fl |= STBSP__LEFTJUST; + ++f; + continue; + // if we have leading plus + case '+': + fl |= STBSP__LEADINGPLUS; + ++f; + continue; + // if we have leading space + case ' ': + fl |= STBSP__LEADINGSPACE; + ++f; + continue; + // if we have leading 0x + case '#': + fl |= STBSP__LEADING_0X; + ++f; + continue; + // if we have thousand commas + case '\'': + fl |= STBSP__TRIPLET_COMMA; + ++f; + continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl & STBSP__METRIC_SUFFIX) { + if (fl & STBSP__METRIC_1024) { + fl |= STBSP__METRIC_JEDEC; + } else { + fl |= STBSP__METRIC_1024; + } + } else { + fl |= STBSP__METRIC_SUFFIX; + } + ++f; + continue; + // if we don't want space between metric suffix and number + case '_': + fl |= STBSP__METRIC_NOSPACE; + ++f; + continue; + // if we have leading zero + case '0': + fl |= STBSP__LEADINGZERO; + ++f; + goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if (f[0] == '*') { + fw = va_arg(va, stbsp__uint32); + ++f; + } else { + while ((f[0] >= '0') && (f[0] <= '9')) { + fw = fw * 10 + f[0] - '0'; + f++; + } + } + // get the precision + if (f[0] == '.') { + ++f; + if (f[0] == '*') { + pr = va_arg(va, stbsp__uint32); + ++f; + } else { + pr = 0; + while ((f[0] >= '0') && (f[0] <= '9')) { + pr = pr * 10 + f[0] - '0'; + f++; + } + } + } + + // handle integer size overrides + switch (f[0]) { + // are we halfwidth? + case 'h': + fl |= STBSP__HALFWIDTH; + ++f; + if (f[0] == 'h') + ++f; // QUARTERWIDTH + break; + // are we 64-bit (unix style) + case 'l': + fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); + ++f; + if (f[0] == 'l') { + fl |= STBSP__INTMAX; + ++f; + } + break; + // are we 64-bit on intmax? (c99) + case 'j': + fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + case 't': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit (msft style) + case 'I': + if ((f[1] == '6') && (f[2] == '4')) { + fl |= STBSP__INTMAX; + f += 3; + } else if ((f[1] == '3') && (f[2] == '2')) { + f += 3; + } else { + fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); + ++f; + } + break; + default: break; + } + + // handle each replacement + switch (f[0]) { + #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[STBSP__NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + stbsp__uint32 l, n, cs; + stbsp__uint64 n64; +#ifndef STB_SPRINTF_NOFLOAT + double fv; +#endif + stbsp__int32 dp; + char const *sn; + + case 's': + // get the string + s = va_arg(va, char *); + if (s == 0) + s = (char *)"null"; + // get the length, limited to desired precision + // always limit to ~0u chars since our counts are 32b + l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character + s = num + STBSP__NUMSZ - 1; + *s = (char)va_arg(va, int); + l = 1; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { + int *d = va_arg(va, int *); + *d = tlen + (int)(bf - buf); + } break; + +#ifdef STB_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float +// va_arg(va, double); // eat it + (*(double*)((va->overflow_arg_area += 8, va->overflow_arg_area - 8))); + s = (char *)"No float"; + l = 8; + lead[0] = 0; + tail[0] = 0; + pr = 0; + cs = 0; + STBSP__NOTUSED(dp); + goto scopy; +#else + case 'A': // hex float + case 'a': // hex float + h = (f[0] == 'A') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) + fl |= STBSP__NEGATIVE; + + s = num + 64; + + stbsp__lead_sign(fl, lead); + + if (dp == -1023) + dp = (n64) ? -1022 : 0; + else + n64 |= (((stbsp__uint64)1) << 52); + n64 <<= (64 - 56); + if (pr < 15) + n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); +// add leading chars + +#ifdef STB_SPRINTF_MSVC_MODE + *s++ = '0'; + *s++ = 'x'; +#else + lead[1 + lead[0]] = '0'; + lead[2 + lead[0]] = 'x'; + lead[0] += 2; +#endif + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + if (pr) + *s++ = stbsp__period; + sn = s; + + // print the bits + n = pr; + if (n > 13) + n = 13; + if (pr > (stbsp__int32)n) + tz = pr - n; + pr = 0; + while (n--) { + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + } + + // print the expo + tail[1] = h[17]; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; + n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + + dp = (int)(s - sn); + l = (int)(s - (num + 64)); + s = num + 64; + cs = 1 + (3 << 24); + goto scopy; + + case 'G': // float + case 'g': // float + h = (f[0] == 'G') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; + else if (pr == 0) + pr = 1; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) + fl |= STBSP__NEGATIVE; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if (l > (stbsp__uint32)pr) + l = pr; + while ((l > 1) && (pr) && (sn[l - 1] == '0')) { + --pr; + --l; + } + + // should we use %e + if ((dp <= -4) || (dp > (stbsp__int32)n)) { + if (pr > (stbsp__int32)l) + pr = l - 1; + else if (pr) + --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g semantics for %f + if (dp > 0) { + pr = (dp < (stbsp__int32)l) ? l - dp : 0; + } else { + pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr); + } + goto dofloatfromg; + + case 'E': // float + case 'e': // float + h = (f[0] == 'E') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) + fl |= STBSP__NEGATIVE; + doexpfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + // handle leading chars + *s++ = sn[0]; + + if (pr) + *s++ = stbsp__period; + + // handle after decimal + if ((l - 1) > (stbsp__uint32)pr) + l = pr + 1; + for (n = 1; n < l; n++) + *s++ = sn[n]; + // trailing zeros + tz = pr - (l - 1); + pr = 0; + // dump expo + tail[1] = h[0xe]; + dp -= 1; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; +#ifdef STB_SPRINTF_MSVC_MODE + n = 5; +#else + n = (dp >= 100) ? 5 : 4; +#endif + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + cs = 1 + (3 << 24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va, double); + doafloat: + // do kilos + if (fl & STBSP__METRIC_SUFFIX) { + double divisor; + divisor = 1000.0f; + if (fl & STBSP__METRIC_1024) + divisor = 1024.0; + while (fl < 0x4000000) { + if ((fv < divisor) && (fv > -divisor)) + break; + fv /= divisor; + fl += 0x1000000; + } + } + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) + fl |= STBSP__NEGATIVE; + dofloatfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + + // handle the three decimal varieties + if (dp <= 0) { + stbsp__int32 i; + // handle 0.000*000xxxx + *s++ = '0'; + if (pr) + *s++ = stbsp__period; + n = -dp; + if ((stbsp__int32)n > pr) + n = pr; + i = n; + while (i) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + i -= 4; + } + while (i) { + *s++ = '0'; + --i; + } + if ((stbsp__int32)(l + n) > pr) + l = pr - n; + i = l; + while (i) { + *s++ = *sn++; + --i; + } + tz = pr - (n + l); + cs = 1 + (3 << 24); // how many tens did we write (for commas below) + } else { + cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; + if ((stbsp__uint32)dp >= l) { + // handle xxxx000*000.0 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= l) + break; + } + } + if (n < (stbsp__uint32)dp) { + n = dp - n; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (n) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --n; + } + while (n >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + n -= 4; + } + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = '0'; + --n; + } + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) { + *s++ = stbsp__period; + tz = pr; + } + } else { + // handle xxxxx.xxxx000*000 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= (stbsp__uint32)dp) + break; + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) + *s++ = stbsp__period; + if ((l - dp) > (stbsp__uint32)pr) + l = pr + dp; + while (n < l) { + *s++ = sn[n]; + ++n; + } + tz = pr - (l - dp); + } + } + pr = 0; + + // handle k,m,g,t + if (fl & STBSP__METRIC_SUFFIX) { + char idx; + idx = 1; + if (fl & STBSP__METRIC_NOSPACE) + idx = 0; + tail[0] = idx; + tail[1] = ' '; + { + if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl & STBSP__METRIC_1024) + tail[idx + 1] = "_KMGT"[fl >> 24]; + else + tail[idx + 1] = "_kMGT"[fl >> 24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { + tail[idx + 1] = 'i'; + idx++; + } + tail[0] = idx; + } + } + }; + + flt_lead: + // get the length that we copied + l = (stbsp__uint32)(s - (num + 64)); + s = num + 64; + goto scopy; +#endif + + case 'B': // upper binary + case 'b': // lower binary + h = (f[0] == 'B') ? hexu : hex; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[0xb]; + } + l = (8 << 4) | (1 << 8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 1; + lead[1] = '0'; + } + l = (3 << 4) | (3 << 8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; + pr = sizeof(void *) * 2; + fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros + // fall through - to X + + case 'X': // upper hex + case 'x': // lower hex + h = (f[0] == 'X') ? hexu : hex; + l = (4 << 4) | (4 << 8); + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[16]; + } + radixnum: + // get the number + if (fl & STBSP__INTMAX) + n64 = va_arg(va, stbsp__uint64); + else + n64 = va_arg(va, stbsp__uint32); + + s = num + STBSP__NUMSZ; + dp = 0; + // clear tail, and clear leading if value is zero + tail[0] = 0; + if (n64 == 0) { + lead[0] = 0; + if (pr == 0) { + l = 0; + cs = 0; + goto scopy; + } + } + // convert to string + for (;;) { + *--s = h[n64 & ((1 << (l >> 8)) - 1)]; + n64 >>= (l >> 8); + if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) + break; + if (fl & STBSP__TRIPLET_COMMA) { + ++l; + if ((l & 15) == ((l >> 4) & 15)) { + l &= ~15; + *--s = stbsp__comma; + } + } + }; + // get the tens and the comma pos + cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if (fl & STBSP__INTMAX) { + stbsp__int64 i64 = va_arg(va, stbsp__int64); + n64 = (stbsp__uint64)i64; + if ((f[0] != 'u') && (i64 < 0)) { + n64 = (stbsp__uint64)-i64; + fl |= STBSP__NEGATIVE; + } + } else { + stbsp__int32 i = va_arg(va, stbsp__int32); + n64 = (stbsp__uint32)i; + if ((f[0] != 'u') && (i < 0)) { + n64 = (stbsp__uint32)-i; + fl |= STBSP__NEGATIVE; + } + } + +#ifndef STB_SPRINTF_NOFLOAT + if (fl & STBSP__METRIC_SUFFIX) { + if (n64 < 1024) + pr = 0; + else if (pr == -1) + pr = 1; + fv = (double)(stbsp__int64)n64; + goto doafloat; + } +#endif + + // convert to string + s = num + STBSP__NUMSZ; + l = 0; + + for (;;) { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char *o = s - 8; + if (n64 >= 100000000) { + n = (stbsp__uint32)(n64 % 100000000); + n64 /= 100000000; + } else { + n = (stbsp__uint32)n64; + n64 = 0; + } + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + do { + s -= 2; + *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + } while (n); + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = (char)(n % 10) + '0'; + n /= 10; + } + } + if (n64 == 0) { + if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) + ++s; + break; + } + while (s != o) + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = '0'; + } + } + + tail[0] = 0; + stbsp__lead_sign(fl, lead); + + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + if (l == 0) { + *--s = '0'; + l = 1; + } + cs = l + (3 << 24); + if (pr < 0) + pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr < (stbsp__int32)l) + pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw < (stbsp__int32)n) + fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ((fl & STBSP__LEFTJUST) == 0) { + if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr + { + pr = (fw > pr) ? fw : pr; + fw = 0; + } else { + fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw + pr) { + stbsp__int32 i; + stbsp__uint32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ((fl & STBSP__LEFTJUST) == 0) + while (fw > 0) { + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = ' '; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leader + sn = lead + 1; + while (lead[0]) { + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leading zeros + c = cs >> 24; + cs &= 0xffffff; + cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; + while (pr > 0) { + stbsp__cb_buf_clamp(i, pr); + pr -= i; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + } + while (i) { + if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { + cs = 0; + *bf++ = stbsp__comma; + } else + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + } + + // copy leader if there is still one + sn = lead + 1; + while (lead[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy the string + n = l; + while (n) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, n); + n -= i; + STBSP__UNALIGNED(while (i >= 4) { + *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; + bf += 4; + s += 4; + i -= 4; + }) + while (i) { + *bf++ = *s++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy trailing zeros + while (tz) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tz); + tz -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy tail if there is one + sn = tail + 1; + while (tail[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tail[0]); + tail[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // handle the left justify + if (fl & STBSP__LEFTJUST) + if (fw > 0) { + while (fw) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i--) + *bf++ = ' '; + stbsp__chk_cb_buf(1); + } + } + break; + + default: // unknown, just copy code + s = num + STBSP__NUMSZ - 1; + *s = f[0]; + l = 1; + fw = fl = 0; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + } + ++f; + } +endfmt: + + if (!callback) + *bf = 0; + else + stbsp__flush_cb(); + +done: + return tlen + (int)(bf - buf); +} + +// cleanup +#undef STBSP__LEFTJUST +#undef STBSP__LEADINGPLUS +#undef STBSP__LEADINGSPACE +#undef STBSP__LEADING_0X +#undef STBSP__LEADINGZERO +#undef STBSP__INTMAX +#undef STBSP__TRIPLET_COMMA +#undef STBSP__NEGATIVE +#undef STBSP__METRIC_SUFFIX +#undef STBSP__NUMSZ +#undef stbsp__chk_cb_bufL +#undef stbsp__chk_cb_buf +#undef stbsp__flush_cb +#undef stbsp__cb_buf_clamp + +// ============================================================================ +// wrapper functions + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); + va_end(va); + return result; +} + +typedef struct stbsp__context { + char *buf; + int count; + int length; + char tmp[STB_SPRINTF_MIN]; +} stbsp__context; + +static char *stbsp__clamp_callback(const char *buf, void *user, int len) +{ + stbsp__context *c = (stbsp__context *)user; + c->length += len; + + if (len > c->count) + len = c->count; + + if (len) { + if (buf != c->buf) { + const char *s, *se; + char *d; + d = c->buf; + s = buf; + se = buf + len; + do { + *d++ = *s++; + } while (s < se); + } + c->buf += len; + c->count -= len; + } + + if (c->count <= 0) + return c->tmp; + return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can +} + +static char * stbsp__count_clamp_callback( const char * buf, void * user, int len ) +{ + stbsp__context * c = (stbsp__context*)user; + (void) sizeof(buf); + + c->length += len; + return c->tmp; // go direct into buffer if you can +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + stbsp__context c; + + if ( (count == 0) && !buf ) + { + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); + } + else + { + int l; + + c.buf = buf; + c.count = count; + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + } + + return c.length; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + + result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); + va_end(va); + + return result; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) +{ + return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); +} + +// ======================================================================= +// low level float utility functions + +#ifndef STB_SPRINTF_NOFLOAT + +// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) +#define STBSP__COPYFP(dest, src) \ + { \ + int cn; \ + for (cn = 0; cn < 8; cn++) \ + ((char *)&dest)[cn] = ((char *)&src)[cn]; \ + } + +// get float info +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) +{ + double d; + stbsp__int64 b = 0; + + // load value and round at the frac_digits + d = value; + + STBSP__COPYFP(b, d); + + *bits = b & ((((stbsp__uint64)1) << 52) - 1); + *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); + + return (stbsp__int32)((stbsp__uint64) b >> 63); +} + +static double const stbsp__bot[23] = { + 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, + 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022 +}; +static double const stbsp__negbot[22] = { + 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, + 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022 +}; +static double const stbsp__negboterr[22] = { + -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, + 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, + -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, + 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039 +}; +static double const stbsp__top[13] = { + 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299 +}; +static double const stbsp__negtop[13] = { + 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299 +}; +static double const stbsp__toperr[13] = { + 8388608, + 6.8601809640529717e+028, + -7.253143638152921e+052, + -4.3377296974619174e+075, + -1.5559416129466825e+098, + -3.2841562489204913e+121, + -3.7745893248228135e+144, + -1.7356668416969134e+167, + -3.8893577551088374e+190, + -9.9566444326005119e+213, + 6.3641293062232429e+236, + -5.2069140800249813e+259, + -5.2504760255204387e+282 +}; +static double const stbsp__negtoperr[13] = { + 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, + -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, + 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, + 8.0970921678014997e-317 +}; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U +}; +#define stbsp__tento19th ((stbsp__uint64)1000000000000000000) +#else +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; +#define stbsp__tento19th (1000000000000000000ULL) +#endif + +#define stbsp__ddmulthi(oh, ol, xh, yh) \ + { \ + double ahi = 0, alo, bhi = 0, blo; \ + stbsp__int64 bt; \ + oh = xh * yh; \ + STBSP__COPYFP(bt, xh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(ahi, bt); \ + alo = xh - ahi; \ + STBSP__COPYFP(bt, yh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(bhi, bt); \ + blo = yh - bhi; \ + ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ + } + +#define stbsp__ddtoS64(ob, xh, xl) \ + { \ + double ahi = 0, alo, vh, t; \ + ob = (stbsp__int64)xh; \ + vh = (double)ob; \ + ahi = (xh - vh); \ + t = (ahi - xh); \ + alo = (xh - (ahi - t)) - (vh + t); \ + ob += (stbsp__int64)(ahi + alo + xl); \ + } + +#define stbsp__ddrenorm(oh, ol) \ + { \ + double s; \ + s = oh + ol; \ + ol = ol - (s - oh); \ + oh = s; \ + } + +#define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); + +#define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); + +static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 +{ + double ph, pl; + if ((power >= 0) && (power <= 22)) { + stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); + } else { + stbsp__int32 e, et, eb; + double p2h, p2l; + + e = power; + if (power < 0) + e = -e; + et = (e * 0x2c9) >> 14; /* %23 */ + if (et > 13) + et = 13; + eb = e - (et * 23); + + ph = d; + pl = 0.0; + if (power < 0) { + if (eb) { + --eb; + stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); + stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); + ph = p2h; + pl = p2l; + } + } else { + if (eb) { + e = eb; + if (eb > 22) + eb = 22; + e -= eb; + stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); + if (e) { + stbsp__ddrenorm(ph, pl); + stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); + stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); + ph = p2h; + pl = p2l; + } + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); + ph = p2h; + pl = p2l; + } + } + } + stbsp__ddrenorm(ph, pl); + *ohi = ph; + *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) +{ + double d; + stbsp__int64 bits = 0; + stbsp__int32 expo, e, ng, tens; + + d = value; + STBSP__COPYFP(bits, d); + expo = (stbsp__int32)((bits >> 52) & 2047); + ng = (stbsp__int32)((stbsp__uint64) bits >> 63); + if (ng) + d = -d; + + if (expo == 2047) // is nan or inf? + { + *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; + *decimal_pos = STBSP__SPECIAL; + *len = 3; + return ng; + } + + if (expo == 0) // is zero or denormal + { + if (((stbsp__uint64) bits << 1) == 0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; + *len = 1; + return ng; + } + // find the right expo for denormals + { + stbsp__int64 v = ((stbsp__uint64)1) << 51; + while ((bits & v) == 0) { + --expo; + v >>= 1; + } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph, pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens = expo - 1023; + tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); + + // move the significant bits into position and stick them into an int + stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); + + // get full as much precision from double-double as possible + stbsp__ddtoS64(bits, ph, pl); + + // check if we undershot + if (((stbsp__uint64)bits) >= stbsp__tento19th) + ++tens; + } + + // now do the rounding in integer land + frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); + if ((frac_digits < 24)) { + stbsp__uint32 dg = 1; + if ((stbsp__uint64)bits >= stbsp__powten[9]) + dg = 10; + while ((stbsp__uint64)bits >= stbsp__powten[dg]) { + ++dg; + if (dg == 20) + goto noround; + } + if (frac_digits < dg) { + stbsp__uint64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ((stbsp__uint32)e >= 24) + goto noround; + r = stbsp__powten[e]; + bits = bits + (r / 2); + if ((stbsp__uint64)bits >= stbsp__powten[dg]) + ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if (bits) { + stbsp__uint32 n; + for (;;) { + if (bits <= 0xffffffff) + break; + if (bits % 1000) + goto donez; + bits /= 1000; + } + n = (stbsp__uint32)bits; + while ((n % 1000) == 0) + n /= 1000; + bits = n; + donez:; + } + + // convert to string + out += 64; + e = 0; + for (;;) { + stbsp__uint32 n; + char *o = out - 8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits >= 100000000) { + n = (stbsp__uint32)(bits % 100000000); + bits /= 100000000; + } else { + n = (stbsp__uint32)bits; + bits = 0; + } + while (n) { + out -= 2; + *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + e += 2; + } + if (bits == 0) { + if ((e) && (out[0] == '0')) { + ++out; + --e; + } + break; + } + while (out != o) { + *--out = '0'; + ++e; + } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef stbsp__ddmulthi +#undef stbsp__ddrenorm +#undef stbsp__ddmultlo +#undef stbsp__ddmultlos +#undef STBSP__SPECIAL +#undef STBSP__COPYFP + +#endif // STB_SPRINTF_NOFLOAT + +// clean up +#undef stbsp__uint16 +#undef stbsp__uint32 +#undef stbsp__int32 +#undef stbsp__uint64 +#undef stbsp__int64 +#undef STBSP__UNALIGNED + +#endif // STB_SPRINTF_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/zealbooter/lib/strcmp.c b/zealbooter/lib/strcmp.c new file mode 100644 index 00000000..6451e1d5 --- /dev/null +++ b/zealbooter/lib/strcmp.c @@ -0,0 +1,19 @@ +/* strcmp( const char *, const char * ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +int strcmp(const char *s1, const char *s2) +{ + while ((*s1) && (*s1 == *s2)) + { + ++s1; + ++s2; + } + + return (*(unsigned char *)s1 - *(unsigned char *)s2); +} + + diff --git a/zealbooter/lib/strcmp.h b/zealbooter/lib/strcmp.h new file mode 100644 index 00000000..8343f792 --- /dev/null +++ b/zealbooter/lib/strcmp.h @@ -0,0 +1,6 @@ +#ifndef __STRCMP_H__ +#define __STRCMP_H__ + +int strcmp(const char *s1, const char *s2); + +#endif // __STRCMP_H__ diff --git a/zealbooter/lib/strcpy.c b/zealbooter/lib/strcpy.c new file mode 100644 index 00000000..1f2d59ac --- /dev/null +++ b/zealbooter/lib/strcpy.c @@ -0,0 +1,19 @@ +/* strcpy( char *, const char * ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +char *strcpy(char *s1, const char *s2) +{ + char *rc = s1; + + while ((*s1++ = *s2++)) + { + /* EMPTY */ + } + + return rc; +} + diff --git a/zealbooter/lib/strcpy.h b/zealbooter/lib/strcpy.h new file mode 100644 index 00000000..6ae7ea87 --- /dev/null +++ b/zealbooter/lib/strcpy.h @@ -0,0 +1,6 @@ +#ifndef __STRCPY_H__ +#define __STRCPY_H__ + +char *strcpy(char *s1, const char *s2); + +#endif // __STRCPY_H__ diff --git a/zealbooter/lib/strlen.c b/zealbooter/lib/strlen.c new file mode 100644 index 00000000..142a435d --- /dev/null +++ b/zealbooter/lib/strlen.c @@ -0,0 +1,19 @@ +/* strlen( const char * ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +size_t strlen(const char *s) +{ + size_t rc = 0; + + while (s[rc]) + { + ++rc; + } + + return rc; +} + diff --git a/zealbooter/lib/strlen.h b/zealbooter/lib/strlen.h new file mode 100644 index 00000000..859589bd --- /dev/null +++ b/zealbooter/lib/strlen.h @@ -0,0 +1,6 @@ +#ifndef __STRLEN_H__ +#define __STRLEN_H__ + +size_t strlen(const char *s); + +#endif // __STRLEN_H__ diff --git a/zealbooter/lib/strncmp.c b/zealbooter/lib/strncmp.c new file mode 100644 index 00000000..e330938e --- /dev/null +++ b/zealbooter/lib/strncmp.c @@ -0,0 +1,26 @@ +/* strncmp( const char *, const char *, size_t ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +int strncmp(const char *s1, const char *s2, size_t n) +{ + while (n && *s1 && (*s1 == *s2)) + { + ++s1; + ++s2; + --n; + } + + if (n == 0) + { + return 0; + } + else + { + return (*(unsigned char *)s1 - *(unsigned char *)s2); + } +} + diff --git a/zealbooter/lib/strncmp.h b/zealbooter/lib/strncmp.h new file mode 100644 index 00000000..8c37ccac --- /dev/null +++ b/zealbooter/lib/strncmp.h @@ -0,0 +1,6 @@ +#ifndef __STRNCMP_H__ +#define __STRNCMP_H__ + +int strncmp(const char *s1, const char *s2, size_t n); + +#endif // __STRNCMP_H__ diff --git a/zealbooter/lib/strncpy.c b/zealbooter/lib/strncpy.c new file mode 100644 index 00000000..45248289 --- /dev/null +++ b/zealbooter/lib/strncpy.c @@ -0,0 +1,31 @@ +/* strncpy( char *, const char *, size_t ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + + +char *strncpy(char *s1, const char *s2, size_t n) +{ + char *rc = s1; + + while (n && (*s1++ = *s2++)) + { + /* Cannot do "n--" in the conditional as size_t is unsigned and we have + to check it again for >0 in the next loop below, so we must not risk + underflow. + */ + --n; + } + + /* Checking against 1 as we missed the last --n in the loop above. */ + while (n-- > 1) + { + *s1++ = '\0'; + } + + return rc; +} + + diff --git a/zealbooter/lib/strncpy.h b/zealbooter/lib/strncpy.h new file mode 100644 index 00000000..fbaf449f --- /dev/null +++ b/zealbooter/lib/strncpy.h @@ -0,0 +1,6 @@ +#ifndef __STRNCPY_H__ +#define __STRNCPY_H__ + +char *strncpy(char *s1, const char *s2, size_t n); + +#endif // __STRNCPY_H__ diff --git a/zealbooter/linker.ld b/zealbooter/linker.ld new file mode 100644 index 00000000..36452585 --- /dev/null +++ b/zealbooter/linker.ld @@ -0,0 +1,53 @@ +/* Tell the linker that we want an x86_64 ELF64 output file */ +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(i386:x86-64) + +/* We want the symbol _start to be our entry point */ +ENTRY(_start) + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ +} + +SECTIONS +{ + /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + .text : { + *(.text .text.*) + } :text + + /* Move to the next memory page for .rodata */ + . += CONSTANT(MAXPAGESIZE); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Move to the next memory page for .data */ + . += CONSTANT(MAXPAGESIZE); + + .data : { + *(.data .data.*) + } :data + + .bss : { + *(COMMON) + *(.bss .bss.*) + } :data + + /* Discard .note.* and .eh_frame since they may cause issues on some hosts. */ + /DISCARD/ : { + *(.eh_frame) + *(.note .note.*) + } +} diff --git a/zealbooter/trampoline.S b/zealbooter/trampoline.S new file mode 100644 index 00000000..62398b05 --- /dev/null +++ b/zealbooter/trampoline.S @@ -0,0 +1,51 @@ +.section .text + +.global trampoline +trampoline: + // Set new stack + mov %rdx, %rsp + + // Load GDTR + lgdt (%rcx) + + // Far jump to 32-bit compatibility mode + // AKA (set CS to CGDT.cs32) + pushq $0x30 + addq $(1f - trampoline), %rax + pushq %rax + lretq + + .code32 + 1: + + // Set all data segments to CGDT.ds + mov $0x10, %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + mov %eax, %ss + + // Disable paging + mov %cr0, %eax + btr $31, %eax + mov %eax, %cr0 + + // Disable LME and friends + mov $0xc0000080, %ecx + xor %eax, %eax + xor %edx, %edx + wrmsr + + // Set CR0 to (PE | NE) AKA SYS_START_CR0 + mov $0x11, %eax + mov %eax, %cr0 + + // Set flags to 0x02 + pushl $0x02 + popfl + + jmp *%ebx + +.global trampoline_end +trampoline_end: diff --git a/zealbooter/zealbooter.c b/zealbooter/zealbooter.c new file mode 100644 index 00000000..195ec3fc --- /dev/null +++ b/zealbooter/zealbooter.c @@ -0,0 +1,365 @@ +#include +#include +#include +#include +#include + +static volatile struct limine_module_request module_request = { + .id = LIMINE_MODULE_REQUEST, + .revision = 0 +}; + +static volatile struct limine_hhdm_request hhdm_request = { + .id = LIMINE_HHDM_REQUEST, + .revision = 0 +}; + +static volatile struct limine_memmap_request memmap_request = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0 +}; + +static volatile struct limine_framebuffer_request framebuffer_request = { + .id = LIMINE_FRAMEBUFFER_REQUEST, + .revision = 1 +}; + +static volatile struct limine_smbios_request smbios_request = { + .id = LIMINE_SMBIOS_REQUEST, + .revision = 0 +}; + +static volatile struct limine_efi_system_table_request efi_request = { + .id = LIMINE_EFI_SYSTEM_TABLE_REQUEST, + .revision = 0 +}; + +struct CZXE { + uint16_t jmp; + uint8_t module_align_bits; + uint8_t reserved; + uint32_t signature; + int64_t org; + int64_t patch_table_offset; + int64_t file_size; +} __attribute__((packed)); + +struct CDate { + uint32_t time; + int32_t date; +} __attribute__((packed)); + +#define MEM_E820_ENTRIES_NUM 256 + +#define MEM_E820T_USABLE 1 +#define MEM_E820T_RESERVED 2 +#define MEM_E820T_ACPI 3 +#define MEM_E820T_ACPI_NVS 4 +#define MEM_E820T_BAD_MEM 5 +#define MEM_E820T_PERM_MEM 7 + +struct CMemE820 { + uint8_t *base; + int64_t len; + uint8_t type, pad[3]; +} __attribute__((packed)); + +struct CGDTEntry { + uint64_t lo, hi; +} __attribute__((packed)); + +#define MP_PROCESSORS_NUM 128 + +struct CGDT { + struct CGDTEntry null; + struct CGDTEntry boot_ds; + struct CGDTEntry boot_cs; + struct CGDTEntry cs32; + struct CGDTEntry cs64; + struct CGDTEntry cs64_ring3; + struct CGDTEntry ds; + struct CGDTEntry ds_ring3; + struct CGDTEntry tr[MP_PROCESSORS_NUM]; + struct CGDTEntry tr_ring3[MP_PROCESSORS_NUM]; +} __attribute__((packed)); + +struct CSysLimitBase { + uint16_t limit; + uint8_t *base; +} __attribute__((packed)); + +struct CVideoInfo { + uint16_t width; + uint16_t height; +} __attribute__((packed)); + +#define VBE_MODES_NUM 32 + +#define ZEALBOOTER_LIMINE_SIGNATURE_1 0xaa23c08ed10bd4d7 +#define ZEALBOOTER_LIMINE_SIGNATURE_2 0xf6ceba7d4b74179a + +struct CKernel { + struct CZXE h; + uint32_t jmp; + uint32_t boot_src; + uint32_t boot_blk; + uint32_t boot_patch_table_base; + uint32_t sys_run_level; + struct CDate compile_time; + // U0 start + uint32_t boot_base; + uint16_t mem_E801[2]; + struct CMemE820 mem_E820[MEM_E820_ENTRIES_NUM]; + uint64_t mem_physical_space; + struct CSysLimitBase sys_gdt_ptr; + uint16_t sys_pci_buses; + struct CGDT sys_gdt __attribute__((aligned(16))); + uint64_t sys_framebuffer_addr; + uint64_t sys_framebuffer_width; + uint64_t sys_framebuffer_height; + uint64_t sys_framebuffer_pitch; + uint8_t sys_framebuffer_bpp; + uint64_t sys_smbios_entry; + uint64_t sys_disk_uuid[2]; + uint32_t sys_boot_stack; + uint8_t sys_is_uefi_booted; + struct CVideoInfo sys_framebuffer_list[VBE_MODES_NUM]; +} __attribute__((packed)); + +#define BOOT_SRC_RAM 2 +#define BOOT_SRC_HDD 3 +#define BOOT_SRC_DVD 4 +#define RLF_16BIT 0b001 +#define RLF_VESA 0b010 +#define RLF_32BIT 0b100 + +extern symbol trampoline, trampoline_end; + +struct E801 { + size_t lowermem; + size_t uppermem; +}; + +static struct E801 get_E801(void) { + struct E801 E801 = {0}; + + for (size_t i = 0; i < memmap_request.response->entry_count; i++) { + struct limine_memmap_entry *entry = memmap_request.response->entries[i]; + + if (entry->type == LIMINE_MEMMAP_USABLE) { + if (entry->base == 0x100000) { + if (entry->length > 0xf00000) { + E801.lowermem = 0x3c00; + } else { + E801.lowermem = entry->length / 1024; + } + } + if (entry->base <= 0x1000000 && entry->base + entry->length > 0x1000000) { + E801.uppermem = ((entry->length - (0x1000000 - entry->base)) / 1024) / 64; + } + } + } + + return E801; +} + +void _start(void) { + printf("ZealBooter prekernel\n"); + printf("____________________\n\n"); + + struct limine_file *module_kernel = module_request.response->modules[0]; + struct CKernel *kernel = module_kernel->address; + + const size_t trampoline_size = (uintptr_t)trampoline_end - (uintptr_t)trampoline; + const size_t boot_stack_size = 32768; + const size_t final_size = align_up_u64(module_kernel->size + trampoline_size, 16) + boot_stack_size; + + uintptr_t final_address = (uintptr_t)-1; + for (size_t i = 0; i < memmap_request.response->entry_count; i++) { + struct limine_memmap_entry *entry = memmap_request.response->entries[i]; + + if (entry->type != LIMINE_MEMMAP_USABLE) { + continue; + } + + if (entry->length >= final_size) { + final_address = entry->base; + break; + } + } + if (final_address == (uintptr_t)-1) { + printf("ERROR: could not find valid final address"); + for (;;) { asm("hlt"); } + } + + printf("final_address: 0x%X\n", final_address); + + struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0]; + kernel->sys_framebuffer_pitch = fb->pitch; + kernel->sys_framebuffer_width = fb->width; + kernel->sys_framebuffer_height = fb->height; + kernel->sys_framebuffer_bpp = fb->bpp; + kernel->sys_framebuffer_addr = (uintptr_t)fb->address - hhdm_request.response->offset; + + struct limine_video_mode *mode; + for (size_t i = 0, j = 0; i < fb->mode_count && i < VBE_MODES_NUM; i++) + { + mode = fb->modes[i]; + if (mode->bpp == 32) + { + kernel->sys_framebuffer_list[j].height = mode->height; + kernel->sys_framebuffer_list[j].width = mode->width; + j++; + } + } + + void *entry_point; // to CORE0_32BIT_INIT + for (uint64_t *p = (uint64_t *)kernel; ; p++) { + if (*p != ZEALBOOTER_LIMINE_SIGNATURE_1) { + continue; + } + p++; + if (*p != ZEALBOOTER_LIMINE_SIGNATURE_2) { + continue; + } + p++; + entry_point = p; + break; + } + + entry_point -= (uintptr_t)module_kernel->address; + entry_point += final_address; + + printf("entry_point: 0x%X\n", entry_point); + + if (module_kernel->media_type == LIMINE_MEDIA_TYPE_OPTICAL) + kernel->boot_src = BOOT_SRC_DVD; + else if (module_kernel->media_type == LIMINE_MEDIA_TYPE_GENERIC) + kernel->boot_src = BOOT_SRC_HDD; + else + kernel->boot_src = BOOT_SRC_RAM; + kernel->boot_blk = 0; + kernel->boot_patch_table_base = (uintptr_t)kernel + kernel->h.patch_table_offset; + kernel->boot_patch_table_base -= (uintptr_t)module_kernel->address; + kernel->boot_patch_table_base += final_address; + + printf("kernel->boot_patch_table_base: 0x%X\n", kernel->boot_patch_table_base); + + kernel->sys_run_level = RLF_VESA | RLF_16BIT | RLF_32BIT; + + kernel->boot_base = (uintptr_t)&kernel->jmp - (uintptr_t)module_kernel->address; + kernel->boot_base += final_address; + + printf("kernel->boot_base: 0x%X\n", kernel->boot_base); + + kernel->sys_gdt_ptr.limit = sizeof(kernel->sys_gdt) - 1; + kernel->sys_gdt_ptr.base = (void *)&kernel->sys_gdt - (uintptr_t)module_kernel->address; + kernel->sys_gdt_ptr.base += final_address; + + printf("kernel->sys_gdt_ptr.limit: 0x%X\n", kernel->sys_gdt_ptr.limit); + printf("kernel->sys_gdt_ptr.base: 0x%X\n", kernel->sys_gdt_ptr.base); + + kernel->sys_pci_buses = 256; + + struct E801 E801 = get_E801(); + kernel->mem_E801[0] = E801.lowermem; + kernel->mem_E801[1] = E801.uppermem; + + kernel->mem_physical_space = 0; + + printf("memory map:\n"); + size_t mem_count = memmap_request.response->entry_count; // MEM_E820_ENTRIES_NUM now == 256, which is also Limine's memmap entry count max + for (size_t i = 0; i < mem_count; i++) { + struct limine_memmap_entry *entry = memmap_request.response->entries[i]; + int zeal_mem_type; + + printf(" "); + switch (entry->type) { + case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: + case LIMINE_MEMMAP_KERNEL_AND_MODULES: + case LIMINE_MEMMAP_USABLE: + zeal_mem_type = MEM_E820T_USABLE; + printf(" USABLE: "); + break; + case LIMINE_MEMMAP_ACPI_RECLAIMABLE: + zeal_mem_type = MEM_E820T_ACPI; + printf(" ACPI: "); + break; + case LIMINE_MEMMAP_ACPI_NVS: + zeal_mem_type = MEM_E820T_ACPI_NVS; + printf(" NVS: "); + break; + case LIMINE_MEMMAP_BAD_MEMORY: + zeal_mem_type = MEM_E820T_BAD_MEM; + printf(" BAD: "); + break; + case LIMINE_MEMMAP_RESERVED: + default: + zeal_mem_type = MEM_E820T_RESERVED; + printf("RESERVED: "); + break; + } + + kernel->mem_E820[i].base = (void *)entry->base; + kernel->mem_E820[i].len = entry->length; + kernel->mem_E820[i].type = zeal_mem_type; + + if (kernel->mem_physical_space < entry->base + entry->length) { + kernel->mem_physical_space = entry->base + entry->length; + } + + printf("0x%08X-0x%08X", entry->base, entry->base + entry->length - 1); + + if (i % 3 == 0) + { + printf("\n"); + } + + } + printf("\n"); + + kernel->mem_E820[mem_count].type = 0; + + kernel->mem_physical_space = align_up_u64(kernel->mem_physical_space, 0x200000); + + void *sys_gdt_ptr = (void *)&kernel->sys_gdt_ptr - (uintptr_t)module_kernel->address; + sys_gdt_ptr += final_address; + + printf("sys_gdt_ptr: 0x%X\n", sys_gdt_ptr); + + void *sys_smbios_entry = smbios_request.response->entry_32; + if (sys_smbios_entry != NULL) { + kernel->sys_smbios_entry = (uintptr_t)sys_smbios_entry - hhdm_request.response->offset; + } + + memcpy(kernel->sys_disk_uuid, &module_kernel->gpt_disk_uuid, sizeof(kernel->sys_disk_uuid)); + + void *const trampoline_phys = (void *)final_address + module_kernel->size; + + printf("trampoline_phys: 0x%X\n", trampoline_phys); + + const uintptr_t boot_stack = final_address + final_size; + + printf("boot_stack: 0x%X\n", boot_stack); + + kernel->sys_boot_stack = boot_stack; + + if (efi_request.response) + { + kernel->sys_is_uefi_booted = true; + } + + memcpy(trampoline_phys, trampoline, trampoline_size); + memcpy((void *)final_address, kernel, module_kernel->size); + +// printf("\nDEBUG: halting."); for (;;); + asm volatile ( + "jmp *%0" + : + : "a"(trampoline_phys), "b"(entry_point), + "c"(sys_gdt_ptr), "d"(boot_stack), + "S"(kernel->boot_patch_table_base), "D"(kernel->boot_base) + : "memory"); + + __builtin_unreachable(); +}