├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── bcd.yml │ ├── firmware.yml │ ├── msbuild.yml │ └── wimldr.yml ├── .gitignore ├── LICENSE ├── README.md ├── emu.sln ├── emu.vcxproj ├── emu.vcxproj.filters ├── ews ├── EmbeddableWebServer.h ├── ews.c ├── ews.h ├── ews.vcxproj ├── ews.vcxproj.filters ├── main.c └── packages.config ├── firmware ├── AA64_EFI.qcow2 ├── ARM_EFI.qcow2 ├── IA32_EFI.qcow2 ├── X64_EFI.qcow2 ├── bios.qcow2 ├── wim.cpio ├── wim.qcow2 ├── wimldr ├── wimldr.aa64 ├── wimldr.ia32 └── wimldr.x64 ├── icons ├── add.png ├── admin.png ├── audio.png ├── camera.png ├── cd.png ├── close.png ├── copy.png ├── cpu.png ├── dice.png ├── dir.png ├── disk.png ├── display.png ├── down.png ├── edit.png ├── eth.png ├── firmware.png ├── floppy.png ├── halt.png ├── info.png ├── maximize.png ├── memory.png ├── minimize.png ├── network.png ├── pc.png ├── pci.png ├── qemu.png ├── refresh.png ├── remove.png ├── start.png ├── storage.png ├── usb.png ├── vm.png └── warn.png ├── include ├── cmdline.h ├── dev.h ├── gettext.h ├── ini.h ├── lodepng.h ├── nkctx.h ├── nkctx_priv.h ├── nuklear.h ├── nuklear_gdip.h ├── ui.h └── version.h ├── nuklear.ico ├── nuklear.rc ├── pack-hda.sh ├── packages.config ├── resource.h ├── src ├── cmdline.c ├── dev.c ├── gettext.c ├── ini.c ├── lodepng.c ├── main.c ├── nkctx.c ├── nkstyle.c ├── nuklear.c ├── open_dialog.c ├── ui.c ├── ui_boot.c ├── ui_cpu.c ├── ui_dev.c ├── ui_dir.c ├── ui_end.c ├── ui_fw.c ├── ui_hdb.c ├── ui_mem.c ├── ui_start.c └── wim.c ├── wimbcd └── bcd.bat ├── wimcpio ├── BCD ├── boot.sdi ├── bootmgr.exe └── wgl4_boot.ttf ├── wimhda ├── BCD ├── _.QEMU_HDA._ ├── boot.sdi ├── bootaa64.efi ├── bootia32.efi ├── bootx64.efi └── wgl4_boot.ttf └── wimldr ├── .gitignore ├── Makefile ├── assert.h ├── bios.lds ├── bootapp.h ├── byteswap.h ├── callback.S ├── cmdline.c ├── cmdline.h ├── compiler.h ├── cookie.c ├── cpio.c ├── cpio.h ├── ctype.h ├── die.c ├── efi.c ├── efi.h ├── efi.lds ├── efi ├── AArch64 │ └── ProcessorBind.h ├── Base.h ├── Guid │ ├── FileInfo.h │ ├── HiiFormMapMethodGuid.h │ ├── PcAnsi.h │ └── WinCertificate.h ├── Ia32 │ └── ProcessorBind.h ├── IndustryStandard │ ├── Acpi10.h │ ├── Acpi20.h │ ├── Acpi30.h │ ├── Acpi40.h │ ├── Acpi50.h │ ├── Acpi51.h │ ├── Acpi60.h │ ├── AcpiAml.h │ ├── Bluetooth.h │ └── PeImage.h ├── ProcessorBind.h ├── Protocol │ ├── BlockIo.h │ ├── DevicePath.h │ ├── GraphicsOutput.h │ ├── LoadedImage.h │ ├── SimpleFileSystem.h │ ├── SimpleTextIn.h │ ├── SimpleTextInEx.h │ └── SimpleTextOut.h ├── Uefi.h ├── Uefi │ ├── UefiBaseType.h │ ├── UefiGpt.h │ ├── UefiInternalFormRepresentation.h │ ├── UefiMultiPhase.h │ ├── UefiPxe.h │ └── UefiSpec.h ├── X64 │ └── ProcessorBind.h └── import.pl ├── efiblock.c ├── efiblock.h ├── efiboot.c ├── efiboot.h ├── efifile.c ├── efifile.h ├── efiguid.c ├── efimain.c ├── efipath.c ├── efipath.h ├── elf2efi.c ├── errno.h ├── huffman.c ├── huffman.h ├── int13.c ├── int13.h ├── ipxe ├── vsprintf.c └── vsprintf.h ├── lznt1.c ├── lznt1.h ├── lzx.c ├── lzx.h ├── main.c ├── memmap.c ├── memmap.h ├── paging.c ├── paging.h ├── patch.c ├── patch.h ├── pause.c ├── pause.h ├── peloader.c ├── peloader.h ├── prefix.S ├── rotate.h ├── sha1.c ├── sha1.h ├── startup.S ├── stdarg.h ├── stddef.h ├── stdint.h ├── stdio.c ├── stdio.h ├── stdlib.h ├── string.c ├── string.h ├── strings.h ├── vdisk.c ├── vdisk.h ├── vsprintf.c ├── wchar.h ├── wctype.h ├── wim.c ├── wim.h ├── wimboot.h ├── wimfile.c ├── wimfile.h ├── xca.c └── xca.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/bcd.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - "main" 8 | paths: 9 | - "wimbcd/bcd.bat" 10 | 11 | jobs: 12 | generate-bcd: 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - name: Run git checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: Build BCD 20 | working-directory: ${{env.GITHUB_WORKSPACE}} 21 | run: | 22 | .\wimbcd\bcd.bat 23 | 24 | - name: Upload BCD 25 | uses: actions/upload-artifact@v4 26 | with: 27 | name: bcd 28 | path: build/bcd 29 | -------------------------------------------------------------------------------- /.github/workflows/firmware.yml: -------------------------------------------------------------------------------- 1 | name: Build Firmware 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | ovmf: 8 | name: Firmware Build 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Install dependencies 13 | run: | 14 | sudo apt update 15 | sudo apt install -y build-essential git wget python3 acpica-tools nasm iasl uuid-dev 16 | sudo apt install -y gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu 17 | sudo apt install -y qemu-utils 18 | 19 | - name: Checkout code 20 | uses: actions/checkout@v4 21 | 22 | - name: Git config 23 | run: git config --global --add safe.directory "$GITHUB_WORKSPACE" 24 | 25 | - name: Build SeaBIOS 26 | run: | 27 | git clone --depth 1 https://github.com/qemu/seabios.git 28 | mkdir -p output 29 | make -C seabios 30 | cp seabios/out/bios.bin output/bios.bin 31 | qemu-img convert -O qcow2 -c output/bios.bin output/bios.qcow2 32 | 33 | - name: Build OVMF 34 | run: | 35 | set -ex 36 | 37 | git clone --recursive https://github.com/tianocore/edk2.git 38 | ( cd edk2 && git checkout edk2-stable202502 ) 39 | 40 | export PACKAGES_PATH="$(pwd -P)"/edk2 41 | 42 | export GCC5_ARM_PREFIX=arm-linux-gnueabi- 43 | export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- 44 | 45 | set +e 46 | . edk2/edksetup.sh 47 | set -e 48 | make -C edk2/BaseTools 49 | 50 | FD_COMMON="-D NETWORK_HTTP_BOOT_ENABLE -D NETWORK_IP6_ENABLE -D NETWORK_TLS_ENABLE -D NETWORK_ISCSI_ENABLE -D NETWORK_ALLOW_HTTP_CONNECTIONS -D TPM2_ENABLE -D TPM2_CONFIG_ENABLE -D TPM1_ENABLE -D CAVIUM_ERRATUM_27456" 51 | build -b RELEASE -t GCC5 -a AARCH64 -p ArmVirtPkg/ArmVirtQemu.dsc 52 | build -b RELEASE -t GCC5 -a IA32 -p OvmfPkg/OvmfPkgIa32.dsc $FD_COMMON -D FD_SIZE_4MB 53 | build -b RELEASE -t GCC5 -a X64 -p OvmfPkg/OvmfPkgX64.dsc $FD_COMMON -D FD_SIZE_4MB 54 | 55 | mkdir -p output 56 | 57 | cp Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/FV/QEMU_EFI.fd output/AA64_EFI.fd 58 | cp output/AA64_EFI.fd output/AA64_EFI.raw.fd 59 | truncate -s 64M output/AA64_EFI.fd 60 | qemu-img convert -O qcow2 -c output/AA64_EFI.fd output/AA64_EFI.qcow2 61 | cp Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/FV/QEMU_VARS.fd output/AA64_VARS.fd 62 | 63 | cp Build/OvmfIa32/RELEASE_GCC5/FV/OVMF_CODE.fd output/IA32_EFI.fd 64 | qemu-img convert -O qcow2 -c output/IA32_EFI.fd output/IA32_EFI.qcow2 65 | cp Build/OvmfIa32/RELEASE_GCC5/FV/OVMF_VARS.fd output/IA32_VARS.fd 66 | 67 | cp Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd output/X64_EFI.fd 68 | qemu-img convert -O qcow2 -c output/X64_EFI.fd output/X64_EFI.qcow2 69 | cp Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd output/X64_VARS.fd 70 | 71 | - name: Upload firmware 72 | uses: actions/upload-artifact@v4 73 | with: 74 | name: firmware 75 | path: output/ 76 | -------------------------------------------------------------------------------- /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | name: MSBuild 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - "main" 8 | 9 | env: 10 | # Path to the solution file relative to the root of the project. 11 | SOLUTION_FILE_PATH: . 12 | 13 | jobs: 14 | build: 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - name: Run git checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Add MSBuild to PATH 22 | uses: microsoft/setup-msbuild@v2 23 | 24 | - name: Restore NuGet packages 25 | working-directory: ${{env.GITHUB_WORKSPACE}} 26 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 27 | 28 | - name: Build 29 | working-directory: ${{env.GITHUB_WORKSPACE}} 30 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 31 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 32 | run: | 33 | msbuild /m /p:Configuration=Release /p:platform=x64 ${{env.SOLUTION_FILE_PATH}} 34 | 35 | - name: Copy files 36 | working-directory: ${{env.GITHUB_WORKSPACE}} 37 | run: | 38 | md zemu 39 | move x64\Release\zemu.exe zemu\ 40 | move firmware\bios.qcow2 zemu\ 41 | move firmware\X64_EFI.qcow2 zemu\ 42 | move firmware\IA32_EFI.qcow2 zemu\ 43 | move firmware\AA64_EFI.qcow2 zemu\ 44 | move firmware\ARM_EFI.qcow2 zemu\ 45 | move firmware\wim.cpio zemu\ 46 | move firmware\wim.qcow2 zemu\ 47 | move firmware\wimldr zemu\ 48 | move firmware\wimldr.x64 zemu\ 49 | move firmware\wimldr.ia32 zemu\ 50 | move firmware\wimldr.aa64 zemu\ 51 | 52 | - name: Create ZIP 53 | uses: thedoctor0/zip-release@master 54 | with: 55 | type: 'zip' 56 | filename: 'zemu.zip' 57 | directory: '.' 58 | path: 'zemu' 59 | 60 | - name: Delete old release 61 | continue-on-error: true 62 | working-directory: ${{env.GITHUB_WORKSPACE}} 63 | run: | 64 | gh release delete latest --cleanup-tag --yes 65 | env: 66 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 67 | 68 | - name: Release 69 | working-directory: ${{env.GITHUB_WORKSPACE}} 70 | run: | 71 | gh release create latest zemu.zip -t "Development Build" -p 72 | env: 73 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 74 | -------------------------------------------------------------------------------- /.github/workflows/wimldr.yml: -------------------------------------------------------------------------------- 1 | name: Build and Upload wimldr 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Install dependencies 16 | run: | 17 | # Update package list and install required tools 18 | sudo apt-get update 19 | sudo apt-get install -y parted dosfstools qemu-utils build-essential gcc-aarch64-linux-gnu 20 | 21 | - name: Build wimldr 22 | working-directory: wimldr 23 | run: | 24 | make 25 | 26 | - name: Run pack-hda.sh script 27 | run: | 28 | chmod +x pack-hda.sh 29 | sudo ./pack-hda.sh 30 | 31 | - name: Upload artifacts 32 | uses: actions/upload-artifact@v4 33 | with: 34 | name: wimldr 35 | path: | 36 | wim.qcow2 37 | wim.cpio 38 | wimldr/wimldr.x64 39 | wimldr/wimldr.ia32 40 | wimldr/wimldr.aa64 41 | wimldr/wimldr 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZenEmu 2 | 3 | ![License](https://img.shields.io/github/license/a1ive/ZenEmu) ![Downloads](https://img.shields.io/github/downloads/a1ive/ZenEmu/total) ![Release](https://img.shields.io/github/v/release/a1ive/ZenEmu) 4 | 5 | ZenEmu is a simple GUI for QEMU on Windows. 6 | It helps users easily test different boot environments. 7 | 8 | ## Features 9 | 10 | - **Supported Boot Environments**: 11 | - x86 BIOS 12 | - IA32 UEFI 13 | - x64 UEFI 14 | - ARM64 UEFI 15 | - ARM32 UEFI 16 | - **Supported Image and Media Types**: 17 | - Hard disk images 18 | - ISO images 19 | - Physical disks 20 | - Linux kernels 21 | - WIM images 22 | - PXE boot 23 | - **Supported Languages**: 24 | - English 25 | - Chinese (Simplified/Traditional) 26 | - Japanese 27 | - Turkish 28 | 29 | ## Download 30 | - Get the latest release from [GitHub](https://github.com/a1ive/ZenEmu/releases). 31 | - Download QEMU from [here](https://qemu.weilnetz.de/w64/). 32 | 33 | ## License 34 | 35 | This project is licensed under the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) license. 36 | -------------------------------------------------------------------------------- /emu.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33829.357 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emu", "emu.vcxproj", "{5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ews", "ews\ews.vcxproj", "{F184EE79-D114-4E2E-B621-C2C0E74B93A3}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Debug|x64.ActiveCfg = Debug|x64 19 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Debug|x64.Build.0 = Debug|x64 20 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Debug|x86.ActiveCfg = Debug|Win32 21 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Debug|x86.Build.0 = Debug|Win32 22 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Release|x64.ActiveCfg = Release|x64 23 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Release|x64.Build.0 = Release|x64 24 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Release|x86.ActiveCfg = Release|Win32 25 | {5EEDC00B-F9F5-42F3-8671-7A13D5105CD9}.Release|x86.Build.0 = Release|Win32 26 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Debug|x64.ActiveCfg = Debug|x64 27 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Debug|x64.Build.0 = Debug|x64 28 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Debug|x86.ActiveCfg = Debug|Win32 29 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Debug|x86.Build.0 = Debug|Win32 30 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Release|x64.ActiveCfg = Release|x64 31 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Release|x64.Build.0 = Release|x64 32 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Release|x86.ActiveCfg = Release|Win32 33 | {F184EE79-D114-4E2E-B621-C2C0E74B93A3}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {D60C193C-F867-4145-8BD2-08919FEB415F} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /ews/ews.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | 6 | #include "ews.h" 7 | 8 | #ifdef _CONSOLE 9 | #define ews_printf printf 10 | #define ews_printf_debug printf 11 | #else 12 | #define ews_printf 13 | #define ews_printf_debug(...) 14 | #endif 15 | 16 | #pragma warning(disable:4101) 17 | #pragma warning(disable:4267) 18 | #pragma warning(disable:4996) 19 | #include "EmbeddableWebServer.h" 20 | 21 | #pragma comment(lib, "ws2_32") 22 | 23 | struct _EWS_SERVER 24 | { 25 | struct Server server; 26 | HANDLE thread; 27 | uint16_t port; 28 | char root[MAX_PATH]; 29 | }; 30 | 31 | static DWORD WINAPI server_thread_func(LPVOID param) 32 | { 33 | EWS_SERVER* ws = (EWS_SERVER*)param; 34 | acceptConnectionsUntilStoppedFromEverywhereIPv4(&ws->server, ws->port); 35 | return 0; 36 | } 37 | 38 | struct Response * 39 | createResponseForRequest(const struct Request* request, struct Connection* connection) 40 | { 41 | EWS_SERVER* ws = (EWS_SERVER*)connection->server->tag; 42 | ews_printf("Request: %s\n", request->path); 43 | if (strcmp(request->path, "/") == 0) 44 | { 45 | struct HeapString connectionDebugInfo = connectionDebugStringCreate(connection); 46 | struct Response* response = responseAllocWithFormat(200, "OK", "text/html; charset=UTF-8", 47 | "EWS" 48 | "" 49 | "

Embedded C Web Server by Forrest Heller

" 50 | "

Version %s

" 51 | "

Browse Files

" 52 | "ROOT
" 53 | "

Server Status

" 54 | "\n" 55 | "\n" 56 | "\n" 57 | "\n" 58 | "\n" 59 | "\n" 60 | "\n" 61 | "\n" 62 | "\n" 63 | "
Active connections%" PRId64 "
Total connections%" PRId64 "
Total bytes sent%" PRId64 "
Total bytes received%" PRId64 "
Heap string allocations%" PRId64 "
Heap string reallocations%" PRId64 "
Heap string frees%" PRId64 "
Heap string total bytes allocated%" PRId64 "
" 64 | "

Connection Debug Info

%s
" 65 | "", 66 | EMBEDDABLE_WEB_SERVER_VERSION_STRING, 67 | counters.activeConnections, 68 | counters.totalConnections, 69 | counters.bytesSent, 70 | counters.bytesReceived, 71 | counters.heapStringAllocations, 72 | counters.heapStringReallocations, 73 | counters.heapStringFrees, 74 | counters.heapStringTotalBytesReallocated, 75 | connectionDebugInfo.contents); 76 | heapStringFreeContents(&connectionDebugInfo); 77 | return response; 78 | } 79 | 80 | if (strcmp(request->path, "/?") == 0) 81 | return responseAllocServeFileFromRequestPath("/", "/", "/", ws->root); 82 | 83 | return responseAllocServeFileFromRequestPath("/", request->path, request->pathDecoded, ws->root); 84 | } 85 | 86 | EWS_SERVER* ews_start(uint16_t port, const char* root) 87 | { 88 | EWS_SERVER* ws = (EWS_SERVER*)malloc(sizeof(EWS_SERVER)); 89 | if (!ws) 90 | return NULL; 91 | memset(ws, 0, sizeof(EWS_SERVER)); 92 | ws->port = port; 93 | strcpy_s(ws->root, MAX_PATH, root); 94 | ws->root[MAX_PATH - 1] = '\0'; 95 | 96 | serverInit(&ws->server); 97 | ws->server.tag = ws; 98 | 99 | #ifdef _CONSOLE 100 | server_thread_func(ws); 101 | #else 102 | ws->thread = CreateThread(NULL, 0, server_thread_func, ws, 0, NULL); 103 | if (ws->thread == NULL) 104 | { 105 | serverDeInit(&ws->server); 106 | free(ws); 107 | return NULL; 108 | } 109 | #endif 110 | return ws; 111 | } 112 | 113 | void ews_stop(EWS_SERVER* ws) 114 | { 115 | if (!ws) 116 | return; 117 | serverStop(&ws->server); 118 | if (ws->thread) 119 | { 120 | WaitForSingleObject(ws->thread, INFINITE); 121 | CloseHandle(ws->thread); 122 | } 123 | serverDeInit(&ws->server); 124 | free(ws); 125 | } 126 | -------------------------------------------------------------------------------- /ews/ews.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | struct _EWS_SERVER; 8 | typedef struct _EWS_SERVER EWS_SERVER; 9 | 10 | EWS_SERVER* ews_start(uint16_t port, const char* root); 11 | void ews_stop(EWS_SERVER* ws); 12 | -------------------------------------------------------------------------------- /ews/ews.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Headers 20 | 21 | 22 | Headers 23 | 24 | 25 | 26 | 27 | Sources 28 | 29 | 30 | Sources 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ews/main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ews.h" 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | uint16_t port = 80; 13 | const char* root = "."; 14 | for (int i = 1; i < argc; i++) 15 | { 16 | if (strcmp(argv[i], "--help") == 0 || 17 | strcmp(argv[i], "-h") == 0 || 18 | strcmp(argv[i], "/?") == 0) 19 | { 20 | printf("Usage: %s [--port=PORT] [--root=ROOT]\n", argv[0]); 21 | return 0; 22 | } 23 | if (strncmp(argv[i], "--port=", 7) == 0) 24 | { 25 | port = atoi(argv[i] + 7); 26 | continue; 27 | } 28 | if (strncmp(argv[i], "--root=", 7) == 0) 29 | { 30 | root = argv[i] + 7; 31 | continue; 32 | } 33 | } 34 | EWS_SERVER* ws = ews_start(port, root); 35 | ews_stop(ws); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /ews/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /firmware/AA64_EFI.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/AA64_EFI.qcow2 -------------------------------------------------------------------------------- /firmware/ARM_EFI.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/ARM_EFI.qcow2 -------------------------------------------------------------------------------- /firmware/IA32_EFI.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/IA32_EFI.qcow2 -------------------------------------------------------------------------------- /firmware/X64_EFI.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/X64_EFI.qcow2 -------------------------------------------------------------------------------- /firmware/bios.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/bios.qcow2 -------------------------------------------------------------------------------- /firmware/wim.cpio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wim.cpio -------------------------------------------------------------------------------- /firmware/wim.qcow2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wim.qcow2 -------------------------------------------------------------------------------- /firmware/wimldr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wimldr -------------------------------------------------------------------------------- /firmware/wimldr.aa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wimldr.aa64 -------------------------------------------------------------------------------- /firmware/wimldr.ia32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wimldr.ia32 -------------------------------------------------------------------------------- /firmware/wimldr.x64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/firmware/wimldr.x64 -------------------------------------------------------------------------------- /icons/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/add.png -------------------------------------------------------------------------------- /icons/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/admin.png -------------------------------------------------------------------------------- /icons/audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/audio.png -------------------------------------------------------------------------------- /icons/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/camera.png -------------------------------------------------------------------------------- /icons/cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/cd.png -------------------------------------------------------------------------------- /icons/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/close.png -------------------------------------------------------------------------------- /icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/copy.png -------------------------------------------------------------------------------- /icons/cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/cpu.png -------------------------------------------------------------------------------- /icons/dice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/dice.png -------------------------------------------------------------------------------- /icons/dir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/dir.png -------------------------------------------------------------------------------- /icons/disk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/disk.png -------------------------------------------------------------------------------- /icons/display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/display.png -------------------------------------------------------------------------------- /icons/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/down.png -------------------------------------------------------------------------------- /icons/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/edit.png -------------------------------------------------------------------------------- /icons/eth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/eth.png -------------------------------------------------------------------------------- /icons/firmware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/firmware.png -------------------------------------------------------------------------------- /icons/floppy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/floppy.png -------------------------------------------------------------------------------- /icons/halt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/halt.png -------------------------------------------------------------------------------- /icons/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/info.png -------------------------------------------------------------------------------- /icons/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/maximize.png -------------------------------------------------------------------------------- /icons/memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/memory.png -------------------------------------------------------------------------------- /icons/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/minimize.png -------------------------------------------------------------------------------- /icons/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/network.png -------------------------------------------------------------------------------- /icons/pc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/pc.png -------------------------------------------------------------------------------- /icons/pci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/pci.png -------------------------------------------------------------------------------- /icons/qemu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/qemu.png -------------------------------------------------------------------------------- /icons/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/refresh.png -------------------------------------------------------------------------------- /icons/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/remove.png -------------------------------------------------------------------------------- /icons/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/start.png -------------------------------------------------------------------------------- /icons/storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/storage.png -------------------------------------------------------------------------------- /icons/usb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/usb.png -------------------------------------------------------------------------------- /icons/vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/vm.png -------------------------------------------------------------------------------- /icons/warn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/icons/warn.png -------------------------------------------------------------------------------- /include/cmdline.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #define VC_EXTRALEAN 6 | #include 7 | 8 | #define CMDLINE_LEN 65535 9 | 10 | void 11 | reset_cmdline(void); 12 | 13 | void 14 | append_cmdline(LPCWSTR _Printf_format_string_ format, ...); 15 | 16 | LPWSTR 17 | get_cmdline(void); 18 | -------------------------------------------------------------------------------- /include/dev.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #define VC_EXTRALEAN 6 | #include 7 | 8 | typedef struct _PHY_DRIVE_INFO 9 | { 10 | DWORD index; 11 | UINT64 size; 12 | LPCSTR prefix; 13 | CHAR hw[MAX_PATH]; 14 | LPCSTR bus; 15 | UINT32 mnt; 16 | CHAR text[MAX_PATH]; 17 | }PHY_DRIVE_INFO; 18 | 19 | DWORD 20 | get_disk_list(BOOL is_cd, PHY_DRIVE_INFO** drive_list); 21 | -------------------------------------------------------------------------------- /include/gettext.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | typedef enum _GETTEXT_STR_ID 6 | { 7 | ZTXT_QEMU = 0, 8 | ZTXT_PATH, 9 | ZTXT_ARCH, 10 | ZTXT_CPU, 11 | ZTXT_SMP, 12 | ZTXT_NAME, 13 | ZTXT_MODEL, 14 | ZTXT_MACHINE, 15 | ZTXT_HYPER_V, 16 | ZTXT_KERNEL_IRQCHIP, 17 | ZTXT_VIRT, 18 | ZTXT_MEMORY, 19 | ZTXT_SIZE, 20 | ZTXT_FIRMWARE, 21 | ZTXT_TYPE, 22 | ZTXT_OPTIONS, 23 | ZTXT_BOOT_MENU, 24 | ZTXT_TIMEOUT, 25 | ZTXT_PFLASH, 26 | ZTXT_DISPLAY, 27 | ZTXT_FULLSCREEN, 28 | ZTXT_NETWORK, 29 | ZTXT_MAC_ADDRESS, 30 | ZTXT_PERIPHERAL, 31 | ZTXT_USB, 32 | ZTXT_KEYBOARD, 33 | ZTXT_MOUSE, 34 | ZTXT_TABLET, 35 | ZTXT_AUDIO, 36 | ZTXT_BACKEND, 37 | ZTXT_INTEL_HDA, 38 | ZTXT_PC_SPEAKER, 39 | ZTXT_BOOT_DEVICE, 40 | ZTXT_DISK_IMAGE, 41 | ZTXT_ISO_IMAGE, 42 | ZTXT_PHYSICAL_DISK, 43 | ZTXT_CD_ROM, 44 | ZTXT_HARD_DISK, 45 | ZTXT_FLOPPY, 46 | ZTXT_FLOPPY_IMAGE, 47 | ZTXT_PXE, 48 | ZTXT_BOOT_FILE, 49 | ZTXT_HTTP, 50 | ZTXT_PORT, 51 | ZTXT_LINUX_KERNEL, 52 | ZTXT_KERNEL, 53 | ZTXT_INITRD, 54 | ZTXT_CMDLINE, 55 | ZTXT_DTB, 56 | ZTXT_SHIM_EFI, 57 | ZTXT_WIM_IMAGE, 58 | ZTXT_WIM_INDEX, 59 | ZTXT_DIR_VVFAT, 60 | ZTXT_DIR, 61 | ZTXT_SNAPSHOT, 62 | ZTXT_INTERFACE, 63 | ZTXT_NO_DEVICE, 64 | ZTXT_ADDITIONAL, 65 | ZTXT_FILE, 66 | ZTXT_DEVICE, 67 | ZTXT_COPY, 68 | ZTXT_SAVE, 69 | ZTXT_START, 70 | ZTXT_STOP, 71 | ZTXT_SCREENSHOT, 72 | ZTXT_SAVE_TO, 73 | ZTXT_CLIPBOARD, 74 | ZTXT_LOGS, 75 | ZTXT_WARN_NOT_ADMIN, 76 | ZTXT_WARN_NON_ASCII, 77 | ZTXT_WARN_OUT_OF_MEM, 78 | ZTXT_WARN_FULLSCREEN, 79 | ZTXT_WARN_NOT_BOOTABLE, 80 | ZTXT_MSG_COPIED, 81 | ZTXT_MSG_SAVED, 82 | ZTXT_MSG_MISSING_ARGS, 83 | ZTXT_MSG_KILLED, 84 | ZTXT_MSG_KILL_FAILED, 85 | ZTXT_MSG_PNG_OK, 86 | ZTXT_MSG_PNG_ERR, 87 | ZTXT_UNSUPPORTED, 88 | 89 | ZTXT__MAX 90 | } GETTEXT_STR_ID; 91 | 92 | const char* 93 | ZTXT(GETTEXT_STR_ID id); 94 | -------------------------------------------------------------------------------- /include/nkctx.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #define WIN32_LEAN_AND_MEAN 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../resource.h" 12 | 13 | #define NK_INCLUDE_FIXED_TYPES 14 | #define NK_INCLUDE_STANDARD_IO 15 | #define NK_INCLUDE_STANDARD_VARARGS 16 | #define NK_INCLUDE_DEFAULT_ALLOCATOR 17 | 18 | #include 19 | #define NK_ASSERT(expr) assert(expr) 20 | 21 | #include 22 | #include 23 | 24 | #include "nkctx_priv.h" 25 | 26 | void 27 | nkctx_set_dpi_scaling(HWND wnd); 28 | 29 | struct nk_image 30 | nkctx_load_png(WORD id); 31 | 32 | void 33 | nkctx_set_style(struct nk_context* ctx); 34 | 35 | void 36 | nkctx_init(int x, int y, LPCWSTR class_name, LPCWSTR title); 37 | 38 | void 39 | nkctx_loop(void); 40 | 41 | void 42 | nkctx_update(WPARAM wparam); 43 | 44 | _Noreturn void 45 | nkctx_fini(int code); 46 | -------------------------------------------------------------------------------- /include/nkctx_priv.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | GdipFont* 5 | nk_gdip_load_font(LPCWSTR name, int size); 6 | 7 | nk_bool nk_button_ex(struct nk_context* ctx, struct nk_image img, const char* label); 8 | 9 | nk_bool 10 | nk_begin_ex(struct nk_context* ctx, const char* title, 11 | struct nk_rect bounds, nk_flags flags); 12 | 13 | struct _PHY_DRIVE_INFO; 14 | DWORD 15 | nk_disk_list(struct nk_context* ctx, struct _PHY_DRIVE_INFO* items, DWORD count, 16 | DWORD selected, int item_height); 17 | 18 | void 19 | nk_image_label(struct nk_context* ctx, struct nk_image img, const char* str); 20 | 21 | void 22 | nk_space_label(struct nk_context* ctx, const char* str); 23 | 24 | nk_bool 25 | nk_menu_begin_image_ex(struct nk_context* ctx, const char* id, struct nk_image img, 26 | struct nk_vec2 size); 27 | 28 | #define NK_COLOR_YELLOW {0xFF, 0xEA, 0x00, 0xff} 29 | #define NK_COLOR_RED {0xFF, 0x17, 0x44, 0xff} 30 | #define NK_COLOR_GREEN {0x00, 0xE6, 0x76, 0xff} 31 | #define NK_COLOR_CYAN {0x03, 0xDA, 0xC6, 0xff} 32 | #define NK_COLOR_BLUE {0x29, 0x79, 0xFF, 0xff} 33 | #define NK_COLOR_WHITE {0xFF, 0xFF, 0xFF, 0xff} 34 | #define NK_COLOR_BLACK {0x00, 0x00, 0x00, 0xff} 35 | #define NK_COLOR_GRAY {0x1E, 0x1E, 0x1E, 0xff} 36 | #define NK_COLOR_LIGHT {0xBF, 0xBF, 0xBF, 0xff} 37 | #define NK_COLOR_DARK {0x2D, 0x2D, 0x2D, 0xFF} 38 | 39 | struct _ZEMU_INI_DATA; 40 | 41 | #define FONT_NAME_LEN 64 42 | 43 | typedef struct _NK_GUI_CTX 44 | { 45 | HINSTANCE inst; 46 | HINSTANCE prev; 47 | LPWSTR cmdline; 48 | int cmdshow; 49 | HWND wnd; 50 | WNDCLASSW wc; 51 | WCHAR font_name[FONT_NAME_LEN]; 52 | GdipFont* font; 53 | nk_bool dpi_scaling; 54 | double dpi_factor; 55 | struct nk_color color[NK_COLOR_COUNT]; 56 | struct nk_context* ctx; 57 | unsigned width; 58 | unsigned height; 59 | unsigned font_size; 60 | float title_height; 61 | float sq; 62 | nk_bool show_warning; 63 | struct nk_style_button button_style; 64 | UINT64 tilck; 65 | 66 | struct nk_image image[IDR_PNG_MAX - IDR_PNG_MIN]; 67 | 68 | MEMORYSTATUSEX statex; 69 | 70 | struct _ZEMU_INI_DATA* ini; 71 | } NK_GUI_CTX; 72 | extern NK_GUI_CTX nk; 73 | 74 | -------------------------------------------------------------------------------- /include/ui.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #define VC_EXTRALEAN 6 | #include 7 | 8 | #define FILTER_VHD \ 9 | L"Disk Image (vhd,vhdx,vdi,vmdk,img,raw)\0" \ 10 | "*.VHD;*.VHDX;*.VDI;*.VMDK;*.IMG;*.RAW\0" \ 11 | "QEMU Image (qcow2,qcow)\0" \ 12 | "*.QCOW2;*.QCOW\0" \ 13 | "All Files\0*.*\0" 14 | 15 | #define FILTER_ISO \ 16 | L"ISO\0*.ISO\0All Files\0*.*\0" 17 | 18 | #define FILTER_VFD \ 19 | L"Floppy Image (img)\0*.IMG\0" \ 20 | "All Files\0*.*\0" 21 | 22 | #define FILTER_DTB \ 23 | L"Device Tree Binary (dtb)\0*.DTB\0" \ 24 | "All Files\0*.*\0" 25 | 26 | #define FILTER_EFI \ 27 | L"EFI Application (efi)\0*.EFI\0" \ 28 | "All Files\0*.*\0" 29 | 30 | #define FILTER_WIM \ 31 | L"WIM Image (wim)\0*.WIM\0" \ 32 | "All Files\0*.*\0" 33 | 34 | #define FILTER_PNG \ 35 | L"Portable Network Graphics (png)\0*.PNG\0" 36 | 37 | #define FILTER_ALL \ 38 | L"All Files\0*.*\0" 39 | 40 | void 41 | ui_open_file(CHAR* path, size_t len, LPCWSTR filter); 42 | 43 | void 44 | ui_open_file_by_dir(CHAR* path, size_t len, LPCSTR dir, LPCWSTR filter); 45 | 46 | BOOL 47 | ui_save_file(LPWSTR path, size_t len, LPCWSTR filter, LPCWSTR ext); 48 | 49 | void 50 | ui_open_dir(CHAR* path, size_t len); 51 | 52 | nk_bool 53 | ui_check_wim_header(uint32_t* num_images, uint32_t* boot); 54 | 55 | #define GET_PNG(x) nk.image[x - IDR_PNG_MIN] 56 | 57 | #define UI_OPTION(label, var, val) \ 58 | var = nk_option_label(ctx, (label), var == val) ? val : var 59 | 60 | void 61 | ui_dev_button(struct nk_context* ctx, 62 | struct nk_image img, const char* label, nk_bool* value); 63 | 64 | void 65 | ui_popup_window(struct nk_context* ctx, float width, float height); 66 | 67 | void 68 | ui_popup_msg(const char* msg, DWORD icon); 69 | 70 | nk_bool ui_is_qemu_running(void); 71 | 72 | void ui_reset_log(void); 73 | 74 | void 75 | ui_ini_init(void); 76 | 77 | void 78 | ui_ini_save(void); 79 | 80 | void 81 | ui_qemu_dir(struct nk_context* ctx); 82 | 83 | void 84 | ui_qemu_cpu(struct nk_context* ctx); 85 | 86 | void 87 | ui_qemu_mem(struct nk_context* ctx); 88 | 89 | void 90 | ui_qemu_fw(struct nk_context* ctx); 91 | 92 | void 93 | ui_qemu_dev(struct nk_context* ctx); 94 | 95 | void 96 | ui_qemu_boot(struct nk_context* ctx); 97 | 98 | void 99 | ui_qemu_hdb(struct nk_context* ctx); 100 | 101 | void 102 | ui_qemu_start(struct nk_context* ctx); 103 | 104 | void 105 | ui_qemu_end(struct nk_context* ctx); 106 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #define QUOTE_(x) #x 6 | #define QUOTE(x) QUOTE_(x) 7 | 8 | #define NKGUI_MAJOR_VERSION 0 9 | #define NKGUI_MINOR_VERSION 2 10 | #define NKGUI_MICRO_VERSION 1 11 | #define NKGUI_BUILD_VERSION 0 12 | 13 | #define NKGUI_VERSION NKGUI_MAJOR_VERSION,NKGUI_MINOR_VERSION,NKGUI_MICRO_VERSION,NKGUI_BUILD_VERSION 14 | #define NKGUI_VERSION_STR QUOTE(NKGUI_MAJOR_VERSION.NKGUI_MINOR_VERSION.NKGUI_MICRO_VERSION.NKGUI_BUILD_VERSION) 15 | 16 | #define NKGUI_COMPANY "A1ive" 17 | #define NKGUI_COPYRIGHT "Copyright (c) 2025 A1ive" 18 | #define NKGUI_FILEDESC "ZenEMU" 19 | 20 | #define NKGUI_NAME "ZenEMU" 21 | -------------------------------------------------------------------------------- /nuklear.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/nuklear.ico -------------------------------------------------------------------------------- /nuklear.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/nuklear.rc -------------------------------------------------------------------------------- /pack-hda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Define starting sector for the partition 4 | START_SECTOR=2048 5 | 6 | # Create a 16MB blank disk image 7 | dd if=/dev/zero of=wim.img bs=1M count=12 8 | 9 | # Create an MBR partition table on hda.img 10 | parted wim.img mklabel msdos 11 | 12 | # Create a primary FAT32 partition from sector START_SECTOR to the end of the disk 13 | # "100%" indicates the end of the disk 14 | parted -s wim.img mkpart primary fat16 ${START_SECTOR}s 100% 15 | 16 | # Attach the entire disk image to a loop device with partition scanning enabled (-P) 17 | LOOPDEV=$(losetup -f --show -P wim.img) 18 | 19 | # Format the first partition with FAT32 filesystem so that it gets the correct BPB 20 | mkfs.vfat -F 16 ${LOOPDEV}p1 21 | 22 | # Create a temporary mount point and mount the partition 23 | mkdir -p /mnt/hda_img 24 | mount ${LOOPDEV}p1 /mnt/hda_img 25 | 26 | # Copy all files from the wimhda/ directory into the mounted partition 27 | cp -r wimhda/* /mnt/hda_img/ 28 | 29 | # Unmount the partition and detach the loop device 30 | umount /mnt/hda_img 31 | losetup -d $LOOPDEV 32 | 33 | # Convert wim.img to qcow2 format with compression enabled 34 | qemu-img convert -O qcow2 -c wim.img wim.qcow2 35 | 36 | cd wimcpio 37 | find * | cpio -o -H newc > ../wim.cpio 38 | cd .. 39 | -------------------------------------------------------------------------------- /packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // 3 | #define IDI_MAIN_ICON 101 4 | 5 | #define IDR_PNG_MIN 110 6 | 7 | #define IDR_PNG_CD 110 8 | #define IDR_PNG_COPY 111 9 | #define IDR_PNG_CPU 112 10 | #define IDR_PNG_DIR 113 11 | #define IDR_PNG_DISK 114 12 | #define IDR_PNG_EDIT 115 13 | #define IDR_PNG_ETH 116 14 | #define IDR_PNG_FIRMWARE 117 15 | #define IDR_PNG_FLOPPY 118 16 | #define IDR_PNG_INFO 119 17 | #define IDR_PNG_MEMORY 120 18 | #define IDR_PNG_NETWORK 121 19 | #define IDR_PNG_PC 122 20 | #define IDR_PNG_PCI 123 21 | #define IDR_PNG_QEMU 124 22 | #define IDR_PNG_REFRESH 125 23 | #define IDR_PNG_START 126 24 | #define IDR_PNG_USB 127 25 | #define IDR_PNG_WARN 128 26 | #define IDR_PNG_ADMIN 129 27 | #define IDR_PNG_AUDIO 130 28 | #define IDR_PNG_MINIMIZE 131 29 | #define IDR_PNG_MAXIMIZE 132 30 | #define IDR_PNG_CLOSE 133 31 | #define IDR_PNG_ADD 134 32 | #define IDR_PNG_REMOVE 135 33 | #define IDR_PNG_STORAGE 136 34 | #define IDR_PNG_DISPLAY 137 35 | #define IDR_PNG_DOWN 138 36 | #define IDR_PNG_HALT 139 37 | #define IDR_PNG_CAMERA 140 38 | #define IDR_PNG_DICE 141 39 | #define IDR_PNG_VM 142 40 | 41 | #define IDR_PNG_MAX 143 42 | 43 | #define IDT_TIMER_1S 2001 44 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | 6 | int APIENTRY 7 | wWinMain(_In_ HINSTANCE hInstance, 8 | _In_opt_ HINSTANCE hPrevInstance, 9 | _In_ LPWSTR lpCmdLine, 10 | _In_ int nCmdShow) 11 | { 12 | OleInitialize(NULL); 13 | ZeroMemory(&nk, sizeof(nk)); 14 | nk.inst = hInstance; 15 | nk.prev = hPrevInstance; 16 | nk.cmdline = lpCmdLine; 17 | nk.cmdshow = nCmdShow; 18 | load_ini(); 19 | nkctx_init(100, 100, L"NkWindowClass", L"ZenEMU"); 20 | nkctx_loop(); 21 | nkctx_fini(0); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/nkstyle.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | 5 | static UINT m_dpi = USER_DEFAULT_SCREEN_DPI; 6 | 7 | void 8 | nkctx_set_dpi_scaling(HWND wnd) 9 | { 10 | if (nk.font) 11 | { 12 | nk_gdipfont_del(nk.font); 13 | nk.font = NULL; 14 | } 15 | if (nk.dpi_scaling) 16 | { 17 | RECT rect = { 0 }; 18 | UINT dpi = GetDpiForWindow(wnd); 19 | nk.dpi_factor = 1.0 * dpi / m_dpi; 20 | m_dpi = dpi; 21 | nk.font_size = (int)(nk.font_size * nk.dpi_factor); 22 | // resize window 23 | GetWindowRect(wnd, &rect); 24 | SetWindowPos(wnd, NULL, 0, 0, 25 | (int)((rect.right - rect.left) * nk.dpi_factor), (int)((rect.bottom - rect.top) * nk.dpi_factor), 26 | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 27 | } 28 | nk.font = nk_gdip_load_font(nk.font_name, nk.font_size); 29 | nk_gdip_set_font(nk.font); 30 | } 31 | 32 | struct nk_image 33 | nkctx_load_png(WORD id) 34 | { 35 | HRSRC res = FindResourceW(NULL, MAKEINTRESOURCEW(id), RT_RCDATA); 36 | if (!res) 37 | goto fail; 38 | HGLOBAL mem = LoadResource(NULL, res); 39 | if (!mem) 40 | goto fail; 41 | DWORD size = SizeofResource(NULL, res); 42 | if (!size) 43 | goto fail; 44 | void* data = LockResource(mem); 45 | if (!data) 46 | goto fail; 47 | return nk_gdip_load_image_from_memory(data, size); 48 | fail: 49 | return nk_image_id(0); 50 | } 51 | 52 | void 53 | nkctx_set_style(struct nk_context* ctx) 54 | { 55 | nk.color[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255); 56 | nk.color[NK_COLOR_WINDOW] = nk_rgba(215, 215, 215, 230); 57 | nk.color[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220); 58 | nk.color[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255); 59 | nk.color[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255); 60 | nk.color[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255); 61 | nk.color[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255); 62 | nk.color[NK_COLOR_TOGGLE] = nk_rgba(230, 230, 230, 255); 63 | nk.color[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255); 64 | nk.color[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255); 65 | nk.color[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255); 66 | nk.color[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255); 67 | nk.color[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255); 68 | nk.color[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245); 69 | nk.color[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255); 70 | nk.color[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255); 71 | nk.color[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255); 72 | nk.color[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225); 73 | nk.color[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255); 74 | nk.color[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255); 75 | nk.color[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255); 76 | nk.color[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255); 77 | nk.color[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255); 78 | nk.color[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255); 79 | nk.color[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255); 80 | nk.color[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255); 81 | nk.color[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255); 82 | nk.color[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255); 83 | nk.color[NK_COLOR_KNOB] = nk.color[NK_COLOR_SLIDER]; 84 | nk.color[NK_COLOR_KNOB_CURSOR] = nk.color[NK_COLOR_SLIDER_CURSOR]; 85 | nk.color[NK_COLOR_KNOB_CURSOR_HOVER] = nk.color[NK_COLOR_SLIDER_CURSOR_HOVER]; 86 | nk.color[NK_COLOR_KNOB_CURSOR_ACTIVE] = nk.color[NK_COLOR_SLIDER_CURSOR_ACTIVE]; 87 | 88 | nk_style_from_table(ctx, nk.color); 89 | 90 | nk.ctx->style.button.padding = nk_vec2(2.0f, 2.0f); 91 | nk.ctx->style.button.rounding = 2.0f; 92 | nk.ctx->style.window.scrollbar_size = nk_vec2(16.0f, 16.0f); 93 | 94 | memcpy(&nk.button_style, &ctx->style.button, sizeof(struct nk_style_button)); 95 | 96 | nk.title_height = nk.font_size 97 | + ctx->style.window.header.padding.y 98 | + ctx->style.window.header.label_padding.y; 99 | } 100 | -------------------------------------------------------------------------------- /src/open_dialog.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ui.h" 5 | #include "ini.h" 6 | 7 | #include 8 | #include 9 | 10 | void 11 | ui_open_file(CHAR* path, size_t len, LPCWSTR filter) 12 | { 13 | WCHAR buf[MAX_PATH] = L""; 14 | OPENFILENAMEW ofn; 15 | ZeroMemory(&ofn, sizeof(ofn)); 16 | ofn.lStructSize = sizeof(ofn); 17 | ofn.hwndOwner = nk.wnd; 18 | ofn.lpstrFile = buf; 19 | ofn.nMaxFile = MAX_PATH; 20 | ofn.lpstrFilter = filter; 21 | ofn.nFilterIndex = 1; 22 | ofn.lpstrFileTitle = NULL; 23 | ofn.nMaxFileTitle = 0; 24 | ofn.lpstrInitialDir = NULL; 25 | ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER; 26 | if (GetOpenFileNameW(&ofn) == TRUE) 27 | strcpy_s(path, len, ucs2_to_utf8(buf)); 28 | } 29 | 30 | void 31 | ui_open_file_by_dir(CHAR* path, size_t len, LPCSTR dir, LPCWSTR filter) 32 | { 33 | WCHAR buf[MAX_PATH]; 34 | OPENFILENAMEW ofn; 35 | LPCWSTR parent = rel_to_abs(dir); 36 | ZeroMemory(&ofn, sizeof(ofn)); 37 | swprintf(buf, MAX_PATH, L"%s\\FILE", parent); 38 | ofn.lStructSize = sizeof(ofn); 39 | ofn.hwndOwner = nk.wnd; 40 | ofn.lpstrFile = buf; 41 | ofn.nMaxFile = MAX_PATH; 42 | ofn.lpstrFilter = filter; 43 | ofn.nFilterIndex = 1; 44 | ofn.lpstrFileTitle = NULL; 45 | ofn.nMaxFileTitle = 0; 46 | ofn.lpstrInitialDir = parent; 47 | ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR; 48 | if (GetOpenFileNameW(&ofn) == TRUE) 49 | strcpy_s(path, len, ucs2_to_utf8(PathFindFileNameW(buf))); 50 | } 51 | 52 | BOOL 53 | ui_save_file(LPWSTR path, size_t len, LPCWSTR filter, LPCWSTR ext) 54 | { 55 | OPENFILENAMEW ofn; 56 | ZeroMemory(&ofn, sizeof(ofn)); 57 | ofn.lStructSize = sizeof(ofn); 58 | ofn.hwndOwner = nk.wnd; 59 | ofn.lpstrFilter = filter; 60 | ofn.nFilterIndex = 1; 61 | ofn.lpstrFile = path; 62 | ofn.nMaxFile = MAX_PATH; 63 | ofn.lpstrFileTitle = NULL; 64 | ofn.nMaxFileTitle = 0; 65 | ofn.lpstrInitialDir = NULL; 66 | ofn.Flags = OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT; 67 | ofn.lpstrDefExt = ext; 68 | return GetSaveFileNameW(&ofn); 69 | } 70 | 71 | static int CALLBACK 72 | browse_callback_fn(HWND wnd, UINT msg, LPARAM lparam, LPARAM data) 73 | { 74 | int rc = 0; 75 | switch (msg) 76 | { 77 | case BFFM_INITIALIZED: 78 | SendMessageW(wnd, BFFM_SETSELECTION, TRUE, (LPARAM)nk.ini->pwd); 79 | break; 80 | case BFFM_VALIDATEFAILED: 81 | MessageBoxW(wnd, L"Invalid Path", L"ERROR", MB_OK); 82 | rc = 1; 83 | break; 84 | } 85 | return rc; 86 | } 87 | 88 | void 89 | ui_open_dir(CHAR* path, size_t len) 90 | { 91 | WCHAR dir[MAX_PATH]; 92 | BROWSEINFOW bi = 93 | { 94 | .hwndOwner = nk.wnd, 95 | .pidlRoot = NULL, 96 | .pszDisplayName = dir, 97 | .lpszTitle = L"Select Folder", 98 | .ulFlags = BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN | BIF_USENEWUI | BIF_VALIDATE, 99 | .lpfn = browse_callback_fn, 100 | }; 101 | LPITEMIDLIST pidl = SHBrowseForFolderW(&bi); 102 | if (pidl != NULL) 103 | { 104 | SHGetPathFromIDListW(pidl, dir); 105 | strcpy_s(path, len, ucs2_to_utf8(dir)); 106 | CoTaskMemFree(pidl); 107 | } 108 | size_t path_len = strlen(path); 109 | if (path_len > 0 && path[path_len - 1] == '\\') 110 | path[path_len - 1] = '\0'; 111 | } 112 | -------------------------------------------------------------------------------- /src/ui_cpu.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | #include "ui.h" 6 | #include "gettext.h" 7 | 8 | static const char* edit_cpu_x86[] = 9 | { 10 | "486", "Broadwell", "Conroe", "Cooperlake", 11 | "Dhyana", "EPYC", "Haswell", "Ivybridge", 12 | "Skylake-Client", "Skylake-Server", "Snowridge", 13 | "athlon", "core2duo", "max", 14 | }; 15 | 16 | static const char* edit_cpu_arm[] = 17 | { 18 | "cortex-a7", "cortex-a15", 19 | "cortex-a35", "cortex-a53", "cortex-a57", "cortex-a72", "cortex-a76", 20 | "max", 21 | }; 22 | 23 | static const char* edit_machine_x86[] = 24 | { 25 | "pc", "q35", "isapc", 26 | }; 27 | 28 | static const char* edit_machine_arm[] = 29 | { 30 | "virt", 31 | }; 32 | 33 | void 34 | ui_qemu_cpu(struct nk_context* ctx) 35 | { 36 | nk_layout_row_dynamic(ctx, 0, 1); 37 | nk_image_label(ctx, GET_PNG(IDR_PNG_CPU), ZTXT(ZTXT_CPU)); 38 | nk_layout_row(ctx, NK_DYNAMIC, 0, 5, (float[5]) { 0.2f, 0.2f, 0.1f, 0.25f, 0.25f }); 39 | nk_space_label(ctx, ZTXT(ZTXT_SMP)); 40 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->cur->smp, OPT_SZ, nk_filter_decimal); 41 | nk_spacer(ctx); 42 | nk_checkbox_label(ctx, ZTXT(ZTXT_KERNEL_IRQCHIP), &nk.ini->cur->irqchip); 43 | if (nk.ini->qemu_arch == ZEMU_QEMU_ARCH_AA64) 44 | { 45 | if (nk.ini->cur->fw == ZEMU_FW_ARM32_EFI) 46 | nk_widget_disable_begin(ctx); 47 | nk_checkbox_label(ctx, ZTXT(ZTXT_VIRT), &nk.ini->cur->virt); 48 | if (nk.ini->cur->fw == ZEMU_FW_ARM32_EFI) 49 | nk_widget_disable_end(ctx); 50 | } 51 | else if (nk.ini->qemu_arch == ZEMU_QEMU_ARCH_X64) 52 | nk_checkbox_label(ctx, ZTXT(ZTXT_HYPER_V), &nk.ini->cur->whpx); 53 | else 54 | nk_spacer(ctx); 55 | 56 | nk_layout_row(ctx, NK_DYNAMIC, 0, 6, 57 | (float[6]) { 0.2f, 0.3f - nk.sq, nk.sq, 0.2f, 0.3f - nk.sq, nk.sq }); 58 | nk_space_label(ctx, ZTXT(ZTXT_MODEL)); 59 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->cur->model, OPT_SZ, nk_filter_ascii); 60 | if (nk_menu_begin_image_ex(ctx, "#EDIT_CPU", GET_PNG(IDR_PNG_DOWN), nk_vec2(200, 600))) 61 | { 62 | const char** list = edit_cpu_x86; 63 | size_t count = ARRAYSIZE(edit_cpu_x86); 64 | if (nk.ini->qemu_arch == ZEMU_QEMU_ARCH_AA64) 65 | { 66 | list = edit_cpu_arm; 67 | count = ARRAYSIZE(edit_cpu_arm); 68 | } 69 | nk_layout_row_dynamic(ctx, 0, 1); 70 | for (size_t i = 0; i < count; i++) 71 | { 72 | if (nk_menu_item_label(ctx, list[i], NK_TEXT_LEFT)) 73 | strcpy_s(nk.ini->cur->model, OPT_SZ, list[i]); 74 | } 75 | nk_menu_end(ctx); 76 | } 77 | nk_label(ctx, ZTXT(ZTXT_MACHINE), NK_TEXT_RIGHT); 78 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->cur->machine, OPT_SZ, nk_filter_ascii); 79 | if (nk_menu_begin_image_ex(ctx, "#EDIT_MACHINE", GET_PNG(IDR_PNG_DOWN), nk_vec2(200, 300))) 80 | { 81 | const char** list = edit_machine_x86; 82 | size_t count = ARRAYSIZE(edit_machine_x86); 83 | if (nk.ini->qemu_arch == ZEMU_QEMU_ARCH_AA64) 84 | { 85 | list = edit_machine_arm; 86 | count = ARRAYSIZE(edit_machine_arm); 87 | } 88 | nk_layout_row_dynamic(ctx, 0, 1); 89 | for (size_t i = 0; i < count; i++) 90 | { 91 | if (nk_menu_item_label(ctx, list[i], NK_TEXT_LEFT)) 92 | strcpy_s(nk.ini->cur->machine, OPT_SZ, list[i]); 93 | } 94 | nk_menu_end(ctx); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/ui_dir.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | #include "ui.h" 6 | #include "gettext.h" 7 | 8 | #include 9 | 10 | static BOOL 11 | is_admin(void) 12 | { 13 | BOOL b; 14 | SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY; 15 | PSID admin_group; 16 | b = AllocateAndInitializeSid(&nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 17 | 0, 0, 0, 0, 0, 0, &admin_group); 18 | if (b) 19 | { 20 | if (!CheckTokenMembership(NULL, admin_group, &b)) 21 | b = FALSE; 22 | FreeSid(admin_group); 23 | } 24 | return b; 25 | } 26 | 27 | static BOOL 28 | relaunch_elevated(void) 29 | { 30 | WCHAR prog[MAX_PATH]; 31 | GetModuleFileNameW(NULL, prog, MAX_PATH); 32 | 33 | SHELLEXECUTEINFOW sei = { 0 }; 34 | sei.cbSize = sizeof(sei); 35 | sei.lpVerb = L"runas"; 36 | sei.lpFile = prog; 37 | sei.lpParameters = nk.cmdline; 38 | sei.nShow = SW_SHOWDEFAULT; 39 | 40 | if (!ShellExecuteExW(&sei)) 41 | return FALSE; 42 | nkctx_fini(0); 43 | } 44 | 45 | void 46 | ui_qemu_dir(struct nk_context* ctx) 47 | { 48 | if (!is_admin()) 49 | { 50 | nk_layout_row_dynamic(ctx, 0, 1); 51 | if (nk_button_ex(ctx, GET_PNG(IDR_PNG_ADMIN), ZTXT(ZTXT_WARN_NOT_ADMIN))) 52 | relaunch_elevated(); 53 | } 54 | 55 | nk_layout_row_dynamic(ctx, 0, 1); 56 | nk_image_label(ctx, GET_PNG(IDR_PNG_QEMU), ZTXT(ZTXT_QEMU)); 57 | nk_layout_row(ctx, NK_DYNAMIC, 0, 3, (float[3]) { 0.2f, 0.8f - nk.sq, nk.sq }); 58 | nk_space_label(ctx, ZTXT(ZTXT_PATH)); 59 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->qemu_dir, MAX_PATH, NULL); 60 | if (nk_button_image(ctx, GET_PNG(IDR_PNG_DIR))) 61 | ui_open_dir(nk.ini->qemu_dir, MAX_PATH); 62 | 63 | if (nk.show_warning == nk_false) 64 | nk.show_warning = check_path_invalid(nk.ini->qemu_dir); 65 | 66 | nk_layout_row(ctx, NK_DYNAMIC, 0, 3, (float[3]) { 0.2f, 0.4f, 0.4f }); 67 | nk_space_label(ctx, ZTXT(ZTXT_ARCH)); 68 | UI_OPTION("x86_64", nk.ini->qemu_arch, ZEMU_QEMU_ARCH_X64); 69 | UI_OPTION("arm64", nk.ini->qemu_arch, ZEMU_QEMU_ARCH_AA64); 70 | nk.ini->cur = &nk.ini->profile[nk.ini->qemu_arch]; 71 | } 72 | -------------------------------------------------------------------------------- /src/ui_fw.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | #include "ui.h" 6 | #include "gettext.h" 7 | 8 | void 9 | ui_qemu_fw(struct nk_context* ctx) 10 | { 11 | nk_layout_row_dynamic(ctx, 0, 1); 12 | nk_image_label(ctx, GET_PNG(IDR_PNG_FIRMWARE), ZTXT(ZTXT_FIRMWARE)); 13 | 14 | nk_layout_row(ctx, NK_DYNAMIC, 0, 4, (float[4]) { 0.2f, 0.2f, 0.2f, 0.2f }); 15 | nk_space_label(ctx, ZTXT(ZTXT_TYPE)); 16 | switch (nk.ini->qemu_arch) 17 | { 18 | case ZEMU_QEMU_ARCH_X64: 19 | { 20 | UI_OPTION("BIOS", nk.ini->cur->fw, ZEMU_FW_X86_BIOS); 21 | UI_OPTION("IA32 EFI", nk.ini->cur->fw, ZEMU_FW_X86_EFI); 22 | UI_OPTION("X64 EFI", nk.ini->cur->fw, ZEMU_FW_X64_EFI); 23 | break; 24 | } 25 | case ZEMU_QEMU_ARCH_AA64: 26 | { 27 | UI_OPTION("ARM64 EFI", nk.ini->cur->fw, ZEMU_FW_AA64_EFI); 28 | UI_OPTION("ARM32 EFI", nk.ini->cur->fw, ZEMU_FW_ARM32_EFI); 29 | nk_spacer(ctx); 30 | break; 31 | } 32 | default: 33 | nk_label(ctx, ZTXT(ZTXT_UNSUPPORTED), NK_TEXT_CENTERED); 34 | nk_spacer(ctx); 35 | nk_spacer(ctx); 36 | } 37 | nk_layout_row(ctx, NK_DYNAMIC, 0, 5, (float[5]) { 0.2f, 0.2f, 0.2f, 0.2f, 0.2f }); 38 | nk_space_label(ctx, ZTXT(ZTXT_OPTIONS)); 39 | nk_checkbox_label(ctx, ZTXT(ZTXT_PFLASH), &nk.ini->cur->pflash); 40 | nk_checkbox_label(ctx, ZTXT(ZTXT_BOOT_MENU), &nk.ini->cur->fw_menu); 41 | #ifdef ENABLE_SPLASH_TIMEOUT 42 | nk_label(ctx, ZTXT(ZTXT_TIMEOUT), NK_TEXT_RIGHT); 43 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->cur->fw_timeout, OPT_SZ, nk_filter_decimal); 44 | #else 45 | nk_spacer(ctx); 46 | nk_spacer(ctx); 47 | #endif 48 | } 49 | -------------------------------------------------------------------------------- /src/ui_hdb.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | #include "ui.h" 6 | #include "dev.h" 7 | #include "gettext.h" 8 | 9 | static struct nk_image imgs[ZEMU_DEV_MAX]; 10 | static const char* names[ZEMU_DEV_MAX]; 11 | static LPCWSTR filters[ZEMU_DEV_MAX] = { FILTER_VHD, FILTER_ISO }; 12 | 13 | void 14 | ui_qemu_hdb(struct nk_context* ctx) 15 | { 16 | imgs[ZEMU_DEV_HD] = GET_PNG(IDR_PNG_DISK), 17 | imgs[ZEMU_DEV_CD] = GET_PNG(IDR_PNG_CD); 18 | names[ZEMU_DEV_HD] = ZTXT(ZTXT_HARD_DISK); 19 | names[ZEMU_DEV_CD] = ZTXT(ZTXT_CD_ROM); 20 | if (nk.ini->add_dev_count > MAX_ADD_DEV) 21 | nk.ini->add_dev_count = MAX_ADD_DEV; 22 | nk_layout_row(ctx, NK_DYNAMIC, 0, 3, (float[3]) { 1.0f - 2 * nk.sq, nk.sq, nk.sq }); 23 | nk_image_label(ctx, GET_PNG(IDR_PNG_STORAGE), ZTXT(ZTXT_ADDITIONAL)); 24 | if (nk.ini->add_dev_count == MAX_ADD_DEV) 25 | nk_widget_disable_begin(ctx); 26 | if (nk_menu_begin_image_ex(ctx, "#ADD_DEV", GET_PNG(IDR_PNG_ADD), nk_vec2(200,200))) 27 | { 28 | nk_layout_row_dynamic(ctx, 0, 1); 29 | if (nk_menu_item_image_label(ctx, GET_PNG(IDR_PNG_DISK), ZTXT(ZTXT_HARD_DISK), NK_TEXT_RIGHT)) 30 | { 31 | nk.ini->add_dev[nk.ini->add_dev_count].type = ZEMU_DEV_HD; 32 | nk.ini->add_dev[nk.ini->add_dev_count].is_active = nk_true; 33 | nk.ini->add_dev[nk.ini->add_dev_count].attr.snapshot = nk_true; 34 | nk.ini->add_dev_count++; 35 | } 36 | if (nk_menu_item_image_label(ctx, GET_PNG(IDR_PNG_CD), ZTXT(ZTXT_CD_ROM), NK_TEXT_RIGHT)) 37 | { 38 | nk.ini->add_dev[nk.ini->add_dev_count].type = ZEMU_DEV_CD; 39 | nk.ini->add_dev[nk.ini->add_dev_count].is_active = nk_true; 40 | nk.ini->add_dev[nk.ini->add_dev_count].attr.snapshot = nk_true; 41 | nk.ini->add_dev_count++; 42 | } 43 | nk_menu_end(ctx); 44 | } 45 | if (nk.ini->add_dev_count == MAX_ADD_DEV) 46 | nk_widget_disable_end(ctx); 47 | if (nk.ini->add_dev_count == 0) 48 | nk_widget_disable_begin(ctx); 49 | if (nk_button_image(ctx, GET_PNG(IDR_PNG_REMOVE))) 50 | nk.ini->add_dev_count--; 51 | if (nk.ini->add_dev_count == 0) 52 | nk_widget_disable_end(ctx); 53 | 54 | for (size_t i = 0; i < nk.ini->add_dev_count; i++) 55 | { 56 | ZEMU_ADD_DEV* dev = &nk.ini->add_dev[i]; 57 | BOOL is_cd = (dev->type == ZEMU_DEV_CD) ? TRUE : FALSE; 58 | nk_layout_row(ctx, NK_DYNAMIC, 0, 5, (float[5]) { nk.sq, 0.2f - nk.sq, 0.2f, 0.2f, 0.4f }); 59 | ui_dev_button(ctx, imgs[dev->type], names[dev->type], &dev->is_active); 60 | 61 | if (!dev->is_active) 62 | nk_widget_disable_begin(ctx); 63 | 64 | UI_OPTION(ZTXT(ZTXT_FILE), dev->is_device, nk_false); 65 | UI_OPTION(ZTXT(ZTXT_DEVICE), dev->is_device, nk_true); 66 | if (is_cd) 67 | nk_spacer(ctx); 68 | else 69 | nk_checkbox_label(ctx, ZTXT(ZTXT_SNAPSHOT), &dev->attr.snapshot); 70 | 71 | nk_layout_row(ctx, NK_DYNAMIC, 0, 3, (float[3]) { 0.2f, 0.8f - nk.sq, nk.sq }); 72 | if (dev->is_device) 73 | { 74 | if (nk.ini->d_info[dev->type] == NULL) 75 | nk.ini->d_count[dev->type] = get_disk_list(is_cd, &nk.ini->d_info[dev->type]); 76 | 77 | if (dev->id >= nk.ini->d_count[dev->type]) 78 | dev->id = 0; 79 | 80 | nk_space_label(ctx, ZTXT(ZTXT_DEVICE)); 81 | 82 | if (nk.ini->d_count[dev->type] == 0) 83 | nk_label(ctx, ZTXT(ZTXT_NO_DEVICE), NK_TEXT_CENTERED); 84 | else 85 | dev->id = nk_disk_list(ctx, nk.ini->d_info[dev->type], nk.ini->d_count[dev->type], 86 | dev->id, (int)nk.title_height); 87 | if (nk_button_image(ctx, GET_PNG(IDR_PNG_REFRESH))) 88 | { 89 | free(nk.ini->d_info[dev->type]); 90 | nk.ini->d_info[dev->type] = NULL; 91 | nk.ini->d_count[dev->type] = 0; 92 | } 93 | } 94 | else 95 | { 96 | nk_space_label(ctx, ZTXT(ZTXT_FILE)); 97 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, dev->path, MAX_PATH, NULL); 98 | if (nk_button_image(ctx, GET_PNG(IDR_PNG_DIR))) 99 | ui_open_file(dev->path, MAX_PATH, filters[dev->type]); 100 | 101 | if (nk.show_warning == nk_false) 102 | nk.show_warning = check_path_invalid(dev->path); 103 | } 104 | 105 | if (!dev->is_active) 106 | nk_widget_disable_end(ctx); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/ui_mem.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ini.h" 5 | #include "ui.h" 6 | #include "gettext.h" 7 | 8 | static const char* edit_mem_list[] = 9 | { 10 | "256", "512", "1024", "2048", "4096", "8192", 11 | }; 12 | 13 | void 14 | ui_qemu_mem(struct nk_context* ctx) 15 | { 16 | char buf[48]; 17 | nk_layout_row_dynamic(ctx, 0, 1); 18 | nk_image_label(ctx, GET_PNG(IDR_PNG_MEMORY), ZTXT(ZTXT_MEMORY)); 19 | nk_layout_row(ctx, NK_DYNAMIC, 0, 5, (float[5]) { 0.2f, 0.2f - nk.sq, nk.sq, 0.1f, 0.5f }); 20 | nk_space_label(ctx, ZTXT(ZTXT_SIZE)); 21 | nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, nk.ini->cur->mem, OPT_SZ, nk_filter_decimal); 22 | if (nk_menu_begin_image_ex(ctx, "#EDIT_MEM", GET_PNG(IDR_PNG_DOWN), nk_vec2(100, 300))) 23 | { 24 | nk_layout_row_dynamic(ctx, 0, 1); 25 | for (size_t i = 0; i < ARRAYSIZE(edit_mem_list); i++) 26 | { 27 | if (nk_menu_item_label(ctx, edit_mem_list[i], NK_TEXT_LEFT)) 28 | strcpy_s(nk.ini->cur->mem, OPT_SZ, edit_mem_list[i]); 29 | } 30 | nk_menu_end(ctx); 31 | } 32 | nk_label(ctx, "MB", NK_TEXT_LEFT); 33 | strcpy_s(buf, 48, get_human_size(nk.statex.ullAvailPhys, human_units, 1024)); 34 | nk_labelf(ctx, NK_TEXT_RIGHT, "%lu%% (%s / %s)", nk.statex.dwMemoryLoad, 35 | buf, get_human_size(nk.statex.ullTotalPhys, human_units, 1024)); 36 | if (strtoul(nk.ini->cur->mem, NULL, 10) + 64 >= nk.statex.ullAvailPhys / 1024 / 1024) 37 | { 38 | nk_layout_row_dynamic(ctx, 0, 1); 39 | nk_image_label(ctx, GET_PNG(IDR_PNG_WARN), ZTXT(ZTXT_WARN_OUT_OF_MEM)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/wim.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "nkctx.h" 4 | #include "ui.h" 5 | #include "ini.h" 6 | 7 | #pragma pack(1) 8 | 9 | struct wim_resource_header 10 | { 11 | uint64_t zlen_flags; 12 | uint64_t offset; 13 | uint64_t len; 14 | }; 15 | 16 | enum wim_header_flags 17 | { 18 | WIM_HDR_COMPRESSED = 0x00000002, 19 | WIM_HDR_XPRESS = 0x00020000, 20 | WIM_HDR_LZX = 0x00040000, 21 | WIM_HDR_LZMS = 0x00080000, 22 | }; 23 | 24 | struct wim_header 25 | { 26 | uint8_t signature[8]; // "MSWIM\0\0" 27 | uint32_t header_len; 28 | uint32_t version; 29 | uint32_t flags; 30 | uint32_t chunk_len; 31 | uint8_t guid[16]; 32 | uint16_t part; 33 | uint16_t parts; 34 | uint32_t images; 35 | struct wim_resource_header lookup; 36 | struct wim_resource_header xml; 37 | struct wim_resource_header boot; 38 | uint32_t boot_index; 39 | struct wim_resource_header integrity; 40 | uint8_t reserved[60]; 41 | }; 42 | 43 | #pragma pack() 44 | 45 | #define INITRD_MAX_SIZE (2ULL * 1024 * 1024 * 1024) 46 | 47 | nk_bool 48 | ui_check_wim_header(uint32_t* num_images, uint32_t* boot) 49 | { 50 | *num_images = 0; 51 | *boot = 0; 52 | if (!nk.ini->boot_wim[0]) 53 | return nk_true; 54 | struct wim_header hdr = { 0 }; 55 | uint64_t size = get_file_header(rel_to_abs(nk.ini->boot_wim), 56 | &hdr, sizeof(struct wim_header)); 57 | if (size == 0 || size >= INITRD_MAX_SIZE) 58 | return nk_false; 59 | if (memcmp(hdr.signature, "MSWIM\0\0", 8) != 0) 60 | return nk_false; 61 | if (hdr.flags & WIM_HDR_LZMS) 62 | return nk_false; 63 | *num_images = hdr.images; 64 | *boot = hdr.boot_index; 65 | if (hdr.boot_index == 0) 66 | return nk_false; 67 | return nk_true; 68 | } 69 | -------------------------------------------------------------------------------- /wimbcd/bcd.bat: -------------------------------------------------------------------------------- 1 | rd /s /q build 2 | md build 3 | cd build 4 | 5 | set bcd=/store bcd 6 | 7 | set guidwim={19260817-6666-8888-abcd-000000000000} 8 | 9 | bcdedit /createstore bcd 10 | bcdedit %bcd% /create {bootmgr} /d "Wim" 11 | bcdedit %bcd% /set {bootmgr} locale en-us 12 | bcdedit %bcd% /set {bootmgr} timeout 1 13 | bcdedit %bcd% /set {bootmgr} displaybootmenu false 14 | 15 | bcdedit %bcd% /create {ramdiskoptions} 16 | bcdedit %bcd% /set {ramdiskoptions} ramdisksdidevice "boot" 17 | bcdedit %bcd% /set {ramdiskoptions} ramdisksdipath \boot\boot.sdi 18 | 19 | bcdedit %bcd% /create %guidwim% /d "NT6+ WIM" /application OSLOADER 20 | bcdedit %bcd% /set %guidwim% device ramdisk=[boot]\boot.wim,{ramdiskoptions} 21 | bcdedit %bcd% /set %guidwim% osdevice ramdisk=[boot]\boot.wim,{ramdiskoptions} 22 | bcdedit %bcd% /set %guidwim% winpe true 23 | bcdedit %bcd% /set %guidwim% testsigning true 24 | bcdedit %bcd% /set %guidwim% detecthal true 25 | bcdedit %bcd% /set %guidwim% nointegritychecks true 26 | 27 | bcdedit %bcd% /set {bootmgr} displayorder %guidwim% /addlast 28 | bcdedit %bcd% /default %guidwim% 29 | 30 | cd .. 31 | -------------------------------------------------------------------------------- /wimcpio/BCD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimcpio/BCD -------------------------------------------------------------------------------- /wimcpio/boot.sdi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimcpio/boot.sdi -------------------------------------------------------------------------------- /wimcpio/bootmgr.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimcpio/bootmgr.exe -------------------------------------------------------------------------------- /wimcpio/wgl4_boot.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimcpio/wgl4_boot.ttf -------------------------------------------------------------------------------- /wimhda/BCD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/BCD -------------------------------------------------------------------------------- /wimhda/_.QEMU_HDA._: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/_.QEMU_HDA._ -------------------------------------------------------------------------------- /wimhda/boot.sdi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/boot.sdi -------------------------------------------------------------------------------- /wimhda/bootaa64.efi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/bootaa64.efi -------------------------------------------------------------------------------- /wimhda/bootia32.efi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/bootia32.efi -------------------------------------------------------------------------------- /wimhda/bootx64.efi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/bootx64.efi -------------------------------------------------------------------------------- /wimhda/wgl4_boot.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1ive/ZenEmu/c3ed3f12ca2f69d2fe6984f02883fbfe14c8da39/wimhda/wgl4_boot.ttf -------------------------------------------------------------------------------- /wimldr/.gitignore: -------------------------------------------------------------------------------- 1 | *.s 2 | *.o 3 | *.a 4 | *.elf 5 | *.map 6 | *.efi 7 | wimldr 8 | wimldr.ia32 9 | wimldr.x64 10 | wimldr.aa64 11 | elf2efi32 12 | elf2efi64 13 | -------------------------------------------------------------------------------- /wimldr/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef _ASSERT_H 2 | #define _ASSERT_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Assertions 27 | * 28 | */ 29 | 30 | #include "wimboot.h" 31 | 32 | #define assert(x) do { \ 33 | if ( DEBUG && ! (x) ) { \ 34 | die ( "Assertion failed at %s line %d: %s\n", \ 35 | __FILE__, __LINE__, #x ); \ 36 | } \ 37 | } while ( 0 ) 38 | 39 | #endif /* _ASSERT_H */ 40 | -------------------------------------------------------------------------------- /wimldr/bios.lds: -------------------------------------------------------------------------------- 1 | ENTRY ( main ) 2 | 3 | SECTIONS { 4 | 5 | /* Align sections to allow for page-level runtime protection */ 6 | alignment = 0x1000; 7 | 8 | /* Virtual addresses start at 0x20000 */ 9 | . = 0x20000; 10 | _start = .; 11 | 12 | /* bootmgr.exe hardcodes the address 0x30000 for use as a 13 | * buffer accessible by real-mode code. We can't fit 14 | * everything below this region, so we explicitly verify that 15 | * all BIOS-mode code and initialised data fits below this 16 | * region, and choose to place .bss above it. 17 | */ 18 | _forbidden_start = 0x30000; 19 | _forbidden_end = 0x40000; 20 | 21 | /* bzImage prefix */ 22 | _prefix_pos = 0; 23 | .prefix : AT ( _prefix_pos ) { 24 | _prefix = .; 25 | *(.prefix) 26 | *(.prefix.*) 27 | _eprefix = .; 28 | } 29 | _prefix_len = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix ); 30 | 31 | /* Real-mode uninitialised data section */ 32 | .bss16 ( NOLOAD ) : { 33 | _bss16 = .; 34 | *(.stack16) 35 | *(.stack16.*) 36 | *(.bss16) 37 | *(.bss16.*) 38 | . = ALIGN ( alignment ); 39 | _ebss16 = .; 40 | } 41 | _bss16_len = ABSOLUTE ( _ebss16 ) - ABSOLUTE ( _bss16 ); 42 | 43 | /* Data (and 16-bit BIOS text) section */ 44 | _payload_pos = ( _prefix_pos + _prefix_len ); 45 | _data_pos = _payload_pos; 46 | .data : AT ( _data_pos ) { 47 | _data = .; 48 | _payload = .; 49 | /* Portions that must be accessible in 16-bit modes */ 50 | *(.text16) 51 | *(.text16.*) 52 | *(.rodata16) 53 | *(.rodata16.*) 54 | *(.data16) 55 | *(.data16.*) 56 | /* Portions that need not be accessible in 16-bit modes */ 57 | *(.rodata) 58 | *(.rodata.*) 59 | *(.data) 60 | *(.data.*) 61 | *(.got) 62 | *(.got.*) 63 | . = ALIGN ( alignment ); 64 | _edata = .; 65 | } 66 | _data_len = ABSOLUTE ( _edata ) - ABSOLUTE ( _data ); 67 | 68 | /* Text (excluding 16-bit BIOS text) section */ 69 | _text_pos = ( _data_pos + _data_len ); 70 | .text : AT ( _text_pos ) { 71 | _text = .; 72 | *.i386.*(.text) 73 | *.i386.*(.text.*) 74 | ASSERT ( ABSOLUTE ( . ) <= ABSOLUTE ( _forbidden_start ), 75 | "Binary is too large" ); 76 | *(.text) 77 | *(.text.*) 78 | . = ALIGN ( alignment ); 79 | _epayload = .; 80 | _etext = .; 81 | } 82 | _text_len = ABSOLUTE ( _etext ) - ABSOLUTE ( _text ); 83 | _payload_len = ABSOLUTE ( _epayload ) - ABSOLUTE ( _payload ); 84 | 85 | /* Uninitialised data section */ 86 | .bss ( NOLOAD ) : { 87 | _bss = .; 88 | . = ABSOLUTE ( _forbidden_end ); 89 | *(.bss) 90 | *(.bss.*) 91 | *(COMMON) 92 | *(.stack) 93 | *(.stack.*) 94 | . = ALIGN ( alignment ); 95 | _ebss = .; 96 | } 97 | _bss_len = ABSOLUTE ( _ebss ) - ABSOLUTE ( _bss ); 98 | 99 | /* Secure Boot Advanced Targeting (SBAT) section */ 100 | _sbat_pos = ( _text_pos + _text_len ); 101 | .sbat : AT ( _sbat_pos ) { 102 | _sbat = .; 103 | *(.sbat) 104 | *(.sbat.*) 105 | _esbat = .; 106 | } 107 | _sbat_len = ABSOLUTE ( _esbat ) - ABSOLUTE ( _sbat ); 108 | 109 | _end = .; 110 | 111 | /* Symbols required by i386.x86_64 objects */ 112 | __i386__start = _start; 113 | __i386__end = _end; 114 | 115 | /DISCARD/ : { 116 | *(.comment) 117 | *(.comment.*) 118 | *(.note) 119 | *(.note.*) 120 | *(.eh_frame) 121 | *(.eh_frame.*) 122 | *(.rel) 123 | *(.rel.*) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /wimldr/cmdline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Command line 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "wimboot.h" 34 | #include "cmdline.h" 35 | 36 | static struct nt_args args = { 37 | .testmode = NTARG_BOOL_FALSE, 38 | .minint = NTARG_BOOL_FALSE, 39 | .rawwim = NTARG_BOOL_FALSE, 40 | .gui = NTARG_BOOL_FALSE, 41 | .pause = NTARG_BOOL_FALSE, 42 | .linear = NTARG_BOOL_FALSE, 43 | .index = 0, 44 | }; 45 | 46 | struct nt_args *nt_cmdline; 47 | 48 | static uint8_t 49 | convert_bool ( const char *str ) { 50 | uint8_t value = NTARG_BOOL_FALSE; 51 | if ( ! str || 52 | strcasecmp ( str, "yes" ) == 0 || 53 | strcasecmp ( str, "on" ) == 0 || 54 | strcasecmp ( str, "true" ) == 0 || 55 | strcasecmp ( str, "1" ) == 0 ) 56 | value = NTARG_BOOL_TRUE; 57 | return value; 58 | } 59 | 60 | /** 61 | * Process command line 62 | * 63 | * @v cmdline Command line 64 | */ 65 | void process_cmdline ( char *cmdline ) { 66 | char *tmp = cmdline; 67 | char *key; 68 | char *value; 69 | char *endp; 70 | char chr; 71 | 72 | nt_cmdline = &args; 73 | 74 | /* Do nothing if we have no command line */ 75 | if ( ( cmdline == NULL ) || ( cmdline[0] == '\0' ) ) 76 | return; 77 | 78 | /* Show command line */ 79 | printf ("Command line: \"%s\"\n", cmdline); 80 | 81 | /* Parse command line */ 82 | while ( *tmp ) { 83 | 84 | /* Skip whitespace */ 85 | while ( isspace ( *tmp ) ) 86 | tmp++; 87 | 88 | /* Find value (if any) and end of this argument */ 89 | key = tmp; 90 | value = NULL; 91 | while ( ( chr = *tmp ) ) { 92 | if ( isspace ( chr ) ) { 93 | *(tmp++) = '\0'; 94 | break; 95 | } else if ( ( chr == '=' ) && ( ! value ) ) { 96 | *(tmp++) = '\0'; 97 | value = tmp; 98 | } else { 99 | tmp++; 100 | } 101 | } 102 | 103 | /* Process this argument */ 104 | if ( strcmp ( key, "testmode" ) == 0 ) { 105 | args.testmode = convert_bool ( value ); 106 | } else if ( strcmp ( key, "minint" ) == 0 ) { 107 | args.minint = convert_bool ( value ); 108 | } else if ( strcmp ( key, "rawwim" ) == 0 ) { 109 | args.rawwim = convert_bool ( value ); 110 | } else if ( strcmp ( key, "gui" ) == 0 ) { 111 | args.gui = convert_bool ( value ); 112 | } else if ( strcmp ( key, "pause" ) == 0 ) { 113 | args.pause = convert_bool ( value ); 114 | } else if ( strcmp ( key, "linear" ) == 0 ) { 115 | args.linear = convert_bool ( value ); 116 | } else if ( strcmp ( key, "index" ) == 0 ) { 117 | if ( ( ! value ) || ( ! value[0] ) ) 118 | die ( "Argument \"index\" needs a value\n" ); 119 | args.index = strtoul ( value, &endp, 0 ); 120 | if ( *endp ) 121 | die ( "Invalid index \"%s\"\n", value ); 122 | } else if ( strcmp ( key, "addr" ) == 0 ) { 123 | if ( ( ! value ) || ( ! value[0] ) ) 124 | die ( "Argument \"addr\" needs a value\n" ); 125 | args.ldr_addr = strtoul ( value, &endp, 0 ); 126 | args.ldr_data = ( void * ) args.ldr_addr; 127 | if ( *endp ) 128 | die ( "Invalid addr \"%s\"\n", value ); 129 | } else if ( strcmp ( key, "len" ) == 0 ) { 130 | if ( ( ! value ) || ( ! value[0] ) ) 131 | die ( "Argument \"len\" needs a value\n" ); 132 | args.ldr_len = strtoul ( value, &endp, 0 ); 133 | if ( *endp ) 134 | die ( "Invalid len \"%s\"\n", value ); 135 | } else if ( strcmp ( key, "initrd" ) == 0 ) { 136 | /* Ignore this keyword to allow for use with QEMU */ 137 | } else if ( key == cmdline ) { 138 | /* Ignore unknown initial arguments, which may 139 | * be the program name. 140 | */ 141 | } else { 142 | die ( "Unrecognised argument \"%s%s%s\"\n", key, 143 | ( value ? "=" : "" ), ( value ? value : "" ) ); 144 | } 145 | 146 | /* Undo modifications to command line */ 147 | if ( chr ) 148 | tmp[-1] = chr; 149 | if ( value ) 150 | value[-1] = '='; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /wimldr/cmdline.h: -------------------------------------------------------------------------------- 1 | #ifndef _CMDLINE_H 2 | #define _CMDLINE_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Command line 27 | * 28 | */ 29 | 30 | #include 31 | 32 | #define NTARG_BOOL_TRUE 1 33 | #define NTARG_BOOL_FALSE 0 34 | 35 | struct nt_args { 36 | uint8_t testmode; 37 | uint8_t minint; 38 | uint8_t rawwim; 39 | uint8_t gui; 40 | uint8_t pause; 41 | uint8_t linear; 42 | unsigned int index; 43 | /* QEMU Loader Data */ 44 | void *ldr_data; 45 | intptr_t ldr_addr; 46 | unsigned int ldr_len; 47 | }; 48 | 49 | extern struct nt_args *nt_cmdline; 50 | 51 | extern void process_cmdline ( char *cmdline ); 52 | 53 | #endif /* _CMDLINE_H */ 54 | -------------------------------------------------------------------------------- /wimldr/compiler.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPILER_H 2 | #define _COMPILER_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Global compiler definitions 27 | * 28 | */ 29 | 30 | /* Force visibility of all symbols to "hidden", i.e. inform gcc that 31 | * all symbol references resolve strictly within our final binary. 32 | * This avoids unnecessary PLT/GOT entries on x86_64. 33 | * 34 | * This is a stronger claim than specifying "-fvisibility=hidden", 35 | * since it also affects symbols marked with "extern". 36 | */ 37 | #ifndef ASSEMBLY 38 | #if __GNUC__ >= 4 39 | #pragma GCC visibility push(hidden) 40 | #endif 41 | #endif /* ASSEMBLY */ 42 | 43 | #endif /* _COMPILER_H */ 44 | -------------------------------------------------------------------------------- /wimldr/cookie.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Stack cookie 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | 29 | /** Stack cookie */ 30 | unsigned long __stack_chk_guard; 31 | 32 | /** 33 | * Construct stack cookie value 34 | * 35 | */ 36 | static __attribute__ (( noinline )) unsigned long make_cookie ( void ) { 37 | union { 38 | struct { 39 | uint32_t eax; 40 | uint32_t edx; 41 | } __attribute__ (( packed )); 42 | uint64_t raw; 43 | } u; 44 | unsigned long cookie; 45 | 46 | /* We have no viable source of entropy. Use the CPU timestamp 47 | * counter, which will have at least some minimal randomness 48 | * in the low bits by the time we are invoked. 49 | */ 50 | #if defined(__i386__) || defined(__x86_64__) 51 | __asm__ ( "rdtsc" : "=a" ( u.eax ), "=d" ( u.edx ) ); 52 | #elif defined(__aarch64__) 53 | __asm__ ( "mrs %0, CNTVCT_EL0\n\t" : "=r" ( u.raw ) ); 54 | #endif 55 | cookie = u.raw; 56 | 57 | /* Ensure that the value contains a NUL byte, to act as a 58 | * runaway string terminator. Construct the NUL using a shift 59 | * rather than a mask, to avoid losing valuable entropy in the 60 | * lower-order bits. 61 | */ 62 | cookie <<= 8; 63 | 64 | return cookie; 65 | } 66 | 67 | /** 68 | * Initialise stack cookie 69 | * 70 | * This function must not itself use stack guard 71 | */ 72 | void init_cookie ( void ) { 73 | 74 | /* Set stack cookie value 75 | * 76 | * This function must not itself use stack protection, since 77 | * the change in the stack guard value would trigger a false 78 | * positive. 79 | * 80 | * There is unfortunately no way to annotate a function to 81 | * exclude the use of stack protection. We must therefore 82 | * rely on correctly anticipating the compiler's decision on 83 | * the use of stack protection. 84 | */ 85 | __stack_chk_guard = make_cookie(); 86 | } 87 | 88 | /** 89 | * Abort on stack check failure 90 | * 91 | */ 92 | void __stack_chk_fail ( void ) { 93 | 94 | /* Abort program */ 95 | die ( "Stack check failed\n" ); 96 | } 97 | -------------------------------------------------------------------------------- /wimldr/cpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * CPIO archives 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "wimboot.h" 33 | #include "cpio.h" 34 | 35 | /** 36 | * Align CPIO length to nearest dword 37 | * 38 | * @v len Length 39 | * @ret len Aligned length 40 | */ 41 | static size_t cpio_align ( size_t len ) { 42 | return ( ( len + 0x03 ) & ~0x03 ); 43 | } 44 | 45 | /** 46 | * Parse CPIO field value 47 | * 48 | * @v field ASCII field 49 | * @ret value Field value 50 | */ 51 | static unsigned long cpio_value ( const char *field ) { 52 | char buf[9]; 53 | 54 | memcpy ( buf, field, ( sizeof ( buf ) - 1 ) ); 55 | buf[ sizeof ( buf ) - 1 ] = '\0'; 56 | return strtoul ( buf, NULL, 16 ); 57 | } 58 | 59 | /** 60 | * Extract files from CPIO archive 61 | * 62 | * @v data CPIO archive 63 | * @v len Maximum length of CPIO archive 64 | * @v file File handler 65 | * @ret rc Return status code 66 | */ 67 | int cpio_extract ( void *data, size_t len, 68 | int ( * file ) ( const char *name, void *data, 69 | size_t len ) ) { 70 | const struct cpio_header *cpio; 71 | const uint32_t *pad; 72 | const char *file_name; 73 | void *file_data; 74 | size_t file_name_len; 75 | size_t file_len; 76 | size_t cpio_len; 77 | int rc; 78 | 79 | while ( 1 ) { 80 | 81 | /* Skip over any padding */ 82 | while ( len >= sizeof ( *pad ) ) { 83 | pad = data; 84 | if ( *pad ) 85 | break; 86 | data += sizeof ( *pad ); 87 | len -= sizeof ( *pad ); 88 | } 89 | 90 | /* Stop if we have reached the end of the archive */ 91 | if ( ! len ) 92 | return 0; 93 | 94 | /* Sanity check */ 95 | if ( len < sizeof ( *cpio ) ) { 96 | DBG ( "Truncated CPIO header\n" ); 97 | return -1; 98 | } 99 | cpio = data; 100 | 101 | /* Check magic */ 102 | if ( memcmp ( cpio->c_magic, CPIO_MAGIC, 103 | sizeof ( cpio->c_magic ) ) != 0 ) { 104 | DBG ( "Bad CPIO magic\n" ); 105 | return -1; 106 | } 107 | 108 | /* Extract file parameters */ 109 | file_name = ( ( void * ) ( cpio + 1 ) ); 110 | file_name_len = cpio_value ( cpio->c_namesize ); 111 | file_data = ( data + cpio_align ( sizeof ( *cpio ) + 112 | file_name_len ) ); 113 | file_len = cpio_value ( cpio->c_filesize ); 114 | cpio_len = ( file_data + file_len - data ); 115 | if ( cpio_len < len ) 116 | cpio_len = cpio_align ( cpio_len ); 117 | if ( cpio_len > len ) { 118 | DBG ( "Truncated CPIO file\n" ); 119 | return -1; 120 | } 121 | 122 | /* If we reach the trailer, we're done */ 123 | if ( strcmp ( file_name, CPIO_TRAILER ) == 0 ) 124 | return 0; 125 | 126 | /* Process file */ 127 | if ( ( rc = file ( file_name, file_data, file_len ) ) != 0 ) 128 | return rc; 129 | 130 | /* Move to next file */ 131 | data += cpio_len; 132 | len -= cpio_len; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /wimldr/cpio.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPIO_H 2 | #define _CPIO_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * CPIO archives 27 | * 28 | */ 29 | 30 | #include 31 | 32 | /** A CPIO archive header 33 | * 34 | * All field are hexadecimal ASCII numbers padded with '0' on the 35 | * left to the full width of the field. 36 | */ 37 | struct cpio_header { 38 | /** The string "070701" or "070702" */ 39 | char c_magic[6]; 40 | /** File inode number */ 41 | char c_ino[8]; 42 | /** File mode and permissions */ 43 | char c_mode[8]; 44 | /** File uid */ 45 | char c_uid[8]; 46 | /** File gid */ 47 | char c_gid[8]; 48 | /** Number of links */ 49 | char c_nlink[8]; 50 | /** Modification time */ 51 | char c_mtime[8]; 52 | /** Size of data field */ 53 | char c_filesize[8]; 54 | /** Major part of file device number */ 55 | char c_maj[8]; 56 | /** Minor part of file device number */ 57 | char c_min[8]; 58 | /** Major part of device node reference */ 59 | char c_rmaj[8]; 60 | /** Minor part of device node reference */ 61 | char c_rmin[8]; 62 | /** Length of filename, including final NUL */ 63 | char c_namesize[8]; 64 | /** Checksum of data field if c_magic is 070702, othersize zero */ 65 | char c_chksum[8]; 66 | } __attribute__ (( packed )); 67 | 68 | /** CPIO magic */ 69 | #define CPIO_MAGIC "070701" 70 | 71 | /** CPIO trailer */ 72 | #define CPIO_TRAILER "TRAILER!!!" 73 | 74 | extern int cpio_extract ( void *data, size_t len, 75 | int ( * file ) ( const char *name, void *data, 76 | size_t len ) ); 77 | 78 | #endif /* _CPIO_H */ 79 | -------------------------------------------------------------------------------- /wimldr/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _CTYPE_H 2 | #define _CTYPE_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Character types 27 | * 28 | */ 29 | 30 | static inline int islower ( int c ) { 31 | return ( ( c >= 'a' ) && ( c <= 'z' ) ); 32 | } 33 | 34 | static inline int isupper ( int c ) { 35 | return ( ( c >= 'A' ) && ( c <= 'Z' ) ); 36 | } 37 | 38 | static inline int toupper ( int c ) { 39 | 40 | if ( islower ( c ) ) 41 | c -= ( 'a' - 'A' ); 42 | return c; 43 | } 44 | 45 | extern int isspace ( int c ); 46 | 47 | #endif /* _CTYPE_H */ 48 | -------------------------------------------------------------------------------- /wimldr/die.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Fatal errors 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include "wimboot.h" 30 | #include "efi.h" 31 | 32 | /** 33 | * Handle fatal errors 34 | * 35 | * @v fmt Error message format string 36 | * @v ... Arguments 37 | */ 38 | void die ( const char *fmt, ... ) { 39 | va_list args; 40 | 41 | /* Print message */ 42 | va_start ( args, fmt ); 43 | vprintf ( fmt, args ); 44 | va_end ( args ); 45 | 46 | /* Wait for keypress */ 47 | printf ( "Press a key to reboot..." ); 48 | getchar(); 49 | printf ( "\n" ); 50 | /* Reboot system */ 51 | #ifdef BIOS 52 | reboot(); 53 | #else 54 | EFI_RUNTIME_SERVICES *rs; 55 | rs = efi_systab->RuntimeServices; 56 | rs->ResetSystem ( EfiResetWarm, 0, 0, NULL ); 57 | #endif 58 | 59 | printf ( "Failed to reboot\n" ); 60 | 61 | /* Should be impossible to reach this */ 62 | __builtin_unreachable(); 63 | } 64 | -------------------------------------------------------------------------------- /wimldr/efi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * EFI interface 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | #include "efi.h" 29 | 30 | /** EFI system table */ 31 | EFI_SYSTEM_TABLE *efi_systab; 32 | 33 | /** EFI image handle */ 34 | EFI_HANDLE efi_image_handle; 35 | -------------------------------------------------------------------------------- /wimldr/efi.h: -------------------------------------------------------------------------------- 1 | #ifndef _EFI_H 2 | #define _EFI_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * EFI definitions 27 | * 28 | */ 29 | 30 | /* EFIAPI definition */ 31 | #if __x86_64__ 32 | #define EFIAPI __attribute__ (( ms_abi )) 33 | #else 34 | #define EFIAPI 35 | #endif 36 | 37 | /* EFI headers rudely redefine NULL */ 38 | #undef NULL 39 | 40 | #include "efi/Uefi.h" 41 | #include "efi/Protocol/LoadedImage.h" 42 | 43 | extern EFI_SYSTEM_TABLE *efi_systab; 44 | extern EFI_HANDLE efi_image_handle; 45 | 46 | extern EFI_GUID efi_block_io_protocol_guid; 47 | extern EFI_GUID efi_device_path_protocol_guid; 48 | extern EFI_GUID efi_graphics_output_protocol_guid; 49 | extern EFI_GUID efi_loaded_image_protocol_guid; 50 | extern EFI_GUID efi_simple_file_system_protocol_guid; 51 | extern EFI_GUID efi_file_info_guid; 52 | 53 | #endif /* _EFI_H */ 54 | -------------------------------------------------------------------------------- /wimldr/efi.lds: -------------------------------------------------------------------------------- 1 | ENTRY ( efi_main ) 2 | 3 | SECTIONS { 4 | 5 | /* Align sections to allow for page-level runtime protection */ 6 | alignment = 0x1000; 7 | 8 | /* Virtual addresses start at 0x20000 */ 9 | . = 0x20000; 10 | _start = .; 11 | 12 | /* bzImage prefix */ 13 | _prefix_pos = 0; 14 | .prefix : AT ( _prefix_pos ) { 15 | _prefix = .; 16 | *(.prefix) 17 | *(.prefix.*) 18 | _eprefix = .; 19 | } 20 | _prefix_len = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix ); 21 | 22 | /* Real-mode uninitialised data section */ 23 | .bss16 ( NOLOAD ) : { 24 | _bss16 = .; 25 | *(.stack16) 26 | *(.stack16.*) 27 | *(.bss16) 28 | *(.bss16.*) 29 | . = ALIGN ( alignment ); 30 | _ebss16 = .; 31 | } 32 | _bss16_len = ABSOLUTE ( _ebss16 ) - ABSOLUTE ( _bss16 ); 33 | 34 | /* Data (and 16-bit BIOS text) section */ 35 | _payload_pos = ( _prefix_pos + _prefix_len ); 36 | _data_pos = _payload_pos; 37 | .data : AT ( _data_pos ) { 38 | _data = .; 39 | _payload = .; 40 | /* Portions that must be accessible in 16-bit modes */ 41 | *(.text16) 42 | *(.text16.*) 43 | *(.rodata16) 44 | *(.rodata16.*) 45 | *(.data16) 46 | *(.data16.*) 47 | /* Portions that need not be accessible in 16-bit modes */ 48 | *(.rodata) 49 | *(.rodata.*) 50 | *(.data) 51 | *(.data.*) 52 | *(.got) 53 | *(.got.*) 54 | . = ALIGN ( alignment ); 55 | _edata = .; 56 | } 57 | _data_len = ABSOLUTE ( _edata ) - ABSOLUTE ( _data ); 58 | 59 | /* Text (excluding 16-bit BIOS text) section */ 60 | _text_pos = ( _data_pos + _data_len ); 61 | .text : AT ( _text_pos ) { 62 | _text = .; 63 | *(.text) 64 | *(.text.*) 65 | . = ALIGN ( alignment ); 66 | _epayload = .; 67 | _etext = .; 68 | } 69 | _text_len = ABSOLUTE ( _etext ) - ABSOLUTE ( _text ); 70 | _payload_len = ABSOLUTE ( _epayload ) - ABSOLUTE ( _payload ); 71 | 72 | /* Uninitialised data section */ 73 | .bss ( NOLOAD ) : { 74 | _bss = .; 75 | *(.bss) 76 | *(.bss.*) 77 | *(COMMON) 78 | *(.stack) 79 | *(.stack.*) 80 | . = ALIGN ( alignment ); 81 | _ebss = .; 82 | } 83 | _bss_len = ABSOLUTE ( _ebss ) - ABSOLUTE ( _bss ); 84 | 85 | /* Secure Boot Advanced Targeting (SBAT) section */ 86 | _sbat_pos = ( _text_pos + _text_len ); 87 | .sbat : AT ( _sbat_pos ) { 88 | _sbat = .; 89 | *(.sbat) 90 | *(.sbat.*) 91 | _esbat = .; 92 | } 93 | _sbat_len = ABSOLUTE ( _esbat ) - ABSOLUTE ( _sbat ); 94 | 95 | _end = .; 96 | 97 | /DISCARD/ : { 98 | *(.comment) 99 | *(.comment.*) 100 | *(.note) 101 | *(.note.*) 102 | *(.eh_frame) 103 | *(.eh_frame.*) 104 | *(.rel) 105 | *(.rel.*) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /wimldr/efi/Guid/FileInfo.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.SetInfo() 3 | and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information. 4 | This GUID is defined in UEFI specification. 5 | 6 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
7 | SPDX-License-Identifier: BSD-2-Clause-Patent 8 | 9 | **/ 10 | 11 | #ifndef __FILE_INFO_H__ 12 | #define __FILE_INFO_H__ 13 | 14 | #define EFI_FILE_INFO_ID \ 15 | { \ 16 | 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ 17 | } 18 | 19 | typedef struct { 20 | /// 21 | /// The size of the EFI_FILE_INFO structure, including the Null-terminated FileName string. 22 | /// 23 | UINT64 Size; 24 | /// 25 | /// The size of the file in bytes. 26 | /// 27 | UINT64 FileSize; 28 | /// 29 | /// PhysicalSize The amount of physical space the file consumes on the file system volume. 30 | /// 31 | UINT64 PhysicalSize; 32 | /// 33 | /// The time the file was created. 34 | /// 35 | EFI_TIME CreateTime; 36 | /// 37 | /// The time when the file was last accessed. 38 | /// 39 | EFI_TIME LastAccessTime; 40 | /// 41 | /// The time when the file's contents were last modified. 42 | /// 43 | EFI_TIME ModificationTime; 44 | /// 45 | /// The attribute bits for the file. 46 | /// 47 | UINT64 Attribute; 48 | /// 49 | /// The Null-terminated name of the file. 50 | /// 51 | CHAR16 FileName[1]; 52 | } EFI_FILE_INFO; 53 | 54 | /// 55 | /// The FileName field of the EFI_FILE_INFO data structure is variable length. 56 | /// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to 57 | /// be the size of the data structure without the FileName field. The following macro 58 | /// computes this size correctly no matter how big the FileName array is declared. 59 | /// This is required to make the EFI_FILE_INFO data structure ANSI compilant. 60 | /// 61 | #define SIZE_OF_EFI_FILE_INFO OFFSET_OF (EFI_FILE_INFO, FileName) 62 | 63 | extern EFI_GUID gEfiFileInfoGuid; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /wimldr/efi/Guid/HiiFormMapMethodGuid.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Guid used to identify HII FormMap configuration method. 3 | 4 | Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
5 | SPDX-License-Identifier: BSD-2-Clause-Patent 6 | 7 | @par Revision Reference: 8 | GUID defined in UEFI 2.2 spec. 9 | **/ 10 | 11 | #ifndef __EFI_HII_FORMMAP_GUID_H__ 12 | #define __EFI_HII_FORMMAP_GUID_H__ 13 | 14 | #define EFI_HII_STANDARD_FORM_GUID \ 15 | { 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } } 16 | 17 | extern EFI_GUID gEfiHiiStandardFormGuid; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /wimldr/efi/Guid/PcAnsi.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Terminal Device Path Vendor Guid. 3 | 4 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
5 | SPDX-License-Identifier: BSD-2-Clause-Patent 6 | 7 | @par Revision Reference: 8 | GUIDs defined in UEFI 2.0 spec. 9 | 10 | **/ 11 | 12 | #ifndef __PC_ANSI_H__ 13 | #define __PC_ANSI_H__ 14 | 15 | #define EFI_PC_ANSI_GUID \ 16 | { \ 17 | 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ 18 | } 19 | 20 | #define EFI_VT_100_GUID \ 21 | { \ 22 | 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ 23 | } 24 | 25 | #define EFI_VT_100_PLUS_GUID \ 26 | { \ 27 | 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \ 28 | } 29 | 30 | #define EFI_VT_UTF8_GUID \ 31 | { \ 32 | 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ 33 | } 34 | 35 | #define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \ 36 | { \ 37 | 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \ 38 | } 39 | 40 | #define EFI_SAS_DEVICE_PATH_GUID \ 41 | { \ 42 | 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ 43 | } 44 | 45 | extern EFI_GUID gEfiPcAnsiGuid; 46 | extern EFI_GUID gEfiVT100Guid; 47 | extern EFI_GUID gEfiVT100PlusGuid; 48 | extern EFI_GUID gEfiVTUTF8Guid; 49 | extern EFI_GUID gEfiUartDevicePathGuid; 50 | extern EFI_GUID gEfiSasDevicePathGuid; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /wimldr/efi/Guid/WinCertificate.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | GUID for UEFI WIN_CERTIFICATE structure. 3 | 4 | Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
5 | SPDX-License-Identifier: BSD-2-Clause-Patent 6 | 7 | @par Revision Reference: 8 | GUID defined in UEFI 2.0 spec. 9 | **/ 10 | 11 | #ifndef __EFI_WIN_CERTIFICATE_H__ 12 | #define __EFI_WIN_CERTIFICATE_H__ 13 | 14 | // 15 | // _WIN_CERTIFICATE.wCertificateType 16 | // 17 | #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 18 | #define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 19 | #define WIN_CERT_TYPE_EFI_GUID 0x0EF1 20 | 21 | /// 22 | /// The WIN_CERTIFICATE structure is part of the PE/COFF specification. 23 | /// 24 | typedef struct { 25 | /// 26 | /// The length of the entire certificate, 27 | /// including the length of the header, in bytes. 28 | /// 29 | UINT32 dwLength; 30 | /// 31 | /// The revision level of the WIN_CERTIFICATE 32 | /// structure. The current revision level is 0x0200. 33 | /// 34 | UINT16 wRevision; 35 | /// 36 | /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI 37 | /// certificate types. The UEFI specification reserves the range of 38 | /// certificate type values from 0x0EF0 to 0x0EFF. 39 | /// 40 | UINT16 wCertificateType; 41 | /// 42 | /// The following is the actual certificate. The format of 43 | /// the certificate depends on wCertificateType. 44 | /// 45 | /// UINT8 bCertificate[ANYSIZE_ARRAY]; 46 | /// 47 | } WIN_CERTIFICATE; 48 | 49 | /// 50 | /// WIN_CERTIFICATE_UEFI_GUID.CertType 51 | /// 52 | #define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ 53 | {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } 54 | 55 | /// 56 | /// WIN_CERTIFICATE_UEFI_GUID.CertData 57 | /// 58 | typedef struct { 59 | EFI_GUID HashType; 60 | UINT8 PublicKey[256]; 61 | UINT8 Signature[256]; 62 | } EFI_CERT_BLOCK_RSA_2048_SHA256; 63 | 64 | /// 65 | /// Certificate which encapsulates a GUID-specific digital signature 66 | /// 67 | typedef struct { 68 | /// 69 | /// This is the standard WIN_CERTIFICATE header, where 70 | /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID. 71 | /// 72 | WIN_CERTIFICATE Hdr; 73 | /// 74 | /// This is the unique id which determines the 75 | /// format of the CertData. . 76 | /// 77 | EFI_GUID CertType; 78 | /// 79 | /// The following is the certificate data. The format of 80 | /// the data is determined by the CertType. 81 | /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID, 82 | /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure. 83 | /// 84 | UINT8 CertData[1]; 85 | } WIN_CERTIFICATE_UEFI_GUID; 86 | 87 | /// 88 | /// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature. 89 | /// 90 | /// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from 91 | /// WIN_CERTIFICATE and encapsulate the information needed to 92 | /// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as 93 | /// specified in RFC2437. 94 | /// 95 | typedef struct { 96 | /// 97 | /// This is the standard WIN_CERTIFICATE header, where 98 | /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15. 99 | /// 100 | WIN_CERTIFICATE Hdr; 101 | /// 102 | /// This is the hashing algorithm which was performed on the 103 | /// UEFI executable when creating the digital signature. 104 | /// 105 | EFI_GUID HashAlgorithm; 106 | /// 107 | /// The following is the actual digital signature. The 108 | /// size of the signature is the same size as the key 109 | /// (1024-bit key is 128 bytes) and can be determined by 110 | /// subtracting the length of the other parts of this header 111 | /// from the total length of the certificate as found in 112 | /// Hdr.dwLength. 113 | /// 114 | /// UINT8 Signature[]; 115 | /// 116 | } WIN_CERTIFICATE_EFI_PKCS1_15; 117 | 118 | extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid; 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /wimldr/efi/IndustryStandard/Bluetooth.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | This file contains the Bluetooth definitions that are consumed by drivers. 3 | These definitions are from Bluetooth Core Specification Version 4.0 June, 2010 4 | 5 | Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
6 | SPDX-License-Identifier: BSD-2-Clause-Patent 7 | 8 | **/ 9 | 10 | #ifndef _BLUETOOTH_H_ 11 | #define _BLUETOOTH_H_ 12 | 13 | #pragma pack(1) 14 | 15 | /// 16 | /// BLUETOOTH_ADDRESS 17 | /// 18 | typedef struct { 19 | /// 20 | /// 48bit Bluetooth device address. 21 | /// 22 | UINT8 Address[6]; 23 | } BLUETOOTH_ADDRESS; 24 | 25 | /// 26 | /// BLUETOOTH_CLASS_OF_DEVICE. See Bluetooth specification for detail. 27 | /// 28 | typedef struct { 29 | UINT8 FormatType : 2; 30 | UINT8 MinorDeviceClass : 6; 31 | UINT16 MajorDeviceClass : 5; 32 | UINT16 MajorServiceClass : 11; 33 | } BLUETOOTH_CLASS_OF_DEVICE; 34 | 35 | /// 36 | /// BLUETOOTH_LE_ADDRESS 37 | /// 38 | typedef struct { 39 | /// 40 | /// 48-bit Bluetooth device address 41 | /// 42 | UINT8 Address[6]; 43 | /// 44 | /// 0x00 - Public Device Address 45 | /// 0x01 - Random Device Address 46 | /// 47 | UINT8 Type; 48 | } BLUETOOTH_LE_ADDRESS; 49 | 50 | #pragma pack() 51 | 52 | #define BLUETOOTH_HCI_COMMAND_LOCAL_READABLE_NAME_MAX_SIZE 248 53 | 54 | #define BLUETOOTH_HCI_LINK_KEY_SIZE 16 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /wimldr/efi/ProcessorBind.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMBOOT_EFI_PROCESSOR_BIND_H 2 | #define _WIMBOOT_EFI_PROCESSOR_BIND_H 3 | 4 | /* 5 | * EFI header files rely on having the CPU architecture directory 6 | * present in the search path in order to pick up ProcessorBind.h. We 7 | * use this header file as a quick indirection layer. 8 | * 9 | */ 10 | 11 | #ifdef EFI_HOSTONLY 12 | 13 | /* 14 | * We cannot rely on the EDK2 ProcessorBind.h headers when compiling a 15 | * binary for execution on the build host itself, since the host's CPU 16 | * architecture may not even be supported by EDK2. 17 | */ 18 | 19 | /* Define the basic integer types in terms of the host's */ 20 | #include 21 | typedef int8_t INT8; 22 | typedef int16_t INT16; 23 | typedef int32_t INT32; 24 | typedef int64_t INT64; 25 | typedef uint8_t UINT8; 26 | typedef long INTN; 27 | typedef uint16_t UINT16; 28 | typedef uint32_t UINT32; 29 | typedef uint64_t UINT64; 30 | typedef unsigned long UINTN; 31 | typedef int8_t CHAR8; 32 | typedef int16_t CHAR16; 33 | typedef uint8_t BOOLEAN; 34 | 35 | /* Define EFIAPI as whatever API the host uses by default */ 36 | #define EFIAPI 37 | 38 | /* Define an architecture-neutral MDE_CPU macro to prevent build errors */ 39 | #define MDE_CPU_EBC 40 | 41 | /* Define MAX_BIT in terms of UINTN */ 42 | #define MAX_BIT ( ( ( UINTN ) 1U ) << ( ( 8 * sizeof ( UINTN ) ) - 1 ) ) 43 | 44 | #else /* EFI_HOSTONLY */ 45 | 46 | #ifdef __i386__ 47 | #include 48 | #endif 49 | 50 | #ifdef __x86_64__ 51 | #include 52 | #endif 53 | 54 | #ifdef __aarch64__ 55 | #include 56 | #endif 57 | 58 | #endif /* EFI_HOSTONLY */ 59 | 60 | #endif /* _WIMBOOT_EFI_PROCESSOR_BIND_H */ 61 | -------------------------------------------------------------------------------- /wimldr/efi/Protocol/LoadedImage.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | UEFI 2.0 Loaded image protocol definition. 3 | 4 | Every EFI driver and application is passed an image handle when it is loaded. 5 | This image handle will contain a Loaded Image Protocol. 6 | 7 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
8 | SPDX-License-Identifier: BSD-2-Clause-Patent 9 | 10 | **/ 11 | 12 | #ifndef __LOADED_IMAGE_PROTOCOL_H__ 13 | #define __LOADED_IMAGE_PROTOCOL_H__ 14 | 15 | #define EFI_LOADED_IMAGE_PROTOCOL_GUID \ 16 | { \ 17 | 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ 18 | } 19 | 20 | #define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ 21 | { \ 22 | 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \ 23 | } 24 | 25 | /// 26 | /// Protocol GUID defined in EFI1.1. 27 | /// 28 | #define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID 29 | 30 | /// 31 | /// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h 32 | /// 33 | #define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000 34 | 35 | /// 36 | /// Revision defined in EFI1.1. 37 | /// 38 | #define EFI_LOADED_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION 39 | 40 | /// 41 | /// Can be used on any image handle to obtain information about the loaded image. 42 | /// 43 | typedef struct { 44 | UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure. 45 | ///< All future revisions will be backward compatible to the current revision. 46 | EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from 47 | ///< the firmware's boot manager. 48 | EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer. 49 | 50 | // 51 | // Source location of image 52 | // 53 | EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from. 54 | EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle 55 | ///< that the EFI Image was loaded from. 56 | VOID *Reserved; ///< Reserved. DO NOT USE. 57 | 58 | // 59 | // Images load options 60 | // 61 | UINT32 LoadOptionsSize; ///< The size in bytes of LoadOptions. 62 | VOID *LoadOptions; ///< A pointer to the image's binary load options. 63 | 64 | // 65 | // Location of where image was loaded 66 | // 67 | VOID *ImageBase; ///< The base address at which the image was loaded. 68 | UINT64 ImageSize; ///< The size in bytes of the loaded image. 69 | EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as. 70 | EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as. 71 | EFI_IMAGE_UNLOAD Unload; 72 | } EFI_LOADED_IMAGE_PROTOCOL; 73 | 74 | // 75 | // For backward-compatible with EFI1.1. 76 | // 77 | typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE; 78 | 79 | extern EFI_GUID gEfiLoadedImageProtocolGuid; 80 | extern EFI_GUID gEfiLoadedImageDevicePathProtocolGuid; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /wimldr/efi/Protocol/SimpleTextIn.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | Simple Text Input protocol from the UEFI 2.0 specification. 3 | 4 | Abstraction of a very simple input device like a keyboard or serial 5 | terminal. 6 | 7 | Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
8 | SPDX-License-Identifier: BSD-2-Clause-Patent 9 | 10 | **/ 11 | 12 | #ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__ 13 | #define __SIMPLE_TEXT_IN_PROTOCOL_H__ 14 | 15 | #define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \ 16 | { \ 17 | 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ 18 | } 19 | 20 | typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL; 21 | 22 | /// 23 | /// Protocol GUID name defined in EFI1.1. 24 | /// 25 | #define SIMPLE_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID 26 | 27 | /// 28 | /// Protocol name in EFI1.1 for backward-compatible. 29 | /// 30 | typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE; 31 | 32 | /// 33 | /// The keystroke information for the key that was pressed. 34 | /// 35 | typedef struct { 36 | UINT16 ScanCode; 37 | CHAR16 UnicodeChar; 38 | } EFI_INPUT_KEY; 39 | 40 | // 41 | // Required unicode control chars 42 | // 43 | #define CHAR_BACKSPACE 0x0008 44 | #define CHAR_TAB 0x0009 45 | #define CHAR_LINEFEED 0x000A 46 | #define CHAR_CARRIAGE_RETURN 0x000D 47 | 48 | // 49 | // EFI Scan codes 50 | // 51 | #define SCAN_NULL 0x0000 52 | #define SCAN_UP 0x0001 53 | #define SCAN_DOWN 0x0002 54 | #define SCAN_RIGHT 0x0003 55 | #define SCAN_LEFT 0x0004 56 | #define SCAN_HOME 0x0005 57 | #define SCAN_END 0x0006 58 | #define SCAN_INSERT 0x0007 59 | #define SCAN_DELETE 0x0008 60 | #define SCAN_PAGE_UP 0x0009 61 | #define SCAN_PAGE_DOWN 0x000A 62 | #define SCAN_F1 0x000B 63 | #define SCAN_F2 0x000C 64 | #define SCAN_F3 0x000D 65 | #define SCAN_F4 0x000E 66 | #define SCAN_F5 0x000F 67 | #define SCAN_F6 0x0010 68 | #define SCAN_F7 0x0011 69 | #define SCAN_F8 0x0012 70 | #define SCAN_F9 0x0013 71 | #define SCAN_F10 0x0014 72 | #define SCAN_ESC 0x0017 73 | 74 | /** 75 | Reset the input device and optionally run diagnostics 76 | 77 | @param This Protocol instance pointer. 78 | @param ExtendedVerification Driver may perform diagnostics on reset. 79 | 80 | @retval EFI_SUCCESS The device was reset. 81 | @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. 82 | 83 | **/ 84 | typedef 85 | EFI_STATUS 86 | (EFIAPI *EFI_INPUT_RESET)( 87 | IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 88 | IN BOOLEAN ExtendedVerification 89 | ); 90 | 91 | /** 92 | Reads the next keystroke from the input device. The WaitForKey Event can 93 | be used to test for existence of a keystroke via WaitForEvent () call. 94 | 95 | @param This Protocol instance pointer. 96 | @param Key A pointer to a buffer that is filled in with the keystroke 97 | information for the key that was pressed. 98 | 99 | @retval EFI_SUCCESS The keystroke information was returned. 100 | @retval EFI_NOT_READY There was no keystroke data available. 101 | @retval EFI_DEVICE_ERROR The keystroke information was not returned due to 102 | hardware errors. 103 | 104 | **/ 105 | typedef 106 | EFI_STATUS 107 | (EFIAPI *EFI_INPUT_READ_KEY)( 108 | IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 109 | OUT EFI_INPUT_KEY *Key 110 | ); 111 | 112 | /// 113 | /// The EFI_SIMPLE_TEXT_INPUT_PROTOCOL is used on the ConsoleIn device. 114 | /// It is the minimum required protocol for ConsoleIn. 115 | /// 116 | struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { 117 | EFI_INPUT_RESET Reset; 118 | EFI_INPUT_READ_KEY ReadKeyStroke; 119 | /// 120 | /// Event to use with WaitForEvent() to wait for a key to be available 121 | /// 122 | EFI_EVENT WaitForKey; 123 | }; 124 | 125 | extern EFI_GUID gEfiSimpleTextInProtocolGuid; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /wimldr/efi/Uefi.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | Root include file for Mde Package UEFI, UEFI_APPLICATION type modules. 4 | 5 | This is the include file for any module of type UEFI and UEFI_APPLICATION. Uefi modules only use 6 | types defined via this include file and can be ported easily to any 7 | environment. 8 | 9 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
10 | SPDX-License-Identifier: BSD-2-Clause-Patent 11 | 12 | **/ 13 | 14 | #ifndef __PI_UEFI_H__ 15 | #define __PI_UEFI_H__ 16 | 17 | #include "efi/Uefi/UefiBaseType.h" 18 | #include "efi/Uefi/UefiSpec.h" 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /wimldr/efi/import.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | =head1 NAME 4 | 5 | import.pl 6 | 7 | =head1 SYNOPSIS 8 | 9 | import.pl [options] /path/to/edk2/edk2 10 | 11 | Options: 12 | 13 | -h,--help Display brief help message 14 | -v,--verbose Increase verbosity 15 | -q,--quiet Decrease verbosity 16 | 17 | =cut 18 | 19 | use File::Spec::Functions qw ( :ALL ); 20 | use File::Find; 21 | use File::Path; 22 | use Getopt::Long; 23 | use Pod::Usage; 24 | use FindBin; 25 | use strict; 26 | use warnings; 27 | 28 | my $verbosity = 0; 29 | 30 | sub try_import_file { 31 | my $wimbootdir = shift; 32 | my $edktop = shift; 33 | my $edkdirs = shift; 34 | my $filename = shift; 35 | 36 | # Skip everything except headers 37 | return unless $filename =~ /\.h$/; 38 | 39 | # Skip files that are wimboot native headers 40 | my $outfile = catfile ( $wimbootdir, $filename ); 41 | if ( -s $outfile ) { 42 | open my $outfh, "<$outfile" or die "Could not open $outfile: $!\n"; 43 | my $line = <$outfh>; 44 | close $outfh; 45 | chomp $line; 46 | return if $line =~ /^\#ifndef\s+_WIMBOOT_\S+_H$/; 47 | } 48 | 49 | # Search for importable header 50 | foreach my $edkdir ( @$edkdirs ) { 51 | my $infile = catfile ( $edktop, $edkdir, $filename ); 52 | if ( -e $infile ) { 53 | # We have found a matching source file - import it 54 | print "$filename <- ".catfile ( $edkdir, $filename )."\n" 55 | if $verbosity >= 1; 56 | open my $infh, "<$infile" or die "Could not open $infile: $!\n"; 57 | ( undef, my $outdir, undef ) = splitpath ( $outfile ); 58 | mkpath ( $outdir ); 59 | open my $outfh, ">$outfile" or die "Could not open $outfile: $!\n"; 60 | my @dependencies = (); 61 | while ( <$infh> ) { 62 | # Strip CR and trailing whitespace 63 | s/\r//g; 64 | s/\s*$//g; 65 | chomp; 66 | # Update include lines, and record included files 67 | if ( s/^(\s*\#include\s+)[<\"](\S+)[>\"]/$1 "efi\/$2"/ ) { 68 | push @dependencies, $2; 69 | } 70 | # Write out line 71 | print $outfh "$_\n"; 72 | } 73 | close $outfh; 74 | close $infh; 75 | # Recurse to handle any included files that we don't already have 76 | foreach my $dependency ( @dependencies ) { 77 | if ( ! -e catfile ( $wimbootdir, $dependency ) ) { 78 | print "...following dependency on $dependency\n" if $verbosity >= 1; 79 | try_import_file ( $wimbootdir, $edktop, $edkdirs, $dependency ); 80 | } 81 | } 82 | return; 83 | } 84 | } 85 | die "$filename has no equivalent in $edktop\n"; 86 | } 87 | 88 | # Parse command-line options 89 | Getopt::Long::Configure ( 'bundling', 'auto_abbrev' ); 90 | GetOptions ( 91 | 'verbose|v+' => sub { $verbosity++; }, 92 | 'quiet|q+' => sub { $verbosity--; }, 93 | 'help|h' => sub { pod2usage ( 1 ); }, 94 | ) or die "Could not parse command-line options\n"; 95 | pod2usage ( 1 ) unless @ARGV == 1; 96 | my $edktop = shift; 97 | 98 | # Identify edk import directories 99 | my $edkdirs = [ "MdePkg/Include", "MdeModulePkg/Include" ]; 100 | foreach my $edkdir ( @$edkdirs ) { 101 | die "Directory \"$edktop\" does not appear to contain the EFI EDK2 " 102 | ."(missing \"$edkdir\")\n" unless -d catdir ( $edktop, $edkdir ); 103 | } 104 | 105 | # Identify wimboot EFI includes directory 106 | my $wimbootdir = $FindBin::Bin; 107 | die "Directory \"$wimbootdir\" does not contain the wimboot EFI includes\n" 108 | unless -e catfile ( $wimbootdir, "../wimboot.h" ); 109 | 110 | if ( $verbosity >= 1 ) { 111 | print "Importing EFI headers into $wimbootdir\nfrom "; 112 | print join ( "\n and ", map { catdir ( $edktop, $_ ) } @$edkdirs )."\n"; 113 | } 114 | 115 | # Import headers 116 | find ( { wanted => sub { 117 | try_import_file ( $wimbootdir, $edktop, $edkdirs, 118 | abs2rel ( $_, $wimbootdir ) ); 119 | }, no_chdir => 1 }, $wimbootdir ); 120 | -------------------------------------------------------------------------------- /wimldr/efiblock.h: -------------------------------------------------------------------------------- 1 | #ifndef _EFIBLOCK_H 2 | #define _EFIBLOCK_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * EFI block device 27 | * 28 | */ 29 | 30 | #include "efi.h" 31 | #include "efi/Protocol/BlockIo.h" 32 | #include "efi/Protocol/DevicePath.h" 33 | 34 | extern void efi_install ( EFI_HANDLE *vdisk, EFI_HANDLE *vpartition ); 35 | 36 | extern EFI_DEVICE_PATH_PROTOCOL *bootmgfw_path; 37 | 38 | #endif /* _EFIBLOCK_H */ 39 | -------------------------------------------------------------------------------- /wimldr/efiboot.h: -------------------------------------------------------------------------------- 1 | #ifndef _EFIBOOT_H 2 | #define _EFIBOOT_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * EFI boot manager invocation 27 | * 28 | */ 29 | 30 | #include "efi.h" 31 | #include "efi/Protocol/DevicePath.h" 32 | 33 | struct vdisk_file; 34 | 35 | extern void efi_boot ( struct vdisk_file *file, EFI_DEVICE_PATH_PROTOCOL *path, 36 | EFI_HANDLE device ); 37 | 38 | #endif /* _EFIBOOT_H */ 39 | -------------------------------------------------------------------------------- /wimldr/efifile.h: -------------------------------------------------------------------------------- 1 | #ifndef _EFIFILE_H 2 | #define _EFIFILE_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * EFI file system access 27 | * 28 | */ 29 | 30 | #include "efi.h" 31 | #include "efi/Protocol/SimpleFileSystem.h" 32 | #include "efi/Guid/FileInfo.h" 33 | 34 | struct vdisk_file; 35 | 36 | extern struct vdisk_file *bootmgfw; 37 | extern struct vdisk_file *bootwim; 38 | extern void efi_extract_wim ( EFI_HANDLE handle ); 39 | extern void efi_extract_hda ( void ); 40 | 41 | #endif /* _EFIFILE_H */ 42 | -------------------------------------------------------------------------------- /wimldr/efiguid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * EFI GUIDs 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | #include "efi.h" 29 | #include "efi/Protocol/BlockIo.h" 30 | #include "efi/Protocol/DevicePath.h" 31 | #include "efi/Protocol/GraphicsOutput.h" 32 | #include "efi/Protocol/LoadedImage.h" 33 | #include "efi/Protocol/SimpleFileSystem.h" 34 | #include "efi/Guid/FileInfo.h" 35 | 36 | /** Block I/O protocol GUID */ 37 | EFI_GUID efi_block_io_protocol_guid 38 | = EFI_BLOCK_IO_PROTOCOL_GUID; 39 | 40 | /** Device path protocol GUID */ 41 | EFI_GUID efi_device_path_protocol_guid 42 | = EFI_DEVICE_PATH_PROTOCOL_GUID; 43 | 44 | /** Graphics output protocol GUID */ 45 | EFI_GUID efi_graphics_output_protocol_guid 46 | = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 47 | 48 | /** Loaded image protocol GUID */ 49 | EFI_GUID efi_loaded_image_protocol_guid 50 | = EFI_LOADED_IMAGE_PROTOCOL_GUID; 51 | 52 | /** Simple file system protocol GUID */ 53 | EFI_GUID efi_simple_file_system_protocol_guid 54 | = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; 55 | 56 | EFI_GUID efi_file_info_guid 57 | = EFI_FILE_INFO_ID; 58 | -------------------------------------------------------------------------------- /wimldr/efimain.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * EFI entry point 24 | * 25 | */ 26 | 27 | #include 28 | #include "wimboot.h" 29 | #include "cmdline.h" 30 | #include "efi.h" 31 | #include "efifile.h" 32 | #include "efiblock.h" 33 | #include "efiboot.h" 34 | 35 | /** SBAT section attributes */ 36 | #define __sbat __attribute__ (( section ( ".sbat" ), aligned ( 512 ) )) 37 | 38 | /** SBAT metadata */ 39 | #define SBAT_CSV \ 40 | /* SBAT version */ \ 41 | "sbat,1,SBAT Version,sbat,1," \ 42 | "https://github.com/rhboot/shim/blob/main/SBAT.md" \ 43 | "\n" \ 44 | /* wimboot version */ \ 45 | "wimboot," SBAT_GENERATION ",iPXE,wimboot," VERSION "," \ 46 | "https://ipxe.org/wimboot" \ 47 | "\n" 48 | 49 | /** SBAT metadata (with no terminating NUL) */ 50 | const char sbat[ sizeof ( SBAT_CSV ) - 1 ] __sbat = SBAT_CSV; 51 | 52 | /** 53 | * Process command line 54 | * 55 | * @v loaded Loaded image protocol 56 | */ 57 | static void efi_cmdline ( EFI_LOADED_IMAGE_PROTOCOL *loaded ) { 58 | size_t cmdline_len = ( loaded->LoadOptionsSize / sizeof ( wchar_t ) ); 59 | char cmdline[ cmdline_len + 1 /* NUL */ ]; 60 | const wchar_t *wcmdline = loaded->LoadOptions; 61 | 62 | /* Convert command line to ASCII */ 63 | snprintf ( cmdline, sizeof ( cmdline ), "%ls", wcmdline ); 64 | 65 | /* Process command line */ 66 | process_cmdline ( cmdline ); 67 | } 68 | 69 | static void efi_connect ( void ) 70 | { 71 | EFI_STATUS status; 72 | UINTN count; 73 | EFI_HANDLE *buf; 74 | UINTN i; 75 | EFI_BOOT_SERVICES *bs = efi_systab->BootServices; 76 | DBG ( "Connecting ...\n" ); 77 | status = bs->LocateHandleBuffer ( AllHandles, 78 | NULL, NULL, 79 | &count, 80 | &buf ); 81 | 82 | if (status != EFI_SUCCESS) 83 | return; 84 | 85 | for ( i = 0 ; i < count ; i++ ) 86 | bs->ConnectController ( buf[i], NULL, NULL, TRUE ); 87 | 88 | if ( buf ) 89 | bs->FreePool ( buf ); 90 | } 91 | 92 | /** 93 | * EFI entry point 94 | * 95 | * @v image_handle Image handle 96 | * @v systab EFI system table 97 | * @ret efirc EFI status code 98 | */ 99 | EFI_STATUS EFIAPI efi_main ( EFI_HANDLE image_handle, 100 | EFI_SYSTEM_TABLE *systab ) { 101 | EFI_BOOT_SERVICES *bs; 102 | union { 103 | EFI_LOADED_IMAGE_PROTOCOL *image; 104 | void *interface; 105 | } loaded; 106 | EFI_HANDLE vdisk = NULL; 107 | EFI_HANDLE vpartition = NULL; 108 | EFI_STATUS efirc; 109 | 110 | /* Record EFI handle and system table */ 111 | efi_image_handle = image_handle; 112 | efi_systab = systab; 113 | bs = systab->BootServices; 114 | 115 | /* Initialise stack cookie */ 116 | init_cookie(); 117 | 118 | /* Print welcome banner */ 119 | printf ( "\n\nwimldr\n\n" ); 120 | 121 | /* Get loaded image protocol */ 122 | if ( ( efirc = bs->OpenProtocol ( image_handle, 123 | &efi_loaded_image_protocol_guid, 124 | &loaded.interface, image_handle, NULL, 125 | EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ 126 | die ( "Could not open loaded image protocol: %#lx\n", 127 | ( ( unsigned long ) efirc ) ); 128 | } 129 | 130 | /* Process command line */ 131 | efi_cmdline ( loaded.image ); 132 | 133 | efi_connect (); 134 | 135 | /* Extract files from file system */ 136 | efi_extract_wim ( loaded.image->DeviceHandle ); 137 | efi_extract_hda (); 138 | 139 | /* Install virtual disk */ 140 | efi_install ( &vdisk, &vpartition ); 141 | 142 | /* Invoke boot manager */ 143 | efi_boot ( bootmgfw, bootmgfw_path, vpartition ); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /wimldr/efipath.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * EFI device paths 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | #include "efi.h" 29 | #include "efipath.h" 30 | 31 | /** 32 | * Find end of device path 33 | * 34 | * @v path Path to device 35 | * @ret path_end End of device path 36 | */ 37 | EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) { 38 | 39 | while ( path->Type != END_DEVICE_PATH_TYPE ) { 40 | path = ( ( ( void * ) path ) + 41 | /* There's this amazing new-fangled thing known as 42 | * a UINT16, but who wants to use one of those? */ 43 | ( ( path->Length[1] << 8 ) | path->Length[0] ) ); 44 | } 45 | return path; 46 | } 47 | -------------------------------------------------------------------------------- /wimldr/efipath.h: -------------------------------------------------------------------------------- 1 | #ifndef _EFIPATH_H 2 | #define _EFIPATH_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * EFI device paths 27 | * 28 | */ 29 | 30 | #include "efi.h" 31 | #include "efi/Protocol/DevicePath.h" 32 | 33 | /** 34 | * Initialise device path 35 | * 36 | * @v name Variable name 37 | * @v type Type 38 | * @v subtype Subtype 39 | */ 40 | #define EFI_DEVPATH_INIT( name, type, subtype ) { \ 41 | .Type = (type), \ 42 | .SubType = (subtype), \ 43 | .Length[0] = ( sizeof (name) & 0xff ), \ 44 | .Length[1] = ( sizeof (name) >> 8 ), \ 45 | } 46 | 47 | /** 48 | * Initialise device path 49 | * 50 | * @v path Device path 51 | * @v type Type 52 | * @v subtype Subtype 53 | * @v len Length 54 | */ 55 | static inline __attribute__ (( always_inline )) void 56 | efi_devpath_init ( EFI_DEVICE_PATH_PROTOCOL *path, unsigned int type, 57 | unsigned int subtype, size_t len ) { 58 | 59 | path->Type = type; 60 | path->SubType = subtype; 61 | path->Length[0] = ( len & 0xff ); 62 | path->Length[1] = ( len >> 8 ); 63 | } 64 | 65 | /** 66 | * Initialise device path end 67 | * 68 | * @v name Variable name 69 | */ 70 | #define EFI_DEVPATH_END_INIT( name ) \ 71 | EFI_DEVPATH_INIT ( name, END_DEVICE_PATH_TYPE, \ 72 | END_ENTIRE_DEVICE_PATH_SUBTYPE ) 73 | 74 | /** 75 | * Initialise device path end 76 | * 77 | * @v path Device path 78 | */ 79 | static inline __attribute__ (( always_inline )) void 80 | efi_devpath_end_init ( EFI_DEVICE_PATH_PROTOCOL *path ) { 81 | 82 | efi_devpath_init ( path, END_DEVICE_PATH_TYPE, 83 | END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof ( *path ) ); 84 | } 85 | 86 | extern EFI_DEVICE_PATH_PROTOCOL * 87 | efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ); 88 | 89 | #endif /* _EFIPATH_H */ 90 | -------------------------------------------------------------------------------- /wimldr/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERRNO_H 2 | #define _ERRNO_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Error numbers 27 | * 28 | */ 29 | 30 | #endif /* _ERRNO_H */ 31 | -------------------------------------------------------------------------------- /wimldr/huffman.h: -------------------------------------------------------------------------------- 1 | #ifndef _HUFFMAN_H 2 | #define _HUFFMAN_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Huffman alphabets 27 | * 28 | */ 29 | 30 | #include 31 | 32 | /** Maximum length of a Huffman symbol (in bits) */ 33 | #define HUFFMAN_BITS 16 34 | 35 | /** Raw huffman symbol */ 36 | typedef uint16_t huffman_raw_symbol_t; 37 | 38 | /** Quick lookup length for a Huffman symbol (in bits) 39 | * 40 | * This is a policy decision. 41 | */ 42 | #define HUFFMAN_QL_BITS 7 43 | 44 | /** Quick lookup shift */ 45 | #define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS ) 46 | 47 | /** A Huffman-coded set of symbols of a given length */ 48 | struct huffman_symbols { 49 | /** Length of Huffman-coded symbols (in bits) */ 50 | uint8_t bits; 51 | /** Shift to normalise symbols of this length to HUFFMAN_BITS bits */ 52 | uint8_t shift; 53 | /** Number of Huffman-coded symbols having this length */ 54 | uint16_t freq; 55 | /** First symbol of this length (normalised to HUFFMAN_BITS bits) 56 | * 57 | * Stored as a 32-bit value to allow the value 58 | * (1<bits; 90 | } 91 | 92 | /** 93 | * Get Huffman symbol value 94 | * 95 | * @v sym Huffman symbol set 96 | * @v huf Raw input value (normalised to HUFFMAN_BITS bits) 97 | * @ret raw Raw symbol value 98 | */ 99 | static inline __attribute__ (( always_inline )) huffman_raw_symbol_t 100 | huffman_raw ( struct huffman_symbols *sym, unsigned int huf ) { 101 | 102 | return sym->raw[ huf >> sym->shift ]; 103 | } 104 | 105 | extern int huffman_alphabet ( struct huffman_alphabet *alphabet, 106 | uint8_t *lengths, unsigned int count ); 107 | extern struct huffman_symbols * 108 | huffman_sym ( struct huffman_alphabet *alphabet, unsigned int huf ); 109 | 110 | #endif /* _HUFFMAN_H */ 111 | -------------------------------------------------------------------------------- /wimldr/int13.h: -------------------------------------------------------------------------------- 1 | #ifndef _INT13_H 2 | #define _INT13_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * INT 13 emulation 27 | * 28 | */ 29 | 30 | /** Construct a pointer from a real-mode segment:offset address */ 31 | #define REAL_PTR( segment, offset ) \ 32 | ( ( void * ) ( intptr_t ) ( ( (segment) << 4 ) + offset ) ) 33 | 34 | /** Get drive parameters */ 35 | #define INT13_GET_PARAMETERS 0x08 36 | /** Get disk type */ 37 | #define INT13_GET_DISK_TYPE 0x15 38 | /** Extensions installation check */ 39 | #define INT13_EXTENSION_CHECK 0x41 40 | /** Extended read */ 41 | #define INT13_EXTENDED_READ 0x42 42 | /** Get extended drive parameters */ 43 | #define INT13_GET_EXTENDED_PARAMETERS 0x48 44 | 45 | /** Operation completed successfully */ 46 | #define INT13_STATUS_SUCCESS 0x00 47 | /** Invalid function or parameter */ 48 | #define INT13_STATUS_INVALID 0x01 49 | /** Read error */ 50 | #define INT13_STATUS_READ_ERROR 0x04 51 | /** Reset failed */ 52 | #define INT13_STATUS_RESET_FAILED 0x05 53 | /** Write error */ 54 | #define INT13_STATUS_WRITE_ERROR 0xcc 55 | 56 | /** No such drive */ 57 | #define INT13_DISK_TYPE_NONE 0x00 58 | /** Floppy without change-line support */ 59 | #define INT13_DISK_TYPE_FDD 0x01 60 | /** Floppy with change-line support */ 61 | #define INT13_DISK_TYPE_FDD_CL 0x02 62 | /** Hard disk */ 63 | #define INT13_DISK_TYPE_HDD 0x03 64 | 65 | /** Extended disk access functions supported */ 66 | #define INT13_EXTENSION_LINEAR 0x01 67 | 68 | /** INT13 extensions version 1.x */ 69 | #define INT13_EXTENSION_VER_1_X 0x01 70 | 71 | /** DMA boundary errors handled transparently */ 72 | #define INT13_FL_DMA_TRANSPARENT 0x01 73 | 74 | /** BIOS drive counter */ 75 | #define INT13_DRIVE_COUNT ( *( ( ( uint8_t * ) REAL_PTR ( 0x40, 0x75 ) ) ) ) 76 | 77 | /** An INT 13 disk address packet */ 78 | struct int13_disk_address { 79 | /** Size of the packet, in bytes */ 80 | uint8_t bufsize; 81 | /** Reserved */ 82 | uint8_t reserved_a; 83 | /** Block count */ 84 | uint8_t count; 85 | /** Reserved */ 86 | uint8_t reserved_b; 87 | /** Data buffer */ 88 | struct segoff buffer; 89 | /** Starting block number */ 90 | uint64_t lba; 91 | /** Data buffer (EDD 3.0+ only) */ 92 | uint64_t buffer_phys; 93 | /** Block count (EDD 4.0+ only) */ 94 | uint32_t long_count; 95 | /** Reserved */ 96 | uint32_t reserved_c; 97 | } __attribute__ (( packed )); 98 | 99 | /** INT 13 disk parameters */ 100 | struct int13_disk_parameters { 101 | /** Size of this structure */ 102 | uint16_t bufsize; 103 | /** Flags */ 104 | uint16_t flags; 105 | /** Number of cylinders */ 106 | uint32_t cylinders; 107 | /** Number of heads */ 108 | uint32_t heads; 109 | /** Number of sectors per track */ 110 | uint32_t sectors_per_track; 111 | /** Total number of sectors on drive */ 112 | uint64_t sectors; 113 | /** Bytes per sector */ 114 | uint16_t sector_size; 115 | } __attribute__ (( packed )); 116 | 117 | extern int initialise_int13 ( void ); 118 | extern void emulate_int13 ( struct bootapp_callback_params *params ); 119 | 120 | #endif /* _INT13_H */ 121 | -------------------------------------------------------------------------------- /wimldr/ipxe/vsprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef _IPXE_VSPRINTF_H 2 | #define _IPXE_VSPRINTF_H 3 | 4 | /** @file 5 | * 6 | * printf() and friends 7 | * 8 | * Etherboot's printf() functions understand the following subset of 9 | * the standard C printf()'s format specifiers: 10 | * 11 | * - Flag characters 12 | * - '#' - Alternate form (i.e. "0x" prefix) 13 | * - '0' - Zero-pad 14 | * - Field widths 15 | * - Length modifiers 16 | * - 'hh' - Signed / unsigned char 17 | * - 'h' - Signed / unsigned short 18 | * - 'l' - Signed / unsigned long 19 | * - 'll' - Signed / unsigned long long 20 | * - 'z' - Signed / unsigned size_t 21 | * - Conversion specifiers 22 | * - 'd' - Signed decimal 23 | * - 'x','X' - Unsigned hexadecimal 24 | * - 'c' - Character 25 | * - 's' - String 26 | * - 'p' - Pointer 27 | * 28 | * Hexadecimal numbers are always zero-padded to the specified field 29 | * width (if any); decimal numbers are always space-padded. Decimal 30 | * long longs are not supported. 31 | * 32 | */ 33 | 34 | FILE_LICENCE ( GPL2_OR_LATER ); 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | /** 41 | * A printf context 42 | * 43 | * Contexts are used in order to be able to share code between 44 | * vprintf() and vsnprintf(), without requiring the allocation of a 45 | * buffer for vprintf(). 46 | */ 47 | struct printf_context { 48 | /** 49 | * Character handler 50 | * 51 | * @v ctx Context 52 | * @v c Character 53 | * 54 | * This method is called for each character written to the 55 | * formatted string. 56 | */ 57 | void ( * handler ) ( struct printf_context *ctx, unsigned int c ); 58 | /** Length of formatted string 59 | * 60 | * When handler() is called, @len will be set to the number of 61 | * characters written so far (i.e. zero for the first call to 62 | * handler()). 63 | */ 64 | size_t len; 65 | }; 66 | 67 | extern size_t vcprintf ( struct printf_context *ctx, const char *fmt, 68 | va_list args ); 69 | extern int vssnprintf ( char *buf, ssize_t ssize, const char *fmt, 70 | va_list args ); 71 | extern int __attribute__ (( format ( printf, 3, 4 ) )) 72 | ssnprintf ( char *buf, ssize_t ssize, const char *fmt, ... ); 73 | 74 | #endif /* _IPXE_VSPRINTF_H */ 75 | -------------------------------------------------------------------------------- /wimldr/lznt1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * LZNT1 decompression 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "wimboot.h" 32 | #include "lznt1.h" 33 | 34 | /** 35 | * Decompress LZNT1-compressed data block 36 | * 37 | * @v data Compressed data 38 | * @v limit Length of compressed data up to end of block 39 | * @v offset Starting offset within compressed data 40 | * @v block Decompression buffer for this block, or NULL 41 | * @ret out_len Length of decompressed block, or negative error 42 | */ 43 | static ssize_t lznt1_block ( const void *data, size_t limit, size_t offset, 44 | void *block ) { 45 | const uint16_t *tuple; 46 | const uint8_t *copy_src; 47 | uint8_t *copy_dest = block; 48 | size_t copy_len; 49 | size_t block_out_len = 0; 50 | unsigned int split = 12; 51 | unsigned int next_threshold = 16; 52 | unsigned int tag_bit = 0; 53 | unsigned int tag = 0; 54 | 55 | while ( offset != limit ) { 56 | 57 | /* Extract tag */ 58 | if ( tag_bit == 0 ) { 59 | tag = *( ( uint8_t * ) ( data + offset ) ); 60 | offset++; 61 | if ( offset == limit ) 62 | break; 63 | } 64 | 65 | /* Calculate copy source and length */ 66 | if ( tag & 1 ) { 67 | 68 | /* Compressed value */ 69 | if ( offset + sizeof ( *tuple ) > limit ) { 70 | DBG ( "LZNT1 compressed value overrun at " 71 | "%#zx\n", offset ); 72 | return -1; 73 | } 74 | tuple = ( data + offset ); 75 | offset += sizeof ( *tuple ); 76 | copy_len = LZNT1_VALUE_LEN ( *tuple, split ); 77 | block_out_len += copy_len; 78 | if ( copy_dest ) { 79 | copy_src = ( copy_dest - 80 | LZNT1_VALUE_OFFSET ( *tuple, 81 | split ) ); 82 | while ( copy_len-- ) 83 | *(copy_dest++) = *(copy_src++); 84 | } 85 | 86 | } else { 87 | 88 | /* Uncompressed value */ 89 | copy_src = ( data + offset ); 90 | if ( copy_dest ) 91 | *(copy_dest++) = *copy_src; 92 | offset++; 93 | block_out_len++; 94 | } 95 | 96 | /* Update split, if applicable */ 97 | while ( block_out_len > next_threshold ) { 98 | split--; 99 | next_threshold <<= 1; 100 | } 101 | 102 | /* Move to next value */ 103 | tag >>= 1; 104 | tag_bit = ( ( tag_bit + 1 ) % 8 ); 105 | } 106 | 107 | return block_out_len; 108 | } 109 | 110 | /** 111 | * Decompress LZNT1-compressed data 112 | * 113 | * @v data Compressed data 114 | * @v len Length of compressed data 115 | * @v buf Decompression buffer, or NULL 116 | * @ret out_len Length of decompressed data, or negative error 117 | */ 118 | ssize_t lznt1_decompress ( const void *data, size_t len, void *buf ) { 119 | const uint16_t *header; 120 | const uint8_t *end; 121 | size_t offset = 0; 122 | ssize_t out_len = 0; 123 | size_t block_len; 124 | size_t limit; 125 | void *block; 126 | ssize_t block_out_len; 127 | 128 | while ( offset != len ) { 129 | 130 | /* Check for end marker */ 131 | if ( ( offset + sizeof ( *end ) ) == len ) { 132 | end = ( data + offset ); 133 | if ( *end == 0 ) 134 | break; 135 | } 136 | 137 | /* Extract block header */ 138 | if ( ( offset + sizeof ( *header ) ) > len ) { 139 | DBG ( "LZNT1 block header overrun at %#zx\n", offset ); 140 | return -1; 141 | } 142 | header = ( data + offset ); 143 | offset += sizeof ( *header ); 144 | 145 | /* Process block */ 146 | block_len = LZNT1_BLOCK_LEN ( *header ); 147 | if ( LZNT1_BLOCK_COMPRESSED ( *header ) ) { 148 | 149 | /* Compressed block */ 150 | DBG2 ( "LZNT1 compressed block %#zx+%#zx\n", 151 | offset, block_len ); 152 | limit = ( offset + block_len ); 153 | block = ( buf ? ( buf + out_len ) : NULL ); 154 | block_out_len = lznt1_block ( data, limit, offset, 155 | block ); 156 | if ( block_out_len < 0 ) 157 | return block_out_len; 158 | offset += block_len; 159 | out_len += block_out_len; 160 | 161 | } else { 162 | 163 | /* Uncompressed block */ 164 | if ( ( offset + block_len ) > len ) { 165 | DBG ( "LZNT1 uncompressed block overrun at " 166 | "%#zx+%#zx\n", offset, block_len ); 167 | return -1; 168 | } 169 | DBG2 ( "LZNT1 uncompressed block %#zx+%#zx\n", 170 | offset, block_len ); 171 | if ( buf ) { 172 | memcpy ( ( buf + out_len ), ( data + offset ), 173 | block_len ); 174 | } 175 | offset += block_len; 176 | out_len += block_len; 177 | } 178 | } 179 | 180 | return out_len; 181 | } 182 | -------------------------------------------------------------------------------- /wimldr/lznt1.h: -------------------------------------------------------------------------------- 1 | #ifndef _LZNT1_H 2 | #define _LZNT1_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * LZNT1 decompression 27 | * 28 | */ 29 | 30 | #include 31 | 32 | /** Extract LZNT1 block length */ 33 | #define LZNT1_BLOCK_LEN( header ) ( ( (header) & 0x0fff ) + 1 ) 34 | 35 | /** Determine if LZNT1 block is compressed */ 36 | #define LZNT1_BLOCK_COMPRESSED( header ) ( (header) & 0x8000 ) 37 | 38 | /** Extract LZNT1 compressed value length */ 39 | #define LZNT1_VALUE_LEN( tuple, split ) \ 40 | ( ( (tuple) & ( ( 1 << (split) ) - 1 ) ) + 3 ) 41 | 42 | /** Extract LZNT1 compressed value offset */ 43 | #define LZNT1_VALUE_OFFSET( tuple, split ) ( ( (tuple) >> split ) + 1 ) 44 | 45 | extern ssize_t lznt1_decompress ( const void *data, size_t len, void *buf ); 46 | 47 | #endif /* _LZNT1_H */ 48 | -------------------------------------------------------------------------------- /wimldr/lzx.h: -------------------------------------------------------------------------------- 1 | #ifndef _LZX_H 2 | #define _LZX_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * LZX decompression 27 | * 28 | */ 29 | 30 | #include 31 | #include "huffman.h" 32 | 33 | /** Number of aligned offset codes */ 34 | #define LZX_ALIGNOFFSET_CODES 8 35 | 36 | /** Aligned offset code length (in bits) */ 37 | #define LZX_ALIGNOFFSET_BITS 3 38 | 39 | /** Number of pretree codes */ 40 | #define LZX_PRETREE_CODES 20 41 | 42 | /** Pretree code length (in bits) */ 43 | #define LZX_PRETREE_BITS 4 44 | 45 | /** Number of literal main codes */ 46 | #define LZX_MAIN_LIT_CODES 256 47 | 48 | /** Number of position slots */ 49 | #define LZX_POSITION_SLOTS 30 50 | 51 | /** Number of main codes */ 52 | #define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) ) 53 | 54 | /** Number of length codes */ 55 | #define LZX_LENGTH_CODES 249 56 | 57 | /** Block type length (in bits) */ 58 | #define LZX_BLOCK_TYPE_BITS 3 59 | 60 | /** Default block length */ 61 | #define LZX_DEFAULT_BLOCK_LEN 32768 62 | 63 | /** Number of repeated offsets */ 64 | #define LZX_REPEATED_OFFSETS 3 65 | 66 | /** Don't ask */ 67 | #define LZX_WIM_MAGIC_FILESIZE 12000000 68 | 69 | /** Block types */ 70 | enum lzx_block_type { 71 | /** Verbatim block */ 72 | LZX_BLOCK_VERBATIM = 1, 73 | /** Aligned offset block */ 74 | LZX_BLOCK_ALIGNOFFSET = 2, 75 | /** Uncompressed block */ 76 | LZX_BLOCK_UNCOMPRESSED = 3, 77 | }; 78 | 79 | /** An LZX input stream */ 80 | struct lzx_input_stream { 81 | /** Data */ 82 | const uint8_t *data; 83 | /** Length */ 84 | size_t len; 85 | /** Offset within stream */ 86 | size_t offset; 87 | }; 88 | 89 | /** An LZX output stream */ 90 | struct lzx_output_stream { 91 | /** Data, or NULL */ 92 | uint8_t *data; 93 | /** Offset within stream */ 94 | size_t offset; 95 | /** End of current block within stream */ 96 | size_t threshold; 97 | }; 98 | 99 | /** LZX decompressor */ 100 | struct lzx { 101 | /** Input stream */ 102 | struct lzx_input_stream input; 103 | /** Output stream */ 104 | struct lzx_output_stream output; 105 | /** Accumulator */ 106 | uint32_t accumulator; 107 | /** Number of bits in accumulator */ 108 | unsigned int bits; 109 | /** Block type */ 110 | enum lzx_block_type block_type; 111 | /** Repeated offsets */ 112 | unsigned int repeated_offset[LZX_REPEATED_OFFSETS]; 113 | 114 | /** Aligned offset Huffman alphabet */ 115 | struct huffman_alphabet alignoffset; 116 | /** Aligned offset raw symbols 117 | * 118 | * Must immediately follow the aligned offset Huffman 119 | * alphabet. 120 | */ 121 | huffman_raw_symbol_t alignoffset_raw[LZX_ALIGNOFFSET_CODES]; 122 | /** Aligned offset code lengths */ 123 | uint8_t alignoffset_lengths[LZX_ALIGNOFFSET_CODES]; 124 | 125 | /** Pretree Huffman alphabet */ 126 | struct huffman_alphabet pretree; 127 | /** Pretree raw symbols 128 | * 129 | * Must immediately follow the pretree Huffman alphabet. 130 | */ 131 | huffman_raw_symbol_t pretree_raw[LZX_PRETREE_CODES]; 132 | /** Preetree code lengths */ 133 | uint8_t pretree_lengths[LZX_PRETREE_CODES]; 134 | 135 | /** Main Huffman alphabet */ 136 | struct huffman_alphabet main; 137 | /** Main raw symbols 138 | * 139 | * Must immediately follow the main Huffman alphabet. 140 | */ 141 | huffman_raw_symbol_t main_raw[LZX_MAIN_CODES]; 142 | /** Main code lengths */ 143 | struct { 144 | /** Literals */ 145 | uint8_t literals[LZX_MAIN_LIT_CODES]; 146 | /** Remaining symbols */ 147 | uint8_t remainder[ LZX_MAIN_CODES - LZX_MAIN_LIT_CODES ]; 148 | } __attribute__ (( packed )) main_lengths; 149 | 150 | /** Length Huffman alphabet */ 151 | struct huffman_alphabet length; 152 | /** Length raw symbols 153 | * 154 | * Must immediately follow the length Huffman alphabet. 155 | */ 156 | huffman_raw_symbol_t length_raw[LZX_LENGTH_CODES]; 157 | /** Length code lengths */ 158 | uint8_t length_lengths[LZX_LENGTH_CODES]; 159 | }; 160 | 161 | /** 162 | * Calculate number of footer bits for a given position slot 163 | * 164 | * @v position_slot Position slot 165 | * @ret footer_bits Number of footer bits 166 | */ 167 | static inline unsigned int lzx_footer_bits ( unsigned int position_slot ) { 168 | 169 | if ( position_slot < 2 ) { 170 | return 0; 171 | } else if ( position_slot < 38 ) { 172 | return ( ( position_slot / 2 ) - 1 ); 173 | } else { 174 | return 17; 175 | } 176 | } 177 | 178 | extern ssize_t lzx_decompress ( const void *data, size_t len, void *buf ); 179 | 180 | #endif /* _LZX_H */ 181 | -------------------------------------------------------------------------------- /wimldr/memmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Memory map 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include "wimboot.h" 31 | #include "memmap.h" 32 | 33 | /** Buffer for INT 15,e820 calls */ 34 | static struct e820_entry e820_buf __attribute__ (( section ( ".bss16" ) )); 35 | 36 | /** Continuation value for next INT 15,e820 call */ 37 | static uint32_t e820_ebx; 38 | 39 | /** 40 | * Get system memory map entry 41 | * 42 | * @v prev Previous system memory map entry, or NULL at start 43 | * @v next Next system memory map entry, or NULL at end 44 | */ 45 | struct e820_entry * memmap_next ( struct e820_entry *prev ) { 46 | struct bootapp_callback_params params; 47 | 48 | /* Reset buffer and continuation value if restarting */ 49 | if ( ! prev ) { 50 | memset ( &e820_buf, 0, sizeof ( e820_buf ) ); 51 | e820_ebx = 0; 52 | } else if ( e820_ebx == 0 ) { 53 | /* Reach the end */ 54 | return NULL; 55 | } 56 | 57 | /* Read system memory map */ 58 | memset ( ¶ms, 0, sizeof ( params ) ); 59 | do { 60 | 61 | /* Call INT 15,e820 */ 62 | params.vector.interrupt = 0x15; 63 | params.eax = 0xe820; 64 | params.ebx = e820_ebx; 65 | params.ecx = sizeof ( e820_buf ); 66 | params.edx = E820_SMAP; 67 | params.es = BASE_SEG; 68 | params.edi = ( ( ( void * ) &e820_buf ) - 69 | ( ( void * ) BASE_ADDRESS ) ); 70 | call_interrupt ( ¶ms ); 71 | 72 | /* Record continuation value */ 73 | e820_ebx = params.ebx; 74 | 75 | /* Check result */ 76 | if ( params.eflags & CF ) { 77 | DBG ( "INT 15,e820 failed: error %02x\n", params.ah ); 78 | break; 79 | } 80 | if ( params.eax != E820_SMAP ) { 81 | DBG ( "INT 15,e820 invalid SMAP signature %08x\n", 82 | params.eax ); 83 | break; 84 | } 85 | DBG2 ( "INT 15,e820 region [%llx,%llx) type %d\n", 86 | e820_buf.start, ( e820_buf.start + e820_buf.len ), 87 | e820_buf.type ); 88 | 89 | /* Skip non-RAM regions */ 90 | if ( e820_buf.type != E820_TYPE_RAM ) 91 | continue; 92 | if ( params.ecx > offsetof ( typeof ( e820_buf ), attrs ) ) { 93 | if ( ! ( e820_buf.attrs & E820_ATTR_ENABLED ) ) 94 | continue; 95 | if ( e820_buf.attrs & E820_ATTR_NONVOLATILE ) 96 | continue; 97 | } 98 | 99 | /* Return this region */ 100 | return &e820_buf; 101 | 102 | } while ( e820_ebx != 0 ); 103 | 104 | return NULL; 105 | } 106 | -------------------------------------------------------------------------------- /wimldr/memmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEMMAP_H 2 | #define _MEMMAP_H 3 | 4 | /* 5 | * Copyright (C) 2021 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Memory map 27 | * 28 | */ 29 | 30 | #include 31 | 32 | /** Magic value for INT 15,e820 calls */ 33 | #define E820_SMAP 0x534d4150 34 | 35 | /** An INT 15,e820 memory map entry */ 36 | struct e820_entry { 37 | /** Start of region */ 38 | uint64_t start; 39 | /** Length of region */ 40 | uint64_t len; 41 | /** Type of region */ 42 | uint32_t type; 43 | /** Extended attributes (optional) */ 44 | uint32_t attrs; 45 | } __attribute__ (( packed )); 46 | 47 | /** Normal RAM */ 48 | #define E820_TYPE_RAM 1 49 | 50 | /** Region is enabled (if extended attributes are present) */ 51 | #define E820_ATTR_ENABLED 0x00000001UL 52 | 53 | /** Region is non-volatile memory (if extended attributes are present) */ 54 | #define E820_ATTR_NONVOLATILE 0x00000002UL 55 | 56 | extern struct e820_entry * memmap_next ( struct e820_entry *prev ); 57 | 58 | #endif /* _MEMMAP_H */ 59 | -------------------------------------------------------------------------------- /wimldr/paging.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAGING_H 2 | #define _PAGING_H 3 | 4 | /* 5 | * Copyright (C) 2021 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Paging 27 | * 28 | */ 29 | 30 | #include 31 | 32 | /** Get CPU features */ 33 | #define CPUID_FEATURES 0x00000001 34 | 35 | /** CPU supports PAE */ 36 | #define CPUID_FEATURE_EDX_PAE 0x00000040 37 | 38 | /* CR0: paging */ 39 | #define CR0_PG 0x80000000 40 | 41 | /* CR4: physical address extensions */ 42 | #define CR4_PAE 0x00000020 43 | 44 | /* Page: present */ 45 | #define PG_P 0x01 46 | 47 | /* Page: read/write */ 48 | #define PG_RW 0x02 49 | 50 | /* Page: user/supervisor */ 51 | #define PG_US 0x04 52 | 53 | /* Page: page size */ 54 | #define PG_PS 0x80 55 | 56 | /** 2MB page size */ 57 | #define PAGE_SIZE_2MB 0x200000 58 | 59 | /** 32-bit address space size */ 60 | #define ADDR_4GB 0x100000000ULL 61 | 62 | /** Saved paging state */ 63 | struct paging_state { 64 | /** Control register 0 */ 65 | unsigned long cr0; 66 | /** Control register 3 */ 67 | unsigned long cr3; 68 | /** Control register 4 */ 69 | unsigned long cr4; 70 | }; 71 | 72 | extern int paging; 73 | 74 | extern void init_paging ( void ); 75 | extern void enable_paging ( struct paging_state *state ); 76 | extern void disable_paging ( struct paging_state *state ); 77 | extern uint64_t relocate_memory_high ( void *start, size_t len ); 78 | 79 | #endif /* _PAGING_H */ 80 | -------------------------------------------------------------------------------- /wimldr/patch.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMPATCH_H 2 | #define _WIMPATCH_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * WIM & BCD patching 27 | * 28 | */ 29 | 30 | #include 31 | 32 | struct vdisk_file; 33 | 34 | extern void patch_wim ( struct vdisk_file *file, void *data, size_t offset, 35 | size_t len ); 36 | 37 | extern void patch_bcd ( struct vdisk_file *file, void *data, size_t offset, 38 | size_t len ); 39 | 40 | #endif /* _WIMPATCH_H */ 41 | -------------------------------------------------------------------------------- /wimldr/pause.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Diagnostic pause 24 | * 25 | */ 26 | 27 | #include 28 | #include "wimboot.h" 29 | #include "cmdline.h" 30 | #include "pause.h" 31 | 32 | /** 33 | * Pause before booting 34 | * 35 | */ 36 | void pause ( void ) { 37 | 38 | /* Wait for keypress, prompting */ 39 | printf ( "Press any key to continue booting..." ); 40 | getchar(); 41 | printf ( "\n" ); 42 | } 43 | -------------------------------------------------------------------------------- /wimldr/pause.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAUSE_H 2 | #define _PAUSE_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Diagnostic pause 27 | * 28 | */ 29 | 30 | extern void pause ( void ); 31 | 32 | #endif /* _PAUSE_H */ 33 | -------------------------------------------------------------------------------- /wimldr/peloader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * PE image loader 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "wimboot.h" 32 | #include "peloader.h" 33 | 34 | /** 35 | * Load PE image into memory 36 | * 37 | * @v data PE image 38 | * @v len Length of PE image 39 | * @v pe Loaded PE structure to fill in 40 | * @ret rc Return status code 41 | */ 42 | int load_pe ( const void *data, size_t len, struct loaded_pe *pe ) { 43 | const struct mz_header *mzhdr; 44 | size_t pehdr_offset; 45 | const struct pe_header *pehdr; 46 | size_t opthdr_offset; 47 | const struct pe_optional_header *opthdr; 48 | size_t section_offset; 49 | const struct coff_section *section; 50 | char name[ sizeof ( section->name ) + 1 /* NUL */ ]; 51 | unsigned int i; 52 | void *section_base; 53 | size_t filesz; 54 | size_t memsz; 55 | void *end; 56 | void *raw_base; 57 | 58 | DBG2 ( "Loading PE executable...\n" ); 59 | 60 | /* Parse PE header */ 61 | mzhdr = data; 62 | if ( mzhdr->magic != MZ_HEADER_MAGIC ) { 63 | DBG ( "Bad MZ magic %04x\n", mzhdr->magic ); 64 | return -1; 65 | } 66 | pehdr_offset = mzhdr->lfanew; 67 | if ( pehdr_offset > len ) { 68 | DBG ( "PE header outside file\n" ); 69 | return -1; 70 | } 71 | pehdr = ( data + pehdr_offset ); 72 | if ( pehdr->magic != PE_HEADER_MAGIC ) { 73 | DBG ( "Bad PE magic %08x\n", pehdr->magic ); 74 | return -1; 75 | } 76 | opthdr_offset = ( pehdr_offset + sizeof ( *pehdr ) ); 77 | opthdr = ( data + opthdr_offset ); 78 | pe->base = ( ( void * ) ( intptr_t ) ( opthdr->base ) ); 79 | section_offset = ( opthdr_offset + pehdr->coff.opthdr_len ); 80 | section = ( data + section_offset ); 81 | 82 | /* Load header into memory */ 83 | DBG2 ( "...headers to %p+%#x\n", pe->base, opthdr->header_len ); 84 | memcpy ( pe->base, data, opthdr->header_len ); 85 | end = ( pe->base + opthdr->header_len ); 86 | 87 | /* Load each section into memory */ 88 | for ( i = 0 ; i < pehdr->coff.num_sections ; i++, section++ ) { 89 | memset ( name, 0, sizeof ( name ) ); 90 | memcpy ( name, section->name, sizeof ( section->name ) ); 91 | section_base = ( pe->base + section->virtual ); 92 | filesz = section->raw_len; 93 | memsz = section->misc.virtual_len; 94 | DBG2 ( "...from %#05x to %p+%#zx/%#zx (%s)\n", 95 | section->raw, section_base, filesz, memsz, name ); 96 | memset ( section_base, 0, memsz ); 97 | memcpy ( section_base, ( data + section->raw ), filesz ); 98 | if ( end < ( section_base + memsz ) ) 99 | end = ( section_base + memsz ); 100 | } 101 | pe->len = ( ( ( end - pe->base ) + opthdr->section_align - 1 ) 102 | & ~( opthdr->section_align - 1 ) ); 103 | 104 | /* Load copy of raw image into memory immediately after loaded 105 | * sections. This seems to be used for verification of X.509 106 | * signatures. 107 | */ 108 | raw_base = ( pe->base + pe->len ); 109 | memcpy ( raw_base, data, len ); 110 | pe->len += len; 111 | DBG2 ( "...raw copy to %p+%#zx\n", raw_base, len ); 112 | 113 | /* Extract entry point */ 114 | pe->entry = ( pe->base + opthdr->entry ); 115 | DBG2 ( "...entry point %p\n", pe->entry ); 116 | 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /wimldr/prefix.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * bzImage prefix 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | 29 | /** Standard number of setup sectors */ 30 | #define SETUP_SECTS 4 31 | 32 | /** Sector size */ 33 | #define SECTOR_SIZE 512 34 | 35 | /** Setup code length */ 36 | #define SETUP_LEN ( ( SETUP_SECTS + 1 ) * SECTOR_SIZE ) 37 | 38 | /** Protected-mode code will be loaded high */ 39 | #define LOADED_HIGH 0x01 40 | 41 | /** Protected-mode code will be loaded to this linear address */ 42 | #define LOADED_HIGH_ADDRESS 0x100000 43 | 44 | /** Protected-mode bit in CR0 */ 45 | #define CR0_PE 0x01 46 | 47 | /** 32-bit protected mode code segment based at real-mode %cs:0000 */ 48 | #define PREFIX_CS 0x08 49 | 50 | /** 32 bit protected mode flat code segment */ 51 | #define PREFIX_FLAT_CS 0x10 52 | 53 | /** 32 bit protected mode flat data segment */ 54 | #define PREFIX_FLAT_DS 0x18 55 | 56 | .section ".note.GNU-stack", "", @progbits 57 | .text 58 | .section ".prefix", "ax", @progbits 59 | .org 0 60 | _prefix: 61 | 62 | #if defined(__i386__) || defined(__x86_64__) 63 | 64 | .code32 65 | 66 | .org 0x1f1 67 | setup_sects: 68 | .byte SETUP_SECTS 69 | 70 | .org 0x1fe 71 | boot_flag: 72 | .word 0xaa55 73 | 74 | .org 0x200 75 | jump: 76 | .byte 0xeb, setup - 1f 77 | 1: 78 | 79 | .org 0x202 80 | header: 81 | .ascii "HdrS" 82 | 83 | .org 0x206 84 | version: 85 | .word 0x206 /* Version 2.06 */ 86 | 87 | .org 0x20e 88 | kernel_version: 89 | .word ( version_string - _prefix - 0x200 ) 90 | 91 | .org 0x211 92 | loadflags: 93 | .byte LOADED_HIGH 94 | 95 | .org 0x218 96 | ramdisk_image: 97 | .long 0 /* Filled in by boot loader */ 98 | 99 | .org 0x21c 100 | ramdisk_size: 101 | .long 0 /* Filled in by boot loader */ 102 | 103 | .org 0x228 104 | cmd_line_ptr: 105 | .long 0 /* Filled in by boot loader */ 106 | 107 | .org 0x22c 108 | ramdisk_max: 109 | .long 0xffffffff 110 | 111 | .org 0x238 112 | cmdline_size: 113 | .long 4096 114 | 115 | version_string: 116 | .asciz VERSION 117 | 118 | /* Setup code */ 119 | .code16 120 | setup: 121 | #ifdef BIOS 122 | /* Reset %cs so that labels work */ 123 | pushw %ds 124 | pushw $( 1f - _prefix ) 125 | lret 126 | 1: 127 | /* Fix up GDT */ 128 | xorl %eax, %eax 129 | movw %cs, %ax 130 | shll $4, %eax 131 | addl %eax, ( gdt - _prefix + 2 ) 132 | addl %eax, ( gdt - _prefix + PREFIX_CS + 2 ) 133 | 134 | /* Switch to protected mode and jump to startup code */ 135 | cli 136 | data32 lgdt ( gdt - _prefix ) 137 | movl %cr0, %eax 138 | orb $CR0_PE, %al 139 | movl %eax, %cr0 140 | data32 ljmp $PREFIX_CS, $( 1f - _prefix ) 141 | .code32 142 | 1: 143 | /* Load data segment registers */ 144 | movw $PREFIX_FLAT_DS, %ax 145 | movw %ax, %ds 146 | movw %ax, %es 147 | movw %ax, %fs 148 | movw %ax, %gs 149 | movw %ax, %ss 150 | 151 | /* Zero real-mode and protected-mode .bss sections */ 152 | xorl %eax, %eax 153 | movl $_bss16, %edi 154 | movl $_bss16_len, %ecx 155 | rep stosb 156 | movl $_bss, %edi 157 | movl $_bss_len, %ecx 158 | rep stosb 159 | 160 | /* Copy payload to runtime address */ 161 | movl $( LOADED_HIGH_ADDRESS + _payload_pos - SETUP_LEN ), %esi 162 | movl $_payload, %edi 163 | movl $_payload_len, %ecx 164 | cld 165 | rep movsb 166 | 167 | /* Copy parameters required by runtime */ 168 | movl %cs:( cmd_line_ptr - _prefix ), %eax 169 | movl %eax, cmdline 170 | movl %cs:( ramdisk_image - _prefix ), %eax 171 | movl %eax, initrd 172 | movl %cs:( ramdisk_size - _prefix ), %eax 173 | movl %eax, initrd_len 174 | 175 | /* Jump to payload */ 176 | ljmp $PREFIX_FLAT_CS, $startup 177 | .size setup, . - setup 178 | 179 | /* Global descriptor table */ 180 | gdt: 181 | .word gdt_limit 182 | .long ( gdt - _prefix ) 183 | /* 32-bit protected mode code segment based at real-mode %cs:0000 */ 184 | .org ( gdt + PREFIX_CS ) 185 | .word 0xffff, 0 186 | .byte 0, 0x9f, 0xcf, 0 187 | /* 32 bit protected mode flat code segment */ 188 | .org ( gdt + PREFIX_FLAT_CS ) 189 | .word 0xffff, 0 190 | .byte 0, 0x9f, 0xcf, 0 191 | /* 32 bit protected mode flat data segment */ 192 | .org ( gdt + PREFIX_FLAT_DS ) 193 | .word 0xffff, 0 194 | .byte 0, 0x93, 0xcf, 0 195 | .size gdt, . - gdt 196 | .equ gdt_limit, . - gdt - 1 197 | #endif 198 | #endif 199 | 200 | .org SETUP_LEN 201 | -------------------------------------------------------------------------------- /wimldr/rotate.h: -------------------------------------------------------------------------------- 1 | #ifndef _ROTATE_H 2 | #define _ROTATE_H 3 | 4 | /** @file 5 | * 6 | * Bit operations 7 | */ 8 | 9 | #include 10 | 11 | static inline __attribute__ (( always_inline )) uint8_t 12 | rol8 ( uint8_t data, unsigned int rotation ) { 13 | return ( ( data << rotation ) | ( data >> ( 8 - rotation ) ) ); 14 | } 15 | 16 | static inline __attribute__ (( always_inline )) uint8_t 17 | ror8 ( uint8_t data, unsigned int rotation ) { 18 | return ( ( data >> rotation ) | ( data << ( 8 - rotation ) ) ); 19 | } 20 | 21 | static inline __attribute__ (( always_inline )) uint16_t 22 | rol16 ( uint16_t data, unsigned int rotation ) { 23 | return ( ( data << rotation ) | ( data >> ( 16 - rotation ) ) ); 24 | } 25 | 26 | static inline __attribute__ (( always_inline )) uint16_t 27 | ror16 ( uint16_t data, unsigned int rotation ) { 28 | return ( ( data >> rotation ) | ( data << ( 16 - rotation ) ) ); 29 | } 30 | 31 | static inline __attribute__ (( always_inline )) uint32_t 32 | rol32 ( uint32_t data, unsigned int rotation ) { 33 | return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) ); 34 | } 35 | 36 | static inline __attribute__ (( always_inline )) uint32_t 37 | ror32 ( uint32_t data, unsigned int rotation ) { 38 | return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) ); 39 | } 40 | 41 | static inline __attribute__ (( always_inline )) uint64_t 42 | rol64 ( uint64_t data, unsigned int rotation ) { 43 | return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) ); 44 | } 45 | 46 | static inline __attribute__ (( always_inline )) uint64_t 47 | ror64 ( uint64_t data, unsigned int rotation ) { 48 | return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) ); 49 | } 50 | 51 | #endif /* _ROTATE_H */ 52 | -------------------------------------------------------------------------------- /wimldr/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHA1_H 2 | #define _SHA1_H 3 | 4 | /** @file 5 | * 6 | * SHA-1 algorithm 7 | * 8 | */ 9 | 10 | #include 11 | 12 | /** An SHA-1 digest */ 13 | struct sha1_digest { 14 | /** Hash output */ 15 | uint32_t h[5]; 16 | }; 17 | 18 | /** An SHA-1 data block */ 19 | union sha1_block { 20 | /** Raw bytes */ 21 | uint8_t byte[64]; 22 | /** Raw dwords */ 23 | uint32_t dword[16]; 24 | /** Final block structure */ 25 | struct { 26 | /** Padding */ 27 | uint8_t pad[56]; 28 | /** Length in bits */ 29 | uint64_t len; 30 | } final; 31 | }; 32 | 33 | /** SHA-1 digest and data block 34 | * 35 | * The order of fields within this structure is designed to minimise 36 | * code size. 37 | */ 38 | struct sha1_digest_data { 39 | /** Digest of data already processed */ 40 | struct sha1_digest digest; 41 | /** Accumulated data */ 42 | union sha1_block data; 43 | } __attribute__ (( packed )); 44 | 45 | /** SHA-1 digest and data block */ 46 | union sha1_digest_data_dwords { 47 | /** Digest and data block */ 48 | struct sha1_digest_data dd; 49 | /** Raw dwords */ 50 | uint32_t dword[ sizeof ( struct sha1_digest_data ) / 51 | sizeof ( uint32_t ) ]; 52 | }; 53 | 54 | /** An SHA-1 context */ 55 | struct sha1_context { 56 | /** Amount of accumulated data */ 57 | size_t len; 58 | /** Digest and accumulated data */ 59 | union sha1_digest_data_dwords ddd; 60 | } __attribute__ (( packed )); 61 | 62 | /** SHA-1 context size */ 63 | #define SHA1_CTX_SIZE sizeof ( struct sha1_context ) 64 | 65 | /** SHA-1 digest size */ 66 | #define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest ) 67 | 68 | extern void sha1_init ( void *ctx ); 69 | extern void sha1_update ( void *ctx, const void *data, size_t len ); 70 | extern void sha1_final ( void *ctx, void *out ); 71 | 72 | #endif /* _SHA1_H */ 73 | -------------------------------------------------------------------------------- /wimldr/startup.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Startup code 24 | * 25 | */ 26 | 27 | #include "wimboot.h" 28 | 29 | #define WARM_REBOOT_FLAG 0x0472 30 | #define WARM_REBOOT_MAGIC 0x1234 31 | #define KC_CMD 0x64 32 | #define KC_CMD_RESET 0xfe 33 | 34 | .section ".note.GNU-stack", "", @progbits 35 | 36 | #if defined(__i386__) || defined(__x86_64__) 37 | 38 | .code32 39 | .arch i386 40 | 41 | /* Startup code */ 42 | .section ".text", "ax", @progbits 43 | .globl startup 44 | startup: 45 | /* Reload GDT, IDT, and all segment registers, and set up stack */ 46 | lgdt gdtr 47 | lidt idtr 48 | ljmp $FLAT_CS, $1f 49 | 1: movw $FLAT_DS, %ax 50 | movw %ax, %ds 51 | movw %ax, %es 52 | movw %ax, %fs 53 | movw %ax, %gs 54 | movw %ax, %ss 55 | movl $_estack, %esp 56 | 57 | /* Jump to C code */ 58 | call main 59 | 60 | /* Should never return */ 61 | jmp reboot 62 | .size startup, . - startup 63 | 64 | /* Reboot system */ 65 | .section ".text", "ax", @progbits 66 | .globl reboot 67 | reboot: 68 | /* Attempt a warm reboot via the keyboard controller */ 69 | movw $WARM_REBOOT_MAGIC, WARM_REBOOT_FLAG 70 | movb $KC_CMD_RESET, %al 71 | outb %al, $KC_CMD 72 | /* If that failed, generate a CPU triple fault */ 73 | int $0xff 74 | /* If even that failed, hang the system */ 75 | 1: hlt 76 | jmp 1b 77 | .size reboot, . - reboot 78 | 79 | /* Global descriptor table */ 80 | .section ".rodata16", "aw", @progbits 81 | .balign 8 82 | gdt: 83 | .globl gdtr 84 | gdtr: 85 | .word gdt_limit 86 | .long gdt 87 | /* 64 bit long mode code segment */ 88 | .org ( gdt + LM_CS ) 89 | .word 0, 0 90 | .byte 0, 0x9b, 0x20, 0 91 | /* 32 bit protected mode flat code segment */ 92 | .org ( gdt + FLAT_CS ) 93 | .word 0xffff, 0 94 | .byte 0, 0x9f, 0xcf, 0 95 | /* 32 bit protected mode flat data segment */ 96 | .org ( gdt + FLAT_DS ) 97 | .word 0xffff, 0 98 | .byte 0, 0x93, 0xcf, 0 99 | /* 16 bit flat real mode code segment with base BASE_ADDRESS */ 100 | .org ( gdt + REAL_CS ) 101 | .word 0xffff, ( BASE_ADDRESS & 0xffff ) 102 | .byte ( BASE_ADDRESS >> 16 ), 0x9b, 0x8f, 0 103 | /* 16 bit flat real mode data segment with base BASE_ADDRESS */ 104 | .org ( gdt + REAL_DS ) 105 | .word 0xffff, ( BASE_ADDRESS & 0xffff ) 106 | .byte ( BASE_ADDRESS >> 16 ), 0x93, 0x8f, 0 107 | .size gdt, . - gdt 108 | .equ gdt_limit, . - gdt - 1 109 | 110 | /* Interrupt descriptor table */ 111 | .section ".bss16", "aw", @nobits 112 | .balign 8 113 | idt: 114 | .space ( 256 * 8 ) /* 256 8-byte entries */ 115 | .size idt, . - idt 116 | .equ idt_limit, . - idt - 1 117 | 118 | /* Interrupt descriptor table register */ 119 | .section ".rodata16", "aw", @progbits 120 | .globl idtr 121 | idtr: 122 | .word idt_limit 123 | .long idt 124 | .size idtr, . - idtr 125 | 126 | /* Stack */ 127 | .section ".stack", "aw", @nobits 128 | .balign 8 129 | _stack: 130 | .space ( 64 * 1024 ) 131 | .size _stack, . - _stack 132 | _estack: 133 | 134 | #endif /* defined(__i386__) || defined(__x86_64__) */ 135 | -------------------------------------------------------------------------------- /wimldr/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDARG_H 2 | #define _STDARG_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Standard arguments 27 | * 28 | */ 29 | 30 | typedef __builtin_va_list va_list; 31 | #define va_start( ap, last ) __builtin_va_start ( ap, last ) 32 | #define va_arg( ap, type ) __builtin_va_arg ( ap, type ) 33 | #define va_end( ap ) __builtin_va_end ( ap ) 34 | #define va_copy( dest, src ) __builtin_va_copy ( dest, src ) 35 | 36 | #endif /* _STDARG_H */ 37 | -------------------------------------------------------------------------------- /wimldr/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H 2 | #define _STDDEF_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Standard definitions 27 | * 28 | */ 29 | 30 | #include 31 | 32 | #define NULL ( ( void * ) 0 ) 33 | 34 | #define offsetof( type, member ) ( ( size_t ) &( ( type * ) NULL )->member ) 35 | 36 | #define container_of( ptr, type, member ) ( { \ 37 | const typeof ( ( ( type * ) NULL )->member ) *__mptr = (ptr); \ 38 | ( type * ) ( ( void * ) __mptr - offsetof ( type, member ) ); } ) 39 | 40 | #endif /* _STDDEF_H */ 41 | -------------------------------------------------------------------------------- /wimldr/stdint.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDINT_H 2 | #define _STDINT_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Standard integer types 27 | * 28 | */ 29 | 30 | typedef unsigned char uint8_t; 31 | typedef unsigned short uint16_t; 32 | typedef unsigned int uint32_t; 33 | typedef unsigned long long uint64_t; 34 | 35 | typedef signed char int8_t; 36 | typedef signed short int16_t; 37 | typedef signed int int32_t; 38 | typedef signed long long int64_t; 39 | 40 | typedef unsigned long intptr_t; 41 | 42 | typedef __SIZE_TYPE__ size_t; 43 | typedef signed long ssize_t; 44 | 45 | typedef __WCHAR_TYPE__ wchar_t; 46 | typedef __WINT_TYPE__ wint_t; 47 | 48 | #endif /* _STDINT_H */ 49 | -------------------------------------------------------------------------------- /wimldr/stdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Standard Input/Output 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include "bootapp.h" 30 | #include "wimboot.h" 31 | #include "efi.h" 32 | 33 | /** 34 | * Print character to console 35 | * 36 | * @v character Character to print 37 | */ 38 | int putchar ( int character ) { 39 | /* Convert LF to CR,LF */ 40 | if ( character == '\n' ) 41 | putchar ( '\r' ); 42 | 43 | /* Print character to bochs debug port */ 44 | #if defined(__i386__) || defined(__x86_64__) 45 | __asm__ __volatile__ ( "outb %b0, $0xe9" 46 | : : "a" ( character ) ); 47 | #endif 48 | 49 | #ifdef BIOS 50 | struct bootapp_callback_params params; 51 | memset ( ¶ms, 0, sizeof ( params ) ); 52 | params.vector.interrupt = 0x10; 53 | params.eax = ( 0x0e00 | character ); 54 | params.ebx = 0x0007; 55 | call_interrupt ( ¶ms ); 56 | #else 57 | /* Print character to EFI console as applicable */ 58 | EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *conout; 59 | wchar_t wbuf[2]; 60 | conout = efi_systab->ConOut; 61 | wbuf[0] = character; 62 | wbuf[1] = 0; 63 | conout->OutputString ( conout, wbuf ); 64 | #endif 65 | 66 | return 0; 67 | } 68 | 69 | /** 70 | * Get character from console 71 | * 72 | * @ret character Character 73 | */ 74 | int getchar ( void ) { 75 | int character; 76 | 77 | #ifdef BIOS 78 | struct bootapp_callback_params params; 79 | memset ( ¶ms, 0, sizeof ( params ) ); 80 | params.vector.interrupt = 0x16; 81 | call_interrupt ( ¶ms ); 82 | character = params.al; 83 | #else 84 | EFI_BOOT_SERVICES *bs; 85 | EFI_SIMPLE_TEXT_INPUT_PROTOCOL *conin; 86 | EFI_INPUT_KEY key; 87 | UINTN index; 88 | bs = efi_systab->BootServices; 89 | conin = efi_systab->ConIn; 90 | bs->WaitForEvent ( 1, &conin->WaitForKey, &index ); 91 | conin->ReadKeyStroke ( conin, &key ); 92 | character = key.UnicodeChar; 93 | #endif 94 | 95 | return character; 96 | } 97 | -------------------------------------------------------------------------------- /wimldr/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDIO_H 2 | #define _STDIO_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Standard Input/Output 27 | * 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | extern int putchar ( int character ); 34 | extern int getchar ( void ); 35 | 36 | extern int __attribute__ (( format ( printf, 1, 2 ) )) 37 | printf ( const char *fmt, ... ); 38 | 39 | extern int __attribute__ (( format ( printf, 3, 4 ) )) 40 | snprintf ( char *buf, size_t size, const char *fmt, ... ); 41 | 42 | extern int vprintf ( const char *fmt, va_list args ); 43 | 44 | extern int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ); 45 | 46 | #endif /* _STDIO_H */ 47 | -------------------------------------------------------------------------------- /wimldr/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDLIB_H 2 | #define _STDLIB_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Standard library 27 | * 28 | */ 29 | 30 | extern unsigned long strtoul ( const char *nptr, char **endptr, int base ); 31 | 32 | #endif /* _STDLIB_H */ 33 | -------------------------------------------------------------------------------- /wimldr/string.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRING_H 2 | #define _STRING_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * String operations 27 | * 28 | */ 29 | 30 | #include 31 | 32 | extern void * memcpy ( void *dest, const void *src, size_t len ); 33 | extern void * memmove ( void *dest, const void *src, size_t len ); 34 | extern void * memset ( void *dest, int c, size_t len ); 35 | extern int memcmp ( const void *src1, const void *src2, size_t len ); 36 | extern int strcmp ( const char *str1, const char *str2 ); 37 | extern size_t strlen ( const char *str ); 38 | 39 | #endif /* _STRING_H */ 40 | -------------------------------------------------------------------------------- /wimldr/strings.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRINGS_H 2 | #define _STRINGS_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * String operations 27 | * 28 | */ 29 | 30 | extern int strcasecmp ( const char *str1, const char *str2 ); 31 | 32 | #endif /* _STRINGS_H */ 33 | -------------------------------------------------------------------------------- /wimldr/vsprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Quick and dirty wrapper around iPXE's unmodified vsprintf.c 3 | * 4 | */ 5 | 6 | #include 7 | #include 8 | #include "wimboot.h" 9 | 10 | #define FILE_LICENCE(x) 11 | 12 | #include "ipxe/vsprintf.c" 13 | -------------------------------------------------------------------------------- /wimldr/wchar.h: -------------------------------------------------------------------------------- 1 | #ifndef _WCHAR_H 2 | #define _WCHAR_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Wide characters 27 | * 28 | */ 29 | 30 | #include 31 | 32 | typedef void mbstate_t; 33 | 34 | /** 35 | * Convert wide character to multibyte sequence 36 | * 37 | * @v buf Buffer 38 | * @v wc Wide character 39 | * @v ps Shift state 40 | * @ret len Number of characters written 41 | * 42 | * This is a stub implementation, sufficient to handle basic ASCII 43 | * characters. 44 | */ 45 | static inline size_t wcrtomb ( char *buf, wchar_t wc, 46 | mbstate_t *ps __attribute__ (( unused )) ) { 47 | *buf = wc; 48 | return 1; 49 | } 50 | 51 | extern int wcscasecmp ( const wchar_t *str1, const wchar_t *str2 ); 52 | extern size_t wcslen ( const wchar_t *str ); 53 | extern wchar_t * wcschr ( const wchar_t *str, wchar_t c ); 54 | 55 | #endif /* _WCHAR_H */ 56 | -------------------------------------------------------------------------------- /wimldr/wctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _WCTYPE_H 2 | #define _WCTYPE_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Wide character types 27 | * 28 | * We don't actually care about wide characters. Internationalisation 29 | * is a user interface concern, and has absolutely no place in the 30 | * boot process. However, UEFI uses wide characters and so we have to 31 | * at least be able to handle the ASCII subset of UCS-2. 32 | * 33 | */ 34 | 35 | #include 36 | 37 | static inline int iswlower ( wint_t c ) { 38 | return islower ( c ); 39 | } 40 | 41 | static inline int iswupper ( wint_t c ) { 42 | return isupper ( c ); 43 | } 44 | 45 | static inline int towupper ( wint_t c ) { 46 | return toupper ( c ); 47 | } 48 | 49 | static inline int iswspace ( wint_t c ) { 50 | return isspace ( c ); 51 | } 52 | 53 | #endif /* _WCTYPE_H */ 54 | -------------------------------------------------------------------------------- /wimldr/wimboot.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMBOOT_H 2 | #define _WIMBOOT_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * WIM boot loader 27 | * 28 | */ 29 | 30 | /** Debug switch */ 31 | #ifndef DEBUG 32 | #define DEBUG 1 33 | #endif 34 | 35 | /** Base segment address 36 | * 37 | * We place everything at 2000:0000, since this region is used by the 38 | * Microsoft first-stage loaders (e.g. pxeboot.n12, etfsboot.com). 39 | */ 40 | #define BASE_SEG 0x2000 41 | 42 | /** Base linear address */ 43 | #define BASE_ADDRESS ( BASE_SEG << 4 ) 44 | 45 | /** 64 bit long mode code segment */ 46 | #define LM_CS 0x10 47 | 48 | /** 32 bit protected mode flat code segment */ 49 | #define FLAT_CS 0x20 50 | 51 | /** 32 bit protected mode flat data segment */ 52 | #define FLAT_DS 0x30 53 | 54 | /** 16 bit real mode code segment */ 55 | #define REAL_CS 0x50 56 | 57 | /** 16 bit real mode data segment */ 58 | #define REAL_DS 0x60 59 | 60 | #ifndef ASSEMBLY 61 | 62 | #include 63 | #include 64 | #include 65 | 66 | /** Construct wide-character version of a string constant */ 67 | #define L( x ) _L ( x ) 68 | #define _L( x ) L ## x 69 | 70 | /** Page size */ 71 | #define PAGE_SIZE 4096 72 | 73 | /** 74 | * Calculate start page number 75 | * 76 | * @v address Address 77 | * @ret page Start page number 78 | */ 79 | static inline unsigned int page_start ( const void *address ) { 80 | return ( ( ( intptr_t ) address ) / PAGE_SIZE ); 81 | } 82 | 83 | /** 84 | * Calculate end page number 85 | * 86 | * @v address Address 87 | * @ret page End page number 88 | */ 89 | static inline unsigned int page_end ( const void *address ) { 90 | return ( ( ( ( intptr_t ) address ) + PAGE_SIZE - 1 ) / PAGE_SIZE ); 91 | } 92 | 93 | /** 94 | * Calculate page length 95 | * 96 | * @v start Start address 97 | * @v end End address 98 | * @ret num_pages Number of pages 99 | */ 100 | static inline unsigned int page_len ( const void *start, const void *end ) { 101 | return ( page_end ( end ) - page_start ( start ) ); 102 | } 103 | 104 | /** 105 | * Bochs magic breakpoint 106 | * 107 | */ 108 | static inline void bochsbp ( void ) { 109 | __asm__ __volatile__ ( "xchgw %bx, %bx" ); 110 | } 111 | 112 | /** Debugging output */ 113 | #define DBG(...) do { \ 114 | if ( ( DEBUG & 1 ) ) { \ 115 | printf ( __VA_ARGS__ ); \ 116 | } \ 117 | } while ( 0 ) 118 | 119 | /** Verbose debugging output */ 120 | #define DBG2(...) do { \ 121 | if ( ( DEBUG & 2 ) ) { \ 122 | printf ( __VA_ARGS__ ); \ 123 | } \ 124 | } while ( 0 ) 125 | 126 | /* Branch prediction macros */ 127 | #define likely( x ) __builtin_expect ( !! (x), 1 ) 128 | #define unlikely( x ) __builtin_expect ( (x), 0 ) 129 | 130 | /* Mark parameter as unused */ 131 | #define __unused __attribute__ (( unused )) 132 | 133 | #ifdef BIOS 134 | extern void call_real ( struct bootapp_callback_params *params ); 135 | extern void call_interrupt ( struct bootapp_callback_params *params ); 136 | extern void __attribute__ (( noreturn )) reboot ( void ); 137 | #endif 138 | 139 | extern void __attribute__ (( noreturn, format ( printf, 1, 2 ) )) 140 | die ( const char *fmt, ... ); 141 | 142 | extern unsigned long __stack_chk_guard; 143 | extern void init_cookie ( void ); 144 | 145 | #endif /* ASSEMBLY */ 146 | 147 | #endif /* _WIMBOOT_H */ 148 | -------------------------------------------------------------------------------- /wimldr/wimfile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * WIM virtual files 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "wimboot.h" 33 | #include "vdisk.h" 34 | #include "wim.h" 35 | #include "wimfile.h" 36 | 37 | /** A WIM virtual file */ 38 | struct wim_file { 39 | /** Underlying virtual file */ 40 | struct vdisk_file *file; 41 | /** WIM header */ 42 | struct wim_header header; 43 | /** Resource */ 44 | struct wim_resource_header resource; 45 | }; 46 | 47 | /** Maximum number of WIM virtual files */ 48 | #define WIM_MAX_FILES 8 49 | 50 | /** WIM virtual files */ 51 | static struct wim_file wim_files[WIM_MAX_FILES]; 52 | 53 | /** 54 | * Read from WIM virtual file 55 | * 56 | * @v file Virtual file 57 | * @v data Data buffer 58 | * @v offset Offset 59 | * @v len Length 60 | */ 61 | static void wim_read_file ( struct vdisk_file *file, void *data, 62 | size_t offset, size_t len ) { 63 | struct wim_file *wfile = file->opaque; 64 | int rc; 65 | 66 | /* Read from resource */ 67 | if ( ( rc = wim_read ( wfile->file, &wfile->header, &wfile->resource, 68 | data, offset, len ) ) != 0 ) { 69 | die ( "Could not read from WIM virtual file\n" ); 70 | } 71 | } 72 | 73 | /** 74 | * Add WIM virtual file 75 | * 76 | * @v file Underlying virtual file 77 | * @v index Image index, or 0 to use boot image 78 | * @v path Path to file within WIM 79 | * @v wname New virtual file name 80 | * @ret file Virtual file, or NULL if not found 81 | */ 82 | struct vdisk_file * wim_add_file ( struct vdisk_file *file, unsigned int index, 83 | const wchar_t *path, const wchar_t *wname ) { 84 | static unsigned int wim_file_idx = 0; 85 | struct wim_resource_header meta; 86 | struct wim_file *wfile; 87 | char name[ VDISK_NAME_LEN + 1 /* NUL */ ]; 88 | unsigned int i; 89 | int rc; 90 | 91 | /* Sanity check */ 92 | if ( wim_file_idx >= WIM_MAX_FILES ) 93 | die ( "Too many WIM files\n" ); 94 | wfile = &wim_files[wim_file_idx]; 95 | 96 | /* Construct ASCII file name */ 97 | snprintf ( name, sizeof ( name ), "%ls", wname ); 98 | 99 | /* Skip files already added explicitly */ 100 | for ( i = 0 ; i < VDISK_MAX_FILES ; i++ ) { 101 | if ( strcasecmp ( name, vdisk_files[i].name ) == 0 ) 102 | return NULL; 103 | } 104 | 105 | /* Get WIM header */ 106 | if ( ( rc = wim_header ( file, &wfile->header ) ) != 0 ) 107 | return NULL; 108 | 109 | /* Get image metadata */ 110 | if ( ( rc = wim_metadata ( file, &wfile->header, index, &meta ) ) != 0 ) 111 | return NULL; 112 | 113 | /* Get file resource */ 114 | if ( ( rc = wim_file ( file, &wfile->header, &meta, path, 115 | &wfile->resource ) ) != 0 ) 116 | return NULL; 117 | 118 | /* Add virtual file */ 119 | wim_file_idx++; 120 | wfile->file = file; 121 | return vdisk_add_file ( name, wfile, wfile->resource.len, 122 | wim_read_file ); 123 | } 124 | 125 | /** 126 | * Add WIM virtual files 127 | * 128 | * @v file Underlying virtual file 129 | * @v index Image index, or 0 to use boot image 130 | * @v paths List of paths to files within WIM 131 | */ 132 | void wim_add_files ( struct vdisk_file *file, unsigned int index, 133 | const wchar_t **paths ) { 134 | const wchar_t **path; 135 | const wchar_t *wname; 136 | const wchar_t *tmp; 137 | 138 | /* Add any existent files within the list */ 139 | for ( path = paths ; *path ; path++ ) { 140 | 141 | /* Construct file name */ 142 | wname = *path; 143 | for ( tmp = wname ; *tmp ; tmp++ ) { 144 | if ( *tmp == L'\\' ) 145 | wname = ( tmp + 1 ); 146 | } 147 | 148 | /* Add virtual file, if existent */ 149 | wim_add_file ( file, index, *path, wname ); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /wimldr/wimfile.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMFILE_H 2 | #define _WIMFILE_H 3 | 4 | /* 5 | * Copyright (C) 2014 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * WIM virtual files 27 | * 28 | */ 29 | 30 | #include 31 | 32 | struct vdisk_file; 33 | 34 | extern struct vdisk_file * wim_add_file ( struct vdisk_file *file, 35 | unsigned int index, 36 | const wchar_t *path, 37 | const wchar_t *wname ); 38 | extern void wim_add_files ( struct vdisk_file *file, unsigned int index, 39 | const wchar_t **paths ); 40 | 41 | #endif /* _WIMFILE_H */ 42 | -------------------------------------------------------------------------------- /wimldr/xca.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Michael Brown . 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file 22 | * 23 | * Xpress Compression Algorithm (MS-XCA) decompression 24 | * 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "wimboot.h" 32 | #include "huffman.h" 33 | #include "xca.h" 34 | 35 | /** 36 | * Decompress XCA-compressed data 37 | * 38 | * @v data Compressed data 39 | * @v len Length of compressed data 40 | * @v buf Decompression buffer, or NULL 41 | * @ret out_len Length of decompressed data, or negative error 42 | */ 43 | ssize_t xca_decompress ( const void *data, size_t len, void *buf ) { 44 | const void *src = data; 45 | const void *end = ( src + len ); 46 | uint8_t *out = buf; 47 | size_t out_len = 0; 48 | size_t out_len_threshold = 0; 49 | const struct xca_huf_len *lengths; 50 | struct xca xca; 51 | uint32_t accum = 0; 52 | int extra_bits = 0; 53 | unsigned int huf; 54 | struct huffman_symbols *sym; 55 | unsigned int raw; 56 | unsigned int match_len; 57 | unsigned int match_offset_bits; 58 | unsigned int match_offset; 59 | const uint8_t *copy; 60 | int rc; 61 | 62 | /* Process data stream */ 63 | while ( src < end ) { 64 | 65 | /* (Re)initialise decompressor if applicable */ 66 | if ( out_len >= out_len_threshold ) { 67 | 68 | /* Construct symbol lengths */ 69 | lengths = src; 70 | src += sizeof ( *lengths ); 71 | if ( src > end ) { 72 | DBG ( "XCA too short to hold Huffman lengths " 73 | "table at input offset %#zx\n", 74 | ( src - data ) ); 75 | return -1; 76 | } 77 | for ( raw = 0 ; raw < XCA_CODES ; raw++ ) 78 | xca.lengths[raw] = xca_huf_len ( lengths, raw ); 79 | 80 | /* Construct Huffman alphabet */ 81 | if ( ( rc = huffman_alphabet ( &xca.alphabet, 82 | xca.lengths, 83 | XCA_CODES ) ) != 0 ) 84 | return rc; 85 | 86 | /* Initialise state */ 87 | accum = XCA_GET16 ( src ); 88 | accum <<= 16; 89 | accum |= XCA_GET16 ( src ); 90 | extra_bits = 16; 91 | 92 | /* Determine next threshold */ 93 | out_len_threshold = ( out_len + XCA_BLOCK_SIZE ); 94 | } 95 | 96 | /* Determine symbol */ 97 | huf = ( accum >> ( 32 - HUFFMAN_BITS ) ); 98 | sym = huffman_sym ( &xca.alphabet, huf ); 99 | raw = huffman_raw ( sym, huf ); 100 | accum <<= huffman_len ( sym ); 101 | extra_bits -= huffman_len ( sym ); 102 | if ( extra_bits < 0 ) { 103 | accum |= ( XCA_GET16 ( src ) << ( -extra_bits ) ); 104 | extra_bits += 16; 105 | } 106 | 107 | /* Process symbol */ 108 | if ( raw < XCA_END_MARKER ) { 109 | 110 | /* Literal symbol - add to output stream */ 111 | if ( buf ) 112 | *(out++) = raw; 113 | out_len++; 114 | 115 | } else if ( ( raw == XCA_END_MARKER ) && 116 | ( src >= ( end - 1 ) ) ) { 117 | 118 | /* End marker symbol */ 119 | return out_len; 120 | 121 | } else { 122 | 123 | /* LZ77 match symbol */ 124 | raw -= XCA_END_MARKER; 125 | match_offset_bits = ( raw >> 4 ); 126 | match_len = ( raw & 0x0f ); 127 | if ( match_len == 0x0f ) { 128 | match_len = XCA_GET8 ( src ); 129 | if ( match_len == 0xff ) { 130 | match_len = XCA_GET16 ( src ); 131 | } else { 132 | match_len += 0x0f; 133 | } 134 | } 135 | match_len += 3; 136 | if ( match_offset_bits ) { 137 | match_offset = 138 | ( ( accum >> ( 32 - match_offset_bits )) 139 | + ( 1 << match_offset_bits ) ); 140 | } else { 141 | match_offset = 1; 142 | } 143 | accum <<= match_offset_bits; 144 | extra_bits -= match_offset_bits; 145 | if ( extra_bits < 0 ) { 146 | accum |= ( XCA_GET16 ( src ) << (-extra_bits) ); 147 | extra_bits += 16; 148 | } 149 | 150 | /* Copy data */ 151 | out_len += match_len; 152 | if ( buf ) { 153 | copy = ( out - match_offset ); 154 | while ( match_len-- ) 155 | *(out++) = *(copy++); 156 | } 157 | } 158 | } 159 | 160 | /* Allow for termination with no explicit end marker symbol */ 161 | if ( src == end ) 162 | return out_len; 163 | 164 | DBG ( "XCA input overrun at output length %#zx\n", out_len ); 165 | return -1; 166 | } 167 | -------------------------------------------------------------------------------- /wimldr/xca.h: -------------------------------------------------------------------------------- 1 | #ifndef _XCA_H 2 | #define _XCA_H 3 | 4 | /* 5 | * Copyright (C) 2012 Michael Brown . 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301, USA. 21 | */ 22 | 23 | /** 24 | * @file 25 | * 26 | * Xpress Compression Algorithm (MS-XCA) decompression 27 | * 28 | */ 29 | 30 | #include 31 | #include "huffman.h" 32 | 33 | /** Number of XCA codes */ 34 | #define XCA_CODES 512 35 | 36 | /** XCA decompressor */ 37 | struct xca { 38 | /** Huffman alphabet */ 39 | struct huffman_alphabet alphabet; 40 | /** Raw symbols 41 | * 42 | * Must immediately follow the Huffman alphabet. 43 | */ 44 | huffman_raw_symbol_t raw[XCA_CODES]; 45 | /** Code lengths */ 46 | uint8_t lengths[XCA_CODES]; 47 | }; 48 | 49 | /** XCA symbol Huffman lengths table */ 50 | struct xca_huf_len { 51 | /** Lengths of each symbol */ 52 | uint8_t nibbles[ XCA_CODES / 2 ]; 53 | } __attribute__ (( packed )); 54 | 55 | /** 56 | * Extract Huffman-coded length of a raw symbol 57 | * 58 | * @v lengths Huffman lengths table 59 | * @v symbol Raw symbol 60 | * @ret len Huffman-coded length 61 | */ 62 | static inline unsigned int xca_huf_len ( const struct xca_huf_len *lengths, 63 | unsigned int symbol ) { 64 | return ( ( ( lengths->nibbles[ symbol / 2 ] ) >> 65 | ( 4 * ( symbol % 2 ) ) ) & 0x0f ); 66 | } 67 | 68 | /** Get word from source data stream */ 69 | #define XCA_GET16( src ) ( { \ 70 | const uint16_t *src16 = src; \ 71 | src += sizeof ( *src16 ); \ 72 | *src16; } ) 73 | 74 | /** Get byte from source data stream */ 75 | #define XCA_GET8( src ) ( { \ 76 | const uint8_t *src8 = src; \ 77 | src += sizeof ( *src8 ); \ 78 | *src8; } ) 79 | 80 | /** XCA source data stream end marker */ 81 | #define XCA_END_MARKER 256 82 | 83 | /** XCA block size */ 84 | #define XCA_BLOCK_SIZE ( 64 * 1024 ) 85 | 86 | extern ssize_t xca_decompress ( const void *data, size_t len, void *buf ); 87 | 88 | #endif /* _XCA_H */ 89 | --------------------------------------------------------------------------------